---
name: docs-todo-next
description: Process the next unchecked item from docs-todo.md at the repo root. Picks one item, verifies what the code actually does (not what the doc claims), drafts the new or updated page in the established voice, dispatches a reviewer to check the draft against code reality, then ticks the box. Use this whenever the user says "do the next docs todo", "next docs item", "update the docs to match reality", "advance docs-todo", or asks you to walk through docs-todo.md one item at a time. Trigger on any phrasing that asks for forward progress on the docs-todo list, even when the user does not name the file.
---

# docs-todo-next

A loop that turns one line of `docs-todo.md` into a documentation page that matches the code, reviewed and ticked.

## When this skill runs

The user wants to advance the docs todo list one item. The list lives at `docs-todo.md` in the repo root. Every entry is one of three kinds, and the workflow branches accordingly:

- **New page**: write the file and wire it into `docs/user/mkdocs.yml`.
- **Update**: open the existing page, find what is wrong against the code, rewrite the wrong parts.
- **Delete**: remove the file, remove its nav entry, remove redirects pointing at it.

## Step-by-step

### 1. Pick the next item

Read `/Users/yassin/Documents/projects/turbine-lsp/docs-todo.md`. Find the first `- [ ]` line, top to bottom. The "Missing sections to add" and "Sections to remove" blocks come before page-by-page review, which matches the user's preferred working order.

If every box is ticked, say so and stop.

Capture the audit hints from the parenthetical (for example `(NEEDS UPDATE: failed_rows/values_in missing from CHECK_CATALOG)`). Treat those hints as **leads to verify**, not as truth. The audit was a snapshot. The code is the source of truth.

### 2. Read the existing doc, if any

For an update or a delete, read the current file end to end. For a new page, skim the neighbouring pages it will sit beside in the nav so the new page lands in the same voice and depth.

### 3. Verify what the code actually does

Do not trust the doc. Do not trust the audit hint. Read the code.

For a typical page, that means:

- Use `grep -rn` on `src/turbine/` for every CLI flag, YAML field, class name, function name, and rule name the doc currently mentions or the new doc will mention.
- Read the relevant module top to bottom. Skimming misses the things that change between versions.
- Pay attention to:
  - Default values (the doc often lags behind the actual default).
  - Optional vs required (Pydantic models say so; trust the model).
  - Status enum values (e.g. `retired` vs `removed`, `active` vs `published`).
  - Lint rule names and severities (look in `core/contract/lint_rules.py`).
  - DSL field names: camelCase vs snake_case drift is common.
  - Whether claimed features actually exist. If the doc says "the owner is notified", grep for `notify`/`notification` and confirm. If nothing is wired up, the doc is selling a feature that does not exist; cut the claim.

If the code has moved on but the audit hint still points at the old file, follow imports and call sites to find where the logic lives now.

When in doubt about a feature's true behaviour, dispatch the `code-explorer` subagent with a tight question. Example: "Trace what happens when `turbine ci check` loads a QualitySpec whose target contract is retired. I need exact severity, exact diagnostic id, and the file:line where it's emitted."

### 4. Draft the page

Use the `writing-clearly-and-concisely` skill's principles. The voice this project has settled on is:

### Be Helpful
Guide users to success, don't just document features.

### Be Clear
Use simple words, short sentences, direct instructions.

### Be Friendly
Conversational but professional. Not robotic, not too casual.

### Be Confident
"Click Save" not "You might want to click Save"

