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
2 changes: 2 additions & 0 deletions .claude/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ projects/
plans/

# Ways and CLAUDE.md ARE committed (shared team knowledge)
# ...but raw audit/scan byproducts dropped beside a way are local scratch
ways/**/*-raw.json
64 changes: 64 additions & 0 deletions .claude/ways/kg/documentation/way.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
pattern: doc.?catalog|di[aá]taxis|coverage matrix|frontmatter.*id|DD\.NNN|doclint|doc(s)?.*(graph|catalog)|reference page.*generat
files: docs/.*\.md$
commands: docs/scripts/(doc|doclint)
description: The docs/ tree is one typed graph — catalog frontmatter, DD.NNN.P ids, and the doclint CI gate (ADR-908)
vocabulary: documentation catalog diataxis frontmatter id domain mode doclint coverage matrix typed graph reference generated retired range
scope: agent, subagent
---
# KG Documentation Catalog Way

`docs/` is **one typed graph**, not a pile of files — pages and ADRs are nodes,
`related`/`supersedes` are edges. A page's type lives in **frontmatter**, enforced
by a linter; folders are a *view* for human readers. Decision: **ADR-908**. This
repo is the reference implementation that the agent-ways framework generalized into
its canonical documentation model (see ADR-908 → "Upstream").

## Catalog frontmatter

A `docs/` page joins the catalog **only** when it declares these — untagged prose
is ignored (opt-in):

```yaml
id: 04.001.H # DD.NNN.P (octet-style)
domain: auth # ADR-900 domain key — the shared first octet with ADRs
mode: how-to # Diátaxis: tutorial | how-to | reference | explanation
```

- **Identity is `DD.NNN`** — domain band + domain-scoped serial, assigned once,
never reused. The trailing **pole `P`** (`T`/`H`/`R`/`E`) is a *classifier* that
must agree with `mode:`, not part of the key. Re-classifying a page flips only
the pole; the number is untouched.
- **Mode is reader posture, not audience.** The four modes are a closed 2×2 — there
is no fifth. "Operations" is an audience facet carried by `domain`, never a mode.
- Domain bands mirror the ADR series (`01` infra · `02` db · `03` ingest ·
`04` auth · `05` query · `06` vocab · `07` ui · `08` ai · `09` meta).

## Tooling

| Command | Role |
|---------|------|
| `docs/scripts/doc coverage` / `gaps` / `list` | Diagnostic front-end — domain×mode matrix |
| `docs/scripts/doclint.py --check` | The **test** — CI gate, exit 1 on errors |

Both are **vendored copies** of the canonical agent-ways tools (copy-not-symlink);
re-vendor from canonical rather than editing in place. They share `adr.yaml`'s
domain config. Keep lint at **0 errors** — it enforces frontmatter validity,
resolvable edges, no supersede cycles, and the vacated-range guard.

## Gotchas

- **Generated reference pages** (`reference/{cli,mcp,fuse,schema}.md`) are
overwritten every build — their frontmatter is **emitted by the generator**
(`cli/scripts/*`), never hand-injected, or the next regen wipes it.
- **Retired-range guard is ON** (`legacy: {retired: true}`): no doc/ADR/source may
reference the vacated legacy range (ADR numbers 1–99). The scan honors `.gitignore`, so
gitignored corpora (e.g. `examples/.../claude-ai-history`) and scratch are
skipped. Raw audit/scan byproducts go to `*-raw.json` (gitignored), not committed.
- mkdocs strips unknown frontmatter, so catalog ids never reach readers — they are
maintainer/linter metadata only.

## See Also

