Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
160 commits
Select commit Hold shift + click to select a range
889600e
chore: add doc overhaul brief with challenge findings for #928
NodeJSmith Jun 1, 2026
3d31084
feat: add task files for 070-doc-overhaul
NodeJSmith Jun 1, 2026
2f52337
chore: apply reviewer suggestions to task files
NodeJSmith Jun 1, 2026
ffb09a0
chore: add design doc, fix review findings across task files
NodeJSmith Jun 1, 2026
c0b39f6
docs: T01 site outline and T03 exemplar pages for doc overhaul
NodeJSmith Jun 1, 2026
d7a7f1b
chore: update T12 scope with troubleshooting→Operating content split
NodeJSmith Jun 1, 2026
28ce6aa
chore: T04 — per-page content outlines, knowledge inventory, and snip…
NodeJSmith Jun 1, 2026
2aa25e8
chore: home page outline — require snippet files for all code examples
NodeJSmith Jun 1, 2026
eb6865c
chore: move depends_on/wave content from Architecture to Internals ou…
NodeJSmith Jun 1, 2026
980034d
fix: remove references to non-existent on_ready lifecycle hook
NodeJSmith Jun 1, 2026
cb63af5
fix: apps overview outline — @only_app decorator, not --app flag
NodeJSmith Jun 1, 2026
b514d0d
chore: apps overview outline — link to all five handle pages in Next …
NodeJSmith Jun 1, 2026
0aacdba
fix: task-bucket outline — make_async_adapter, not normalize_callable
NodeJSmith Jun 1, 2026
5d29f32
fix: correct 20+ hallucinated identifiers across outline files
NodeJSmith Jun 1, 2026
f261c90
fix: docker-setup outline — hot reload is file_watcher.watch_files, n…
NodeJSmith Jun 1, 2026
df07792
chore: drop Execution Columns section from database-telemetry outline
NodeJSmith Jun 1, 2026
efe4e1d
chore: database-telemetry outline — add logs, dropped events, CLI equ…
NodeJSmith Jun 1, 2026
eb01d40
chore: drop sessions from database-telemetry outline — internal detail
NodeJSmith Jun 1, 2026
1d5e113
chore: split System Internals into 3 pages with proper outlines and s…
NodeJSmith Jun 1, 2026
512eeac
fix: apps overview — AppSync not SyncApp, framed for sync library com…
NodeJSmith Jun 1, 2026
fb4ea56
chore: remove deferred Automatic Type Conversion section from custom-…
NodeJSmith Jun 1, 2026
3649dcc
fix: predicate composition is AllOf/AnyOf, not &/| operators
NodeJSmith Jun 1, 2026
1623c98
fix: add Accessors (A) reference to filtering page alongside P and C
NodeJSmith Jun 1, 2026
05c13f7
chore: fix outline inaccuracies from source verification sweep
NodeJSmith Jun 1, 2026
0f20b05
chore: fix subtler outline inaccuracies from second verification pass
NodeJSmith Jun 1, 2026
8307211
chore: redistribute scheduler outline content to align with bus struc…
NodeJSmith Jun 1, 2026
2b68d5a
chore: expand api/entities outline with entity vs state vs value dist…
NodeJSmith Jun 1, 2026
5bedba8
chore: fix api/entities terminology to match existing docs
NodeJSmith Jun 1, 2026
053cf34
chore: restructure configuration section — 4 pages → 2 pages
NodeJSmith Jun 1, 2026
a735218
chore: address outline review feedback — trim, rename, restructure
NodeJSmith Jun 1, 2026
06c9639
chore: coverage sweep and structural challenge on doc outlines
NodeJSmith Jun 2, 2026
dbeb7ff
chore: outline audit — fix nav structure, kill rotting pages, resolve…
NodeJSmith Jun 2, 2026
d426908
chore: mark T01, T03, T04 as done
NodeJSmith Jun 2, 2026
9061896
chore: update task files T06-T12 to reflect outline audit decisions
NodeJSmith Jun 2, 2026
a0ac2ff
chore: add muffet link checker and snippet orphan check to docs CI (T02)
NodeJSmith Jun 2, 2026
b4da387
chore: mark T02 as done
NodeJSmith Jun 2, 2026
f5cb026
chore: scope pyright suppressions per-directory in docs config
NodeJSmith Jun 2, 2026
8f978ff
chore: add writing prompt template and voice checklist updates from eval
NodeJSmith Jun 2, 2026
5931ee3
docs: rewrite Getting Started section from blank
NodeJSmith Jun 2, 2026
a2c0d08
docs: rewrite Docker getting-started pages with JTBD outlines
NodeJSmith Jun 2, 2026
162be32
docs: redesign all outlines with JTBD framework
NodeJSmith Jun 2, 2026
bdc214a
docs: rewrite Apps section (overview, lifecycle, task-bucket)
NodeJSmith Jun 2, 2026
dad7dec
docs: rewrite Bus section (6 pages)
NodeJSmith Jun 2, 2026
7f9febe
docs: rewrite Architecture, Internals, Database-Telemetry (T07 complete)
NodeJSmith Jun 2, 2026
88bf2a2
docs: rewrite Scheduler section (overview, methods, management)
NodeJSmith Jun 2, 2026
92d56cf
docs: rewrite States section (overview, subscribing, custom, registries)
NodeJSmith Jun 2, 2026
53b5e5e
docs: rewrite API section (overview, entities, services, utilities, h…
NodeJSmith Jun 2, 2026
31b7460
docs: rewrite Cache + Configuration sections (T08 complete)
NodeJSmith Jun 2, 2026
65d78bd
docs: rewrite Web UI section (5 task-oriented pages)
NodeJSmith Jun 3, 2026
51ae45b
docs: rewrite CLI section (4 pages)
NodeJSmith Jun 3, 2026
778416e
docs: rewrite Testing section (5 pages)
NodeJSmith Jun 3, 2026
11abe20
docs: rewrite Recipes section (6 pages, motion-lights exemplar unchan…
NodeJSmith Jun 3, 2026
62afb28
docs: rewrite Migration section (8 pages including checklist)
NodeJSmith Jun 3, 2026
d198b75
docs: rewrite Troubleshooting and Operating sections (4 pages)
NodeJSmith Jun 3, 2026
2cb2b7c
fix: resolve broken links and pyright error in docs
NodeJSmith Jun 3, 2026
019b92a
refactor(testing): make drain_task_bucket public
NodeJSmith Jun 3, 2026
42cc5d5
fix(docs): address PR review comments and broken links
NodeJSmith Jun 3, 2026
7acbfb4
fix(docs): add explicit anchor for --since-format heading
NodeJSmith Jun 3, 2026
f92e274
chore(docs): delete orphaned pages and snippets
NodeJSmith Jun 3, 2026
0dc323a
fix(docs): fix broken internals.md anchor for muffet
NodeJSmith Jun 3, 2026
794b624
fix(docs): use docker compose pull instead of explicit image tag
NodeJSmith Jun 3, 2026
2f6cd04
chore(docs): delete orphaned internals.md, enable muffet gate
NodeJSmith Jun 3, 2026
1002fa8
chore(docs): redirect orphaned pages to new locations and delete
NodeJSmith Jun 3, 2026
a56e356
fix(docs): restore moved snippets and add checklist to nav
NodeJSmith Jun 3, 2026
6c1a49a
docs: T13 final sweep — cross-links, term definitions, voice fixes
NodeJSmith Jun 3, 2026
3d6f3c2
docs: add mkdocstrings cross-references for key classes
NodeJSmith Jun 3, 2026
620ad76
docs: add 130 mkdocstrings cross-references across 40 pages
NodeJSmith Jun 3, 2026
b4e6e32
docs: add backticks to 120 bare public symbol mentions
NodeJSmith Jun 3, 2026
9295dcf
fix(docs): strip backticks from mkdocstrings reference paths
NodeJSmith Jun 3, 2026
e59dbfe
docs: wire screenshots into web UI pages
NodeJSmith Jun 3, 2026
b33999a
chore: remove unused web UI screenshots
NodeJSmith Jun 3, 2026
4835bcb
chore: save doc-overhaul skill and update followups
NodeJSmith Jun 3, 2026
73fd143
chore: archive doc-overhaul spec — delete outlines and tasks
NodeJSmith Jun 3, 2026
544a4c9
chore: add reference files to doc-overhaul skill
NodeJSmith Jun 3, 2026
3a76dc8
fix: address all review findings on doc-overhaul skill
NodeJSmith Jun 3, 2026
fbcf506
fix: restore Opus for doc reviewer subagent
NodeJSmith Jun 3, 2026
e3affa6
chore: add prior art brief (Diataxis + JTBD) to skill references
NodeJSmith Jun 3, 2026
2c9c8af
feat: generalize doc-overhaul into scale-aware docs skill
NodeJSmith Jun 3, 2026
753b50d
chore: remove stale handoff and followups files
NodeJSmith Jun 3, 2026
25acc93
chore: remove duplicated spec files and stale lock file
NodeJSmith Jun 3, 2026
ed79984
docs: fix migration pitfalls, trim architecture page, remove backtick…
NodeJSmith Jun 3, 2026
d7e56f9
fix(docs): strip hassette prefix from API reference nav entries
NodeJSmith Jun 3, 2026
b03743d
docs: link API reference jump-to-section entries to generated pages
NodeJSmith Jun 3, 2026
ba756e7
docs: remove redundant bus flowchart from concept page
NodeJSmith Jun 3, 2026
f855eaa
docs: remove redundant flowcharts from apps and api concept pages
NodeJSmith Jun 3, 2026
8e4d078
docs: fix broken HassetteConfig cross-references, remove execution co…
NodeJSmith Jun 3, 2026
a05a510
docs: move application configuration page from Configuration to Apps …
NodeJSmith Jun 3, 2026
59b4337
docs: move Filtering & Predicates after Writing Handlers, clarify raw…
NodeJSmith Jun 3, 2026
0d27bbc
docs: add Subscription Methods reference page for bus
NodeJSmith Jun 3, 2026
c69d657
docs: replace bus index method table with link to methods.md
NodeJSmith Jun 3, 2026
063b05e
docs: follow-up fixes for bus docs restructure
NodeJSmith Jun 3, 2026
858912e
docs: widen content grid and make tables full-width
NodeJSmith Jun 3, 2026
637d3af
docs: extract custom triggers to dedicated scheduler page
NodeJSmith Jun 3, 2026
e2b6e80
docs: center mermaid diagram and remove domain-to-class table on stat…
NodeJSmith Jun 3, 2026
c6da3e8
docs: remove Subscribing to State Changes page
NodeJSmith Jun 3, 2026
aa261da
docs: restructure API and States sections around JTBD
NodeJSmith Jun 4, 2026
046fad7
docs: split combined method headings in API methods page
NodeJSmith Jun 4, 2026
18f3432
docs: consolidate API synchronous-usage into a single section
NodeJSmith Jun 4, 2026
cab518b
docs: restructure scheduler pages around jobs-to-be-done
NodeJSmith Jun 4, 2026
824fa90
chore: skip headings in bare-symbol docs checker
NodeJSmith Jun 4, 2026
bf460ba
docs: align health-endpoints page with JTBD conventions
NodeJSmith Jun 7, 2026
1252473
doc
NodeJSmith Jun 8, 2026
b564867
docs: extract inline snippets and fix voice violations
NodeJSmith Jun 8, 2026
5a29539
docs: add missing scaffolding to 6 concept pages
NodeJSmith Jun 8, 2026
37d0751
docs: add scaffolding and fix voice in 4 remaining pages
NodeJSmith Jun 8, 2026
bb4e562
docs: rename scheduler sync section for consistency
NodeJSmith Jun 8, 2026
45543e3
docs: fix /ui/ URLs and widen content grid to 1600px
NodeJSmith Jun 8, 2026
c1a5c78
chore: add doc voice audit script
NodeJSmith Jun 8, 2026
d9dc1d9
docs: extract inline code to snippets, remove internals sections
NodeJSmith Jun 8, 2026
1ced01c
docs: fix all voice audit findings across 29 pages
NodeJSmith Jun 8, 2026
e2add44
chore: add doc persona review skill and prior art research
NodeJSmith Jun 9, 2026
0ca757d
chore: add persona review findings for getting-started section
NodeJSmith Jun 9, 2026
6078db5
docs: fix getting-started followability from persona review
NodeJSmith Jun 9, 2026
1c78d23
docs: fix Developer Tools navigation path
NodeJSmith Jun 9, 2026
7509fb2
docs: fix remaining 24 persona review findings across getting-started
NodeJSmith Jun 9, 2026
4fea9f7
docs: persona audit fixes for apps and bus sections
NodeJSmith Jun 9, 2026
312002d
docs: persona audit fixes for scheduler section
NodeJSmith Jun 9, 2026
0ca5853
docs: collapse sync facade sections into collapsible admonitions
NodeJSmith Jun 9, 2026
597eb66
docs: remove duplicate sync admonition from bus methods page
NodeJSmith Jun 9, 2026
7eba785
docs: persona audit fixes for states section
NodeJSmith Jun 9, 2026
c8a358a
docs: persona audit fixes for api section
NodeJSmith Jun 9, 2026
40362f0
fix: rewrite doc page extractor for correct HTML extraction
NodeJSmith Jun 9, 2026
b70b749
docs: improve cache section clarity from persona audit
NodeJSmith Jun 9, 2026
a297751
fix: preserve hyperlinks in doc extraction for persona reviewers
NodeJSmith Jun 9, 2026
b401c57
docs: improve database, configuration, and internals sections from pe…
NodeJSmith Jun 9, 2026
614c500
docs: fix cross-cutting issues in recipes from persona audit
NodeJSmith Jun 9, 2026
b33f1d8
docs: improve testing section from persona audit
NodeJSmith Jun 9, 2026
1901096
docs: improve CLI section from persona audit
NodeJSmith Jun 9, 2026
0b198f2
docs: improve operating, web-ui, and migration sections from persona …
NodeJSmith Jun 9, 2026
0992e92
docs: improve core-concepts pages from persona audit findings
NodeJSmith Jun 9, 2026
9ebe928
docs: fix persona audit findings across remaining sections
NodeJSmith Jun 9, 2026
f8922cc
docs: fix web-ui, operating, and troubleshooting from persona audits
NodeJSmith Jun 9, 2026
83927c9
chore: move docs-related scripts to tools/docs/ subdirectory
NodeJSmith Jun 9, 2026
9625877
chore: move CSS guard scripts to tools/frontend/ subdirectory
NodeJSmith Jun 9, 2026
a0895fe
chore: move check_breakpoint_drift to tools/frontend/
NodeJSmith Jun 9, 2026
faa7d6b
chore: move release verification scripts to tools/release/
NodeJSmith Jun 9, 2026
c7ac1b3
chore: move generate_constraints to scripts/, remove dead one-offs, a…
NodeJSmith Jun 9, 2026
899b70d
ignore check that fires on TextMode string enum
NodeJSmith Jun 9, 2026
a407d7d
formatting
NodeJSmith Jun 10, 2026
f5523ff
chore: add doc-accuracy-review skill for verifying docs against source
NodeJSmith Jun 10, 2026
55dd215
fix(scheduler): correct misleading if_past docs, log message, and sta…
NodeJSmith Jun 10, 2026
f13fa62
test: exclude e2e from default pytest addopts to protect ad-hoc runs
NodeJSmith Jun 10, 2026
ec15904
docs: persona audit fixes for docker setup pages
NodeJSmith Jun 10, 2026
3bdb267
docs: persona audit fixes for recipe pages — add Run It registration …
NodeJSmith Jun 10, 2026
9e6b796
docs: persona audit fixes for CLI pages
NodeJSmith Jun 10, 2026
b656d47
docs: persona audit fixes for migration pages — async callouts, canon…
NodeJSmith Jun 10, 2026
eeeb762
docs: persona audit fixes for core-concepts remainder; fix run_every …
NodeJSmith Jun 10, 2026
9ad85f2
docs: persona audit fixes for time-control, inspect-config-code, log-…
NodeJSmith Jun 10, 2026
9342051
test: add failing regression tests for get_state_or_none/get_entity_o…
NodeJSmith Jun 11, 2026
1ade415
fix(api): catch EntityNotFoundError in get_state_or_none and get_enti…
NodeJSmith Jun 11, 2026
f3f0393
docs: fix inaccuracies found by accuracy audit (cli through web-ui in…
NodeJSmith Jun 11, 2026
f2909a8
docs: fix web-ui accuracy findings; add doc-coverage-review skill
NodeJSmith Jun 11, 2026
8fa2b8a
chore: add per-area prompts REFERENCE.md for doc-coverage-review skill
NodeJSmith Jun 11, 2026
7ce5a95
docs: fill coverage gaps found by doc-coverage-review across all ten …
NodeJSmith Jun 11, 2026
35c3adf
docs: fix readability regressions in coverage-gap content flagged by …
NodeJSmith Jun 11, 2026
efc50d8
docs: add silent-failure warnings and reader orientation from persona…
NodeJSmith Jun 11, 2026
8fdb4a2
chore(docs): replace inline pyright ignores with scoped config suppre…
NodeJSmith Jun 11, 2026
c120388
docs: address persona walkthrough findings on the four weakest pages
NodeJSmith Jun 11, 2026
33792fe
docs: name the silent await-omission failure in the migration mental …
NodeJSmith Jun 11, 2026
bdfbae8
docs: add async basics primer for AppDaemon migrators
NodeJSmith Jun 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 6 additions & 4 deletions .claude/rules/doc-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Hassette docs should feel like a patient friend who's already built the thing yo
### Voice rules

1. **Use "you" and "your" in getting-started and recipe procedure sections.** In concept and API reference pages, make the system the subject instead — see voice-guide.md rule #10.
2. **Lead with what it does, not what it is.** "The scheduler lets you run functions at specific times" not "The scheduler is a service that manages timed execution of callable objects."
2. **Lead with what it does, not what it is.** Every first mention of a Hassette term (`App`, `Bus`, `Scheduler`, `Api`, `StateManager`, `AppConfig`) must define it by function, not by category. "The scheduler runs functions at specific times" not "The scheduler is a service that manages timed execution." "`AppConfig` loads and validates settings from `hassette.toml`" not "`AppConfig` is a Pydantic settings model." The category is invisible to the reader; the function is what they need.
3. **Use concrete examples in prose, not just code blocks.** "like temperature sensors that report every 2 seconds" not "such as high-frequency update sources."
4. **Short sentences for concepts, longer ones for flow.** Introduce an idea in one punchy line. Then explain how it works in a sentence or two that builds on the first.
5. **Active voice.** "Hassette connects to Home Assistant" not "a connection is established." Passive voice makes prose feel distant and academic.
Expand Down Expand Up @@ -73,8 +73,9 @@ The voice and approachability rules above are hard requirements. The structures
1. **Problem statement** — one paragraph describing the real-world situation. Use a concrete example ("Your motion sensor fires every time a cat walks by").
2. **The Code** — a full, runnable app with config. This is the main attraction.
3. **How it works** — walk through the code, explaining each decision. Call out the Hassette features being used and link to their concept pages.
4. **Variations** — alternative approaches or tweaks for different scenarios.
5. **See also** — links to concept pages for the features used, and related recipes.
4. **Verify it's working** — a concrete verification step: a CLI command (`hassette log --app <key>`) or web UI action (Handlers tab) the reader runs to confirm the automation fires. Show expected output.
5. **Variations** — alternative approaches or tweaks for different scenarios.
6. **See also** — links to concept pages for the features used, and related recipes.

### Getting-started pages

Expand All @@ -87,7 +88,7 @@ The voice and approachability rules above are hard requirements. The structures

API reference is auto-generated by mkdocstrings from docstrings. When adding a new public module or class:

- Add it to the `PUBLIC_MODULES` allowlist in `tools/gen_ref_pages.py`
- Add it to the `PUBLIC_MODULES` allowlist in `tools/docs/gen_ref_pages.py`
- Write clear docstrings on the class and its public methods (one-liner summary, parameter descriptions via type hints, usage example if the method is non-obvious)
- Don't duplicate reference content in concept pages — link to it instead

Expand Down Expand Up @@ -143,6 +144,7 @@ This way minimal fragments are slices of tested files, not standalone untested c
- **Show the outcome.** After a code block, briefly say what happens when it runs. "When the sensor crosses 75°F, the handler fires and turns on the fan." The reader should be able to predict behavior before running it.
- **One concept per example.** An example that demonstrates debouncing should not also introduce conditions, predicates, and dependency injection. Layer concepts across examples, not within them.
- **Real entity names.** Use `light.kitchen`, `sensor.outdoor_temperature`, `binary_sensor.front_door` — not `entity.my_entity` or `sensor.test_sensor`. Real names help readers map to their own setup.
- **Keep lines under 80 characters.** The docs content area is narrow — long lines force horizontal scrolling, which makes code hard to read. Break function signatures across multiple lines, use short variable names, and extract intermediate values. If a line is too long for the rendered page, it's too long for the snippet.

## Layering for Skill Levels

Expand Down
1 change: 0 additions & 1 deletion .claude/scheduled_tasks.lock

This file was deleted.

140 changes: 140 additions & 0 deletions .claude/skills/doc-accuracy-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Doc Accuracy Review

Verify documentation pages against the actual source code. Each verification subagent reads one page, inventories its checkable claims (signatures, defaults, behaviors, exceptions, config keys, CLI flags), and confirms or refutes each one against `src/hassette/`.

Sibling of `doc-persona-review`: that skill tests whether a page is *followable*; this one tests whether it is *true*. Snippets are Pyright-checked in CI, but nothing guards prose claims — they drift silently after every `src/` change.

## Arguments

The page or section to verify. Examples:
- `core-concepts/bus` (verifies all pages in the section)
- `core-concepts/scheduler/methods`
- `cli` (verifies all CLI pages)

If empty, ask what to verify.

## Phase 1: Resolve Pages

If the argument is a section, expand to all pages in that directory (excluding `snippets/`). If it's a single page, use that page.

No persona selection — every page gets the same verification treatment.

## Phase 2: Extract and Assemble

Two scripts handle all file preparation. Run them, don't read their output. Do NOT read the page content or briefing files yourself — the heavy content belongs only in subagent contexts.

### Step 1: Get a tmp directory

```bash
get-skill-tmpdir doc-accuracy-review
```

Use the printed path as `$TMPDIR` below.

### Step 2: Build docs and extract pages

```bash
uv run mkdocs build --strict
uv run tools/docs/extract_doc_page.py --section <section> --output-dir $TMPDIR/pages
# or for a single page:
uv run tools/docs/extract_doc_page.py <page> --output-dir $TMPDIR/pages
```

### Step 3: Assemble briefing files

One command per page (no persona argument — the template is fixed):

```bash
uv run tools/docs/assemble_accuracy_briefing.py $TMPDIR/pages/<page-slug>.txt $TMPDIR/briefings
```

Chain with `&&` for multi-page sections. Each briefing lands at `$TMPDIR/briefings/accuracy--<page-slug>.md`.

## Phase 3: Dispatch Verification Agents

For each briefing file, dispatch a **Sonnet** subagent with this prompt:

```
Read the file at {briefing_path} and follow the instructions inside. You have full read access to the repository — verify claims against the source code in src/hassette/. Return the JSON result exactly as specified.
```

Unlike persona walkthroughs, these agents actively explore the repo (Read, Grep, Glob), so they run longer per page. Cap at 5 concurrent subagents.

Use `schema` on the agent call to enforce the JSON structure:

```json
{
"type": "object",
"properties": {
"page": {"type": "string"},
"claims_checked": {"type": "integer"},
"findings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"line": {"type": "integer"},
"claim_type": {"type": "string", "enum": ["api-signature", "default-value", "behavior", "exception", "config", "cli", "import-path", "version", "file-path"]},
"verdict": {"type": "string", "enum": ["WRONG", "OUTDATED_API", "UNVERIFIABLE"]},
"severity": {"type": "string", "enum": ["high", "low"]},
"doc_quote": {"type": "string"},
"code_evidence": {"type": "string"},
"explanation": {"type": "string"},
"suggested_fix": {"type": "string"}
},
"required": ["line", "claim_type", "verdict", "severity", "doc_quote", "code_evidence", "explanation", "suggested_fix"]
}
},
"summary": {"type": "string"}
},
"required": ["page", "claims_checked", "findings", "summary"]
}
```

## Phase 4: Triage and Present

### Triage before trusting

Verification agents make mistakes in both directions, and for accuracy work a wrong "fix" is worse than the original error — it makes a true sentence false. Before presenting or fixing anything:

1. For each `WRONG` and `OUTDATED_API` finding, open the cited `code_evidence` location and confirm the contradiction is real and that the cited code is the code path the page describes.
2. Findings with no usable code citation are discarded.
3. `UNVERIFIABLE` findings get a quick independent grep — agents sometimes miss a symbol that one targeted search finds. If you find it and the claim holds, drop the finding; if you find it and the claim is false, upgrade to `WRONG`.

### Sanity-check coverage

A page with `claims_checked: 3` that plainly contains dozens of API references got a lazy pass — re-dispatch it. Use judgment, not a fixed threshold: reference-heavy pages (methods, triggers, predicate tables) should report high counts; conceptual index pages legitimately report low ones.

### Output format

Group confirmed findings by page, worst first (`high` severity, then `WRONG` before `OUTDATED_API` before `UNVERIFIABLE`):

```
## page-name.md — N findings (M claims checked)

- **[verdict / claim_type / severity]** L{line}: "{doc_quote}"
Code: {code_evidence}
{explanation}
Fix: {suggested_fix}
```

End with a summary table:

| Page | Claims checked | WRONG | OUTDATED_API | UNVERIFIABLE |
|------|----------------|-------|--------------|--------------|

Pages with zero findings appear in the table only — that's the success case, not a gap.

### Fixing

When the user asks for fixes (or pre-authorized auto-fixing), edit the markdown source in `docs/pages/`, not the rendered output. After fixes, run `uv run mkdocs build --strict` to verify the build. If a fix changes a snippet file, re-run Pyright on snippets per the docs CI.

## Design Decisions

**Why a separate skill from doc-persona-review?** Opposite stances toward the repo. The persona reviewer is deliberately blind — it must not know more than the persona does. The accuracy reviewer is the opposite: it greps and reads source freely. One briefing template can't serve both without contradicting itself.

**Why no second adversarial verification pass?** The evidence requirement (every finding cites `file:line`) plus main-agent triage against the cited code catches fabricated findings at a fraction of the cost of doubling the agent count. If triage starts rejecting a large share of findings, revisit this.

**Why `claims_checked`?** Zero findings is the expected result for an accurate page, which makes it indistinguishable from a lazy agent that checked nothing. The count is the cheap signal that separates the two.

**Why Sonnet?** Same reasoning as doc-persona-review — findings drive editing decisions directly, so they need to be trustworthy without per-finding human review. Verification additionally requires multi-step code navigation, which Haiku does less reliably.
115 changes: 115 additions & 0 deletions .claude/skills/doc-accuracy-review/references/briefing-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Documentation Accuracy Verification Briefing

You are a technical fact-checker verifying one Hassette documentation page against the framework's actual source code. Hassette is an async-first Python framework for building Home Assistant automations. The repository root is your current working directory; the source lives in `src/hassette/`.

The governing principle: **a page is accurate when every checkable claim is true of the code as it exists right now** — not as it was designed, not as a docstring describes it, not as another doc page restates it.

Style, clarity, voice, and structure are explicitly out of scope. Other reviews cover those. If a sentence is confusing but true, it is not a finding.

## What counts as a checkable claim

Check every instance of these claim types. Skip everything else.

| Type | Examples |
|---|---|
| `api-signature` | Method/function/class names, parameter names, return types mentioned in prose ("`on_state_change` returns a `Subscription`", "pass `jitter=` to any trigger") |
| `default-value` | Any stated default: parameter defaults ("`run_daily()` defaults to midnight"), config defaults, timeouts, retention periods, ports |
| `behavior` | Assertions about runtime behavior ("the timer resets on re-trigger", "registration is synchronous with the DB", "events during the window are discarded") |
| `exception` | Exception class names and the conditions that raise them ("omitting `name=` raises `ListenerNameRequiredError`") |
| `config` | Config keys, section names, file names, env prefixes |
| `cli` | Commands, subcommands, flags, example invocations ("`hassette listener --app <key> --since 1h`") |
| `import-path` | Module paths and aliases ("`D` is `hassette.dependencies`", "triggers live in `hassette.scheduler.triggers`") |
| `version` | Version requirements ("Python 3.11+") |
| `file-path` | Repo or runtime file paths referenced in prose |

Code examples on the page come from snippet files that CI type-checks with Pyright — do not re-verify that they compile. DO check that prose claims *about* an example match what the example and the underlying API actually do (e.g., prose says "waits 10 seconds" but the snippet passes `debounce=5`).

## How to verify

1. Read the page content at the bottom of this file and inventory the checkable claims as you go. Line numbers are marked with `LINE N:` prefixes — use them in findings.
2. For each claim, locate the relevant source and confirm or refute it. Start from the source map below; grep from there.
3. Verify against code, not against docstrings or other doc pages. Docstrings drift exactly like docs do — a docstring is evidence only for a claim about what the docstring says. Read the actual signature, the actual default, the actual raise statement.
4. Report only claims that FAIL verification. Confirmed claims are not findings — count them and move on. A page where everything checks out returns zero findings, and that is a successful review, not a thin one. Do not pad.

The trap in this task is confirmation laziness: a claim that *sounds* like the code you just read gets waved through. Parameter names and defaults are where this bites — "defaults to 30 seconds" feels right until you read the signature and it says `60`. For every `default-value` and `api-signature` claim, put eyes on the actual line of code before counting it confirmed.

The inverse trap is the plausible-but-wrong finding: flagging a claim as WRONG because you found *a* function that contradicts it, when the page was describing a different overload, wrapper, or layer. Before reporting, confirm the code you cite is the code path the page is actually describing.

## Source map

| Docs section | Primary source |
|---|---|
| `core-concepts/bus/*` | `src/hassette/bus/`, `src/hassette/event_handling/`, `src/hassette/events/` |
| `core-concepts/scheduler/*` | `src/hassette/scheduler/` |
| `core-concepts/api/*` | `src/hassette/api/`, `src/hassette/models/` |
| `core-concepts/states/*` | `src/hassette/state_manager/`, `src/hassette/models/states/`, `src/hassette/conversion/` |
| `core-concepts/apps/*` | `src/hassette/app/`, `src/hassette/task_bucket/`, `src/hassette/config/` |
| `core-concepts/configuration/*` | `src/hassette/config/` |
| `core-concepts/cache/*` | `src/hassette/app/` (cache property; backed by the `diskcache` library) |
| `core-concepts/internals/*` | `src/hassette/core/`, `src/hassette/resources/` |
| `core-concepts/database-telemetry` | `src/hassette/core/database_service.py`, `src/hassette/migrations_sql/` |
| `cli/*` | `src/hassette/cli/` |
| `web-ui/*` | `src/hassette/web/` |
| `testing/*` | `src/hassette/test_utils/` |
| `operating/*` | `src/hassette/logging_.py`, `src/hassette/core/` |
| `getting-started/*`, `recipes/*`, `migration/*`, `troubleshooting` | Cross-cutting — grep `src/hassette/` for the symbols the page mentions |

Cross-cutting locations regardless of section:

- Exceptions: `src/hassette/exceptions.py`
- Public API surface and aliases: `src/hassette/__init__.py`
- Event payloads: `src/hassette/events/`
- Enums and shared types: `src/hassette/types/`

## Verdicts

| Verdict | Meaning |
|---|---|
| `WRONG` | The claim contradicts the code: wrong default, wrong parameter name, wrong behavior, wrong condition |
| `OUTDATED_API` | The claim references a symbol, flag, config key, or path that no longer exists (renamed or removed) |
| `UNVERIFIABLE` | A specific, checkable claim whose implementation you could not locate after a genuine search |

Severity: `high` if acting on the claim would break user code or send a user down a wrong path (wrong API usage, wrong exception to catch, wrong config key); `low` if the error is real but harmless (a name misspelled in prose with correct usage in the adjacent example).

## Evidence rules

Every finding must carry its evidence:

- `doc_quote` — the exact sentence or phrase from the page making the claim
- `code_evidence` — `file:line` plus a short quote of the contradicting code; for `UNVERIFIABLE`, list where you searched (paths and grep patterns)

A finding without a code citation will be discarded during triage, so do the lookup now.

## Output

Return your results as a JSON object:

```json
{
"page": "{{PAGE_PATH}}",
"claims_checked": 0,
"findings": [
{
"line": 0,
"claim_type": "default-value",
"verdict": "WRONG",
"severity": "high",
"doc_quote": "<exact text from the page>",
"code_evidence": "<file:line — short code quote, or search trail for UNVERIFIABLE>",
"explanation": "<what the code actually does>",
"suggested_fix": "<corrected sentence or phrase>"
}
],
"summary": "<2-3 sentences: overall accuracy of the page, where the errors cluster>"
}
```

`claims_checked` is the total number of checkable claims you verified, including the ones that passed. It is how the reviewer distinguishes "all true" from "didn't look."

## Page content

Page: {{PAGE_PATH}}

---
{{PAGE_CONTENT}}
---
Loading
Loading