### Be Respectful
Don't blame users for errors. "Something went wrong" not "You did something wrong"
- **Lead with the answer.** First paragraph is the one-line distinction or the punchline. A reader who quits after one paragraph should still know the headline.
- **Comparison table near the top.** When the page contrasts two things, put the table within the first screen so skimmers find it.
- **Plain language over jargon.** Internal terms like "linter", "telemetry source label", "cross-contract rule", "DSL" are fine inside the implementation, but in user docs prefer "validation", "shows up in dashboards as", "rules that check the relationship", "the YAML format". Keep domain terms (contract, schema, primary key, dimension); drop tool internals.
- **Hide the implementation; show the experience.** The reader is here to *use* the feature, not to learn how it's built. Do not name the JSON schema, the Pydantic model, the parser, the StrEnum, the specific lint rule code, the diagnostic id, the sentinel value, or the file:line that enforces something. Collapse all of that into what the user *sees*: "validation catches it", "the contract fails to load", "the CLI prints an error". Lint rule names are OK to mention once if the reader needs to grep for the diagnostic in their output, but never as a list of mechanisms ("the JSON schema enforces X, the lint rule does Y, the parser does Z"). Three sentences of plumbing become one sentence of behaviour.
- **Two-tier layout for technical content.** When a page has unavoidable depth (full column tables, every field of a config struct, every status enum, dialect quirks, migration mechanics), do not dump it inline. The top of the page must read end-to-end for someone who is *not* implementing against it: prose, a diagram, and a one-line-each summary table. Push the column-by-column breakdowns and the "if you are debugging the writer" notes into mkdocs material collapsibles using `??? note "Section name"`. A reader who only wants the mental model can skim past; a reader who needs the rows can expand them. Use this layout especially on Concepts pages, where the audience is mixed.
- **Diagrams over wall-of-prose for relationships.** Whenever a page describes objects that point at each other (database tables with FKs, components that exchange messages, lifecycle states), draw the picture. The docs site renders d2 — use ` ```d2 ` blocks with the project's `{{ d2_classes }}` macro and `{{ d2_edge }}` for arrows so the diagram inherits the dark-mode theme already configured in `mkdocs.yml` (`d2.dark_theme: -1`). For schema diagrams, use d2's `sql_table` shape (see `concepts/row-flagging.md` for an example). Do not reach for mermaid; the rest of the docs site is d2 and a stray mermaid block stands out. Mermaid is only acceptable if d2 genuinely cannot express what you need.
- **Concrete examples in YAML block style.** Never inline flow style (`{key: value, key: value}`). Always indented blocks.
- **No em-dashes.** Use commas, periods, or colons. The repo convention is strict.
- **No agreement theater, no puffery.** No "groundbreaking", "seamless", "powerful", "the whole point", "stands as a testament". Say what the thing does and stop.
- **Explain, don't sell.** If a sentence reads like marketing, cut it. If a sentence motivates a feature with pain ("Tired of brittle SQL tests?"), cut it.
- **Reflect reality, even when it contradicts the existing doc.** If the existing page claims notifications, gates, or scoring behaviour the code does not implement, do not perpetuate it. Document the actual behaviour, and if the gap matters, mention it briefly without dressing it up.
- **Short topic sentences. Short paragraphs. Lists when items are parallel.** Avoid the rule of three for its own sake.
- **Active voice. Positive form. Definite, specific words.** Strunk's basics; the writing-clearly skill has the long version.

Page skeleton that has been working:

1. One-paragraph lead with the answer.
2. "At a glance" table (only if the page is comparative or has a fixed set of slots).
3. A diagram, if the page describes things that relate to each other (tables with FKs, lifecycle states, components calling each other). Use d2 with `{{ d2_classes }}`.
4. The next thing the reader will want, usually "When to use which" or "What it looks like".
5. Mechanics last: lint differences, runtime behaviour, edge cases. If any single section turns into a wide column table or a list of dialect quirks, push it into a `??? note "..."` collapsible so it does not break the reading flow above.
6. "See also" cards block at the bottom, linking to neighbours.

If the page exists already, prefer rewriting wrong sections in place over a top-down rewrite. The audit may have flagged three lines; a full rewrite throws away accurate prose.

### 5. Wire up the nav (new page) or remove it (delete)

For a **new page**, edit `docs/user/mkdocs.yml` and add the entry under the right section. The order in the nav usually matches the doc's intended position in a learning sequence; ask if unsure.

For a **delete**, remove the nav entry, remove any redirects in `mkdocs.yml`'s `redirect_maps` pointing at the deleted file, and check there are no internal links to it (`grep -rn 'reference/comparison'` or similar). Fix or drop any orphaned links.

### 6. Dispatch the reviewer

Spawn a subagent to verify the draft against the code. Use the `general-purpose` agent (the `spec-reviewer` agent is for code-vs-spec compliance, not docs-vs-code; this is the closest fit for verification work).

Reviewer prompt template:

```
Verify that the documentation page at <path> accurately describes the
behaviour of <feature> in this codebase.