- `.claude/ways/kg/adr/way.md` — ADR domain numbering (shares `adr.yaml`)
- ADR-908 — the decision; ADR-900 — the domain/numbering system
2 changes: 1 addition & 1 deletion cli/scripts/generate-mcp-docs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ async function main() {
// Documentation-catalog frontmatter (ADR-908). Emitted here, not hand-injected,
// because this page is overwritten on every docs build. domain=ui (MCP),
// mode=reference.
index.push('---\nid: 7.R.04\ndomain: ui\nmode: reference\n---\n');
index.push('---\nid: 07.007.R\ndomain: ui\nmode: reference\n---\n');
index.push('# MCP Server Tool Reference (Auto-Generated)\n');
index.push('> **Auto-Generated Documentation**');
index.push('> ');
Expand Down
2 changes: 1 addition & 1 deletion cli/scripts/simple-doc-gen.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ async function main() {
// Documentation-catalog frontmatter (ADR-908). Emitted here, not hand-injected,
// because this page is overwritten on every docs build. Stripped from GitHub
// Pages (mkdocs ignores unknown keys). domain=ui (CLI), mode=reference.
index.push('---\nid: 7.R.03\ndomain: ui\nmode: reference\n---\n');
index.push('---\nid: 07.004.R\ndomain: ui\nmode: reference\n---\n');
index.push('# CLI Command Reference (Auto-Generated)\n');
index.push('> **Auto-Generated Documentation**');
index.push('> ');
Expand Down
112 changes: 89 additions & 23 deletions docs/architecture/access-workflow/ADR-908-documentation-strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,52 @@ page drift apart, and a contributor never knows which one to edit. Audience is a
real lens, but it is the wrong axis for the directory structure.

We adopt **Diátaxis** as the organizing taxonomy instead. Each page has one
*mode* and serves one reader job:

| Mode | Folder | The page answers |
|------|--------|------------------|
| Tutorial | `get-started/` | "Walk me through my first success." |
| How-to | `how-to/` | "I have a goal; give me the steps." |
| Reference | `reference/` | "State the facts I look up." |
| Explanation | `explanation/` | "Help me understand why." |
| Operations | `self-host/` | "I run the platform; deploy and keep it healthy." |

`self-host/` is a fifth, operations-flavored section — Diátaxis-adjacent rather
than canonical — because running the appliance is a distinct, large reader job.
Architecture/ADRs remain a separate tree (the builder-pair audience) reachable
from their index.
*mode* — the reader's epistemic posture — and serves one reader job:

| Mode | The page answers |
|------|------------------|
| Tutorial | "Walk me through my first success." |
| How-to | "I have a goal; give me the steps." |
| Reference | "State the facts I look up." |
| Explanation | "Help me understand why." |

These four are not a list to extend — they are a closed 2×2 derived from two
orthogonal axes (*action* vs *cognition*, *acquisition* vs *application*).
Tutorial and How-to are action; Reference and Explanation are cognition.
Tutorial and Reference serve acquisition-adjacent and lookup needs; How-to and
Explanation serve the working reader. There is no fifth quadrant, because there
is no third axis. Mode is therefore the *highest* level of the catalog: it
classifies every page by reader posture alone, independent of subject.

**Folders are reader destinations, not modes.** The default site layout maps
one mode to one folder — `get-started/` (tutorial), `how-to/`, `reference/`,
`explanation/` — but a folder may hold several modes when it serves a coherent
*audience*. `self-host/` is exactly that: the operator's home, holding a
tutorial (`quick-start`), how-tos (`upgrading`, `tls`, `backup-restore`),
reference (`configuration`), and explanation (`security`, `production`).
"Operations" is an **audience facet**, not a mode — it answers *who reads this*
and *what subsystem* (deployment, networking, backup), which the catalog already
captures on the **domain** axis (`infra`, with the security model under `auth`).
It does not belong in the mode slot. Architecture/ADRs likewise remain a
separate tree (the builder-pair audience) reachable from their index.

> **Correction (2026-06-16).** The 2026-06-15 amendment first defined a fifth
> mode, `operations` (letter `O`), homed in `self-host/` — "Diátaxis-adjacent."
> That was a category error: it placed an *audience* label on the *mode* axis,
> which is reserved for reader posture. Operations content is never outside the
> four modes (it decomposes into a tutorial, how-tos, reference, and
> explanation), and its distinct-job-ness lives on the **domain** axis, which
> the `self-host/` pages already encode correctly (`infra`, plus `auth` for the
> security model). The mode vocabulary is now the canonical four (`T/H/R/E`);
> `O` is retired. The same correction reshapes the catalog id from
> `<digit>.<LETTER>.<serial>` to the octet-style `DD.NNN.P` defined below, so
> that mode (the mutable part) trails the identity instead of sitting inside it.
> **Migration:** re-tag the 11 `self-host/` pages to their true mode, drop
> `operations` from `doclint.py`'s `MODE_LETTER`, renumber every catalog id to
> `DD.NNN.P` with domain-scoped serials, and update the four reference-page
> generators (`cli`, `mcp`, `fuse`, `schema`) to emit the new ids. The
> `self-host/` folder and its nav are unaffected — it remains a multi-mode,
> audience-coherent destination.

The consolidation that applied this taxonomy is recorded in
`specs/documentation-consolidation-spec.md` (an intermediary spec, not an ADR):
Expand All @@ -62,21 +94,41 @@ part number that is invisible on the showroom floor:

```yaml
---
id: 4.R.01 # <domain-digit>.<MODE-letter>.<serial>
domain: auth # ADR-900 domain key — the shared "first octet"
mode: reference # Diátaxis: tutorial | how-to | reference | explanation | operations
id: 04.001.H # <DD domain band>.<NNN serial>.<diátaxis pole>
domain: auth # ADR-900 domain key — the shared "first octet"
mode: how-to # Diátaxis: tutorial | how-to | reference | explanation
---
```

- **domain** reuses the ADR-900 domain bands (1 infra · 2 db · 3 ingest ·
4 auth · 5 query · 6 vocab · 7 ui · 8 ai · 9 meta). A doc and the ADRs that
govern it share the leading digit, so "everything about auth" spans both trees.
- **mode** is the Diátaxis mode (letter `T` / `H` / `R` / `E` / `O` in the ID).
- **serial** is a 2-digit sequence within `(domain, mode)`.
The id is a fixed-width, octet-style number — `DD.NNN.P`:

- **domain band (`DD`)** — two digits, the ADR-900 band (`01` infra · `02` db ·
`03` ingest · `04` auth · `05` query · `06` vocab · `07` ui · `08` ai ·
`09` meta). A doc and the ADRs that govern it share the band, so "everything
about auth" spans both trees.
- **serial (`NNN`)** — a three-digit sequence **scoped to the domain**, not to
`(domain, mode)`. Assigned once at creation and never reused. `DD.NNN`
together is the page's immutable identity.
- **pole (`P`)** — the Diátaxis mode as a single trailing letter
(`T`/`H`/`R`/`E`). It is a *classifier*, not part of the identity; it must
agree with the `mode:` field, and the linter enforces that.

**Why the pole trails and the serial is domain-scoped.** The original scheme was
`<digit>.<LETTER>.<serial>` with the serial scoped to `(domain, mode)` — which
baked a *mutable* attribute into the *middle of the identity*. Re-classifying a
page then forced its part number to change: the 2026-06-16 correction below
re-shelved eleven `self-host/` pages and, under the old scheme, every one of
their ids would have churned. A handle that mutates when you re-shelve the part
is not a handle. Under `DD.NNN.P` the identity is `DD.NNN`; re-classifying flips
only the trailing pole (`…​.H` → `…​.E`) and the number is untouched. The pole
stays visible so the id self-documents, but it is a *view* of the `mode:` field,
never the key. Domain-scoped serials mean the linter can treat any id collision
as a real clash (`check_duplicate_ids`), since two pages in a domain can never
legitimately share a serial.

These keys are **management metadata, not display**. mkdocs ignores unknown
frontmatter keys, so the catalog is stripped from GitHub Pages — readers never
see `4.R.01`, maintainers and the linter do. Diátaxis stays a *principle* for
see `04.001.H`, maintainers and the linter do. Diátaxis stays a *principle* for
readers; the catalog is the *index* for maintainers. The two are facets of the
same page, not competing schemes.

Expand All @@ -101,6 +153,20 @@ references. It lints for:
Linting is **enforced on `docs/`** (errors fail CI) and **warns on ADRs** until
the ADR frontmatter sweep lands (tracked separately as the #520 fast-follow).

### Upstream: generalized into the agent-ways framework

This catalog — the typed doc+ADR graph, the `DD.NNN.P` id, the `doc`/`doclint`
tooling — was generalized out of this repo into the agent-ways framework as its
canonical *documentation model* (the framework's own `ADR-302`, unrelated to this
project's `ADR-302`). This repo is that model's **reference implementation**, and
`docs/scripts/{doc,doclint.py}` are **vendored copies** of the canonical tools
(copy-not-symlink, refreshed from canonical). That is why the vendored sources
cite `ADR-302` (the upstream model) and credit `ADR-908`/`ADR-900` (this repo's
local decisions) — the two numbers name two different things and both are correct.
The framework-side reference is prose only: do **not** add `ADR-302` to this ADR's
`related:` edges, since here that id resolves to the multimodal-ingestion ADR and
would be a false graph edge.

### Numbering freeze

Per ADR-900, legacy ADRs (1–99) are frozen at their numbers — we do not
Expand Down
1 change: 1 addition & 0 deletions docs/architecture/adr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ defaults:
legacy:
range: [1, 99]
label: "Retired (renumbered into domains 2026-06-15)"
retired: true # vacated range — doclint fails the build on any reference into 1–99

# Viewer command for `adr view`
# Use {file} as placeholder for the file path
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/docstring-coverage.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 9.H.01
id: 09.001.H
domain: meta
mode: how-to
---
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/test-suite.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 9.R.01
id: 09.002.R
domain: meta
mode: reference
---
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/voice.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 9.R.02
id: 09.003.R
domain: meta
mode: reference
---
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/computed-evidence.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 6.E.01
id: 06.001.E
domain: vocab
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/embedding-landscape.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 8.E.01
id: 08.001.E
domain: ai
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/graph-program.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 5.E.01
id: 05.001.E
domain: query
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/grounding.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 6.E.02
id: 06.002.E
domain: vocab
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/how-it-works.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 3.E.01
id: 03.001.E
domain: ingest
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/recursive-upsert.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 3.E.02
id: 03.002.E
domain: ingest
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/storage-and-freshness.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 2.E.01
id: 02.001.E
domain: db
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/vocabulary-lifecycle.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 6.E.03
id: 06.003.E
domain: vocab
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/explanation/worker-lanes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 1.E.01
id: 01.001.E
domain: infra
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/get-started/first-graph.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 3.T.01
id: 03.003.T
domain: ingest
mode: tutorial
---
Expand Down
2 changes: 1 addition & 1 deletion docs/get-started/first-query.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 5.T.01
id: 05.002.T
domain: query
mode: tutorial
---
Expand Down
2 changes: 1 addition & 1 deletion docs/get-started/github-history.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 3.T.02
id: 03.004.T
domain: ingest
mode: tutorial
---
Expand Down
2 changes: 1 addition & 1 deletion docs/get-started/mcp-quickstart.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 7.T.01
id: 07.001.T
domain: ui
mode: tutorial
---
Expand Down
2 changes: 1 addition & 1 deletion docs/get-started/what-and-why.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 9.E.01
id: 09.004.E
domain: meta
mode: explanation
---
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/ai-providers.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 8.H.01
id: 08.002.H
domain: ai
mode: how-to
---
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/embeddings.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 8.H.02
id: 08.003.H
domain: ai
mode: how-to
---
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/epistemic-status.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 6.H.01
id: 06.004.H
domain: vocab
mode: how-to
---
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/extraction-quality.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 8.H.03
id: 08.004.H
domain: ai
mode: how-to
---
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/fuse.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 7.H.01
id: 07.002.H
domain: ui
mode: how-to
---
Expand Down
2 changes: 1 addition & 1 deletion docs/how-to/ingest.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 3.H.01
id: 03.005.H
domain: ingest
mode: how-to
---
Expand Down
Loading
Loading