What I changed/wrote: <one-paragraph summary>.

Read the page, then read the actual implementation in <list of files
you checked in step 3>. For every factual claim in the page (CLI flags,
YAML field names, default values, error severities, runtime behaviour,
lint rule names), confirm it against the code or flag it as wrong.

Also flag:
- Claims of features that do not exist in code.
- Stale terminology (renamed enums, fields, modules).
- YAML examples that would not parse against the current Pydantic models.

Report findings as a numbered list. For each finding give: the line in
the doc, what it claims, what the code actually does, and the file:line
that proves it. Do not rewrite the doc; just report. Under 400 words.
```

### 7. Apply the fixes

Read the reviewer's findings. For each one:

- If the finding is correct, fix the doc.
- If the finding is wrong (rare, but happens when the reviewer reads stale code in another worktree), say so and move on.

Do **not** silently accept findings without checking. Reviewers occasionally over-correct.

### 8. Tick the box

Edit `docs-todo.md`. Change the `- [ ]` for this item to `- [x]`. Do not change other lines.

### 9. Report back

Tell the user:

- Which item you took.
- Whether it was a new page, update, or delete.
- The 2–4 most material reality-vs-doc gaps you closed (skip trivial typos).
- The path of the file you wrote, so they can open it.
- That the box is ticked.

Stop there. Do not auto-advance to the next item; the user decides when to run again.

## Things that have tripped this workflow before

- **Following audit hints blindly.** The audit was made on a date; some hints are no longer accurate. Always re-verify.
- **Carrying over salesy phrasing from the old doc.** If the previous page said "ensures rock-solid quality across your entire data platform", do not preserve that voice for continuity. Rewrite it plain.
- **Adding em-dashes back in.** They sneak in via copy-paste from the old doc. Grep the final file for `—` and remove every one before committing.
- **Restating schema in QualitySpec docs (or similar).** Specs inherit from the contract; do not re-document the schema in two places.
- **Listing internal mechanisms when one user-facing sentence will do.** A draft that reads "the JSON schema enforces the enum, the `check-dimension-required` lint rule errors out when missing, and the parser rejects unknown names" leaks three implementation details the reader does not care about. Replace with "validation catches it" or "the contract fails to load". The reader wants to know what they will experience, not which layer caught them. Same for sentinel keys, parser fallbacks, and "shouted about it" asides about lint behaviour — they're plumbing, not user surface.
- **Dumping every column inline.** A schema page with five tables, each with eight to ten columns, becomes a wall of grids that drowns the prose. Lead with the mental model (what each table is *for*, in one line) and a diagram, then collapse the per-column tables into `??? note "<table name>"` blocks. A reader who only needs the diagram never has to scroll past the schema; a reader who needs the columns expands them. This applies whenever a page would otherwise carry more than one wide reference table.
- **Editing the changelog.** This skill does not touch `CHANGELOG.md`. If the user wants a changelog line, that is a separate ask.

## What this skill does not do

- It does not commit or push. The user runs `/commit` when they're ready.
- It does not run the docs build. If the user wants a preview, they run `mkdocs serve --livereload` themselves.
- It does not advance to the next item automatically.
