barbatos-docs-sync
Keeps Barbatos.Wpf docs in step with the code after a public API change: each package's README.md (concept-first, the nuget.org landing page) versus API-REFERENCE.md (member-by-member, GitHub only), D
SKILL.md.claude/skills/barbatos-docs-sync/SKILL.md
GitHubDocumentation upkeep
Every package carries two hand-written documents - src/<Package>/README.md (concept-first)
and src/<Package>/API-REFERENCE.md (member-by-member) - on top of the XML docs in the code.
Per CLAUDE.md, a public API change is not done until both are updated - so run this as the
closing step of any src/ change, even when only the code was asked for. This skill is the
procedure for that and for the root and template docs around them. It is not about writing the
code (barbatos-package-authoring) or the template files themselves (barbatos-templates).
The path-scoped rule .claude/rules/docs.md loads a short form of this automatically whenever
one of these documents is opened.
Sources of truth
- The documents: Core README / API reference, Aquarius README / API reference, Router README / API reference, Valee README / API reference, the root README.md and API-REFERENCE.md, and templates/README.md.
- What gets packed: Directory.Build.targets (the
Noneitem packingREADME.mdto\README.md) and Directory.Build.props (PackageReadmeFile,GenerateDocumentationFile). Nothing packsAPI-REFERENCE.md. - The code wins over every document. Read the member, its XML
<summary>/<remarks>, and what it throws before writing about it - never copy a signature from the old doc. - Tests that pin documented claims - change the claim and the test together:
tests/Barbatos.Wpf.Aquarius.UnitTests/KeepAliveTests.cs(the KeepAlive comparison table:TabControlandFrame/Pagereally unmount,Directives.Showdoes not),tests/Barbatos.Wpf.AquariusRouter.UnitTests/RouterNavigationGuardOrderTests.cs(The Full Pipeline Order),tests/Barbatos.Wpf.Core.UnitTests/McpFeatureTests.cs(theEnvironmentVariablesnested-initializer syntax the Core README shows). - check-docs.mjs in this folder measures everything below that a script can. Run it before and after every docs edit, from the repo root:
node .claude/skills/barbatos-docs-sync/check-docs.mjs # menus, links, anchors, namespaces
node .claude/skills/barbatos-docs-sync/check-docs.mjs --types # + public types API-REFERENCE never names
Where each document is read
| Layer | Packed into the .nupkg? |
Read on | Consequence |
|---|---|---|---|
XML doc comments in src/ |
Yes (GenerateDocumentationFile) |
IntelliSense | Must agree with API-REFERENCE |
src/<Package>/README.md |
Yes, as the package readme | nuget.org and GitHub | Links must survive nuget.org |
src/<Package>/API-REFERENCE.md |
No - nothing packs it | GitHub only | Reached from the README by absolute URL |
Root README.md, API-REFERENCE.md, templates/README.md |
No | GitHub only | Relative links are fine |
What the published nuget.org pages actually do (seen in their HTML):
- Heading ids are the same GitHub slugs, so in-page
#anchorlinks and the menu work there. - A relative link (
[x](API-REFERENCE.md#rules)) renders ashref=""- dead. Every link that leaves a package README uses the absolute formhttps://github.com/Barbatos-Labs/Barbatos.Wpf/blob/main/<path>#anchor, as the "Read the Full API Reference" link and every cross-package link already do. - An image whose host is not on NuGet's allow-list renders as
src="".github.com/...?raw=trueis not allowed;img.shields.ioandraw.githubusercontent.comare (https://raw.githubusercontent.com/Barbatos-Labs/Barbatos.Wpf/main/build/<x>-logo.svgservesimage/svg+xml). > [!IMPORTANT]renders as an alert on both sites.- nuget.org keeps the readme of the version that was pushed; a README fix reaches it only with the next release.
The split - do not duplicate
| File | Answers | Register |
|---|---|---|
README.md |
"What is this, how do I use it, why is it shaped this way?" | Prose, worked examples, comparison tables, the rationale for every non-obvious decision |
API-REFERENCE.md |
"What exactly does this member take, return, default to, throw?" | Terse signature blocks and member lists/tables, modeled on the .NET API docs |
The API reference links back for the why - Router:
See [Navigation Guards](README.md#navigation-guards) for firing semantics and pipeline order.;
Core: see [Optional desktop features](README.md#optional-desktop-features) in the README. The
README links forward once, from its ## API Reference section.
Record exact behavior in API-REFERENCE: the exception type and when (Computed<T>.Value's setter
throws InvalidOperationException on the read-only form; PathTokenizer.Tokenize throws
ArgumentException / FormatException), what null means, cached versus recomputed
(FieldMeta.Dirty is a live comparison, never cached), defaults, and internal setters
("All setters are internal" on FieldMeta).
Package README skeleton
All four follow this; match it when adding a package or a top-level section.
# Barbatos.Wpf.<Package>

### *One-line positioning statement*
**Bold one-paragraph summary naming the main types.**
four badges: NuGet version, NuGet downloads, GitHub stars, license
---
## 📖 Documentation Menu
## Getting Started
### Introduction #### What is Barbatos.Wpf.<Package>? (Aquarius also says what it is
NOT), a > **Prerequisites** blockquote carrying a "Familiar with
<ported library>?" note (Core: a separate "Familiar from .NET MAUI?"
blockquote)
### Quick Start dotnet add package, the xmlns line (aq / aqr / aqv; none for Core),
minimal wiring; Router and Valee end with "See `samples/<Sample>` ..."
listing what the sample demonstrates
## <feature sections> ### subsections; #### for steps and asides (normally not in the menu)
## Deliberately Out of Scope Router and Valee; Aquarius has "## Patterns that are already
native" instead; Core has neither
## Ecosystem
### Repository layout src/, samples/, tests/ - one bullet each
## API Reference one paragraph + the 👉 absolute link to API-REFERENCE.md (Core also
lists its namespaces before it and adds a closing line)
## Community Core: ### Maintainers / ### Support / ### License; the other three:
one sentence linking https://github.com/Barbatos-Labs/Barbatos.Wpf#community
Every ## is preceded by a --- rule. The Core README has no xmlns (Core has no
XmlnsDefinition); a new Core desktop feature also gets a row in the
Optional desktop features
table (Feature | Builder method | Options section | Runtime service | Enabled by default?) and,
if it is large, its own ## section the way Dialogs, SplashScreen and Periodic services have.
Documentation Menu and anchors
- The menu sits under
## 📖 Documentation Menu:* **[Title](#anchor)**for a##, two-space-indented* [Title](#anchor)for a###, four spaces for the rare####(Core's "Removing an interceptor at runtime"). Order and nesting follow the body. - Every
##and###gets an entry. A section without one is effectively unfindable. Link text may be shortened ([Modal routes](#modal-routes---a-route-that-renders-into-a-window)); the anchor may not. - Anchors are GitHub slugs of the rendered heading text: lowercase; every character that is not
a letter, digit, space,
-or_dropped (backticks,.,:,/,<>,(),', emoji); each space becomes-; a repeated heading gets-1,-2, ... in document order.
| Heading | Anchor |
|---|---|
### `Valee.Mask` - guiding what gets typed |
#valeemask---guiding-what-gets-typed |
### If (v-if / v-else / v-else-if) |
#if-v-if--v-else--v-else-if |
## 📖 Documentation Menu |
#-documentation-menu (leading hyphen) |
### `Field<T>` (sealed class) : `ObservableObject`, `IField`, `IDisposable` |
#fieldt-sealed-class--observableobject-ifield-idisposable |
## `Barbatos.Wpf.Aquarius.Reactivity` Namespace |
#barbatoswpfaquariusreactivity-namespace |
Core API-REFERENCE's repeated #### Properties |
#properties, #properties-1, ... |
Consequences: never link to a repeated #### Properties / #### Methods heading - link the
type's own heading. A Router/Valee type heading carries its base list, so changing a base type
changes the anchor; grep every doc for the old anchor. Renaming any heading means grepping for
its old slug across all ten documents.
API-REFERENCE structure - two dialects
Match the dialect of the file you are in; do not convert one into the other.
| Core, Aquarius | Router, Valee | |
|---|---|---|
| Opening | one paragraph, "modeled after the official .NET API documentation" | one paragraph + See the [README](README.md) for a concept-first walkthrough |
| Namespace table | Namespace | Description, bold links |
Namespace | Contents |
| Namespace heading | ## `Barbatos.Wpf.Hosting` Namespace |
## Namespace: `Barbatos.Wpf.AquariusRouter.Matching` |
| Type heading | ### `WpfApp` Class / ### `Watch` Static Class |
### `PathToken` (sealed record), ### `Form` (sealed class) : `ObservableObject`, ... |
| Members | csharp signature block, then bullets - **`Services`** (`IServiceProvider`) ...; Core groups them under #### Properties / #### Methods, and opens its larger namespaces (Hosting, LifecycleEvents, Dispatching, ApplicationModel, ApplicationModel.Communication, Apsu) with ### Classes / ### Interfaces / ### Classes / Interfaces / ### Extension Methods summaries |
Member | Type | Meaning tables (Member | Default | Meaning for options records) |
Aquarius, Router and Valee API references also state, under the namespace table, that all their
namespaces map onto one XAML namespace (Router and Valee name [assembly: XmlnsDefinition] in
AssemblyInfo.cs); the Aquarius and Router README Quick Starts list those namespaces after the
xmlns line. A new namespace touches those sentences, the namespace table, the root
API-REFERENCE.md, and (code side, barbatos-package-authoring) AssemblyInfo.cs.
Root and template documents
- Root
README.md- the GitHub landing page. One row per package in the## Packagestable (logo, badges, the one-paragraph summary, absoluteREADME · API Referencelinks), the TFM and dependency paragraph, thedotnet add packageblock,## Templates(install commands, example invocations with--Include*flags, IDE notes),## Repository layout, and## Community, whose#communityanchor the Aquarius/Router/Valee READMEs link to - do not rename it. Update it when a package summary, the package list or the templates change. - Root
API-REFERENCE.md- one bullet per package listing its public namespaces, linking the package's API reference by absolute URL. Update it whenever a namespace or package is added or removed (check-docs.mjsreportsROOTlines). templates/README.md- the layout tree (an empty leaf shows.gitkeeper (none yet)), the Install and Uninstall command blocks, one##section per template named`short-name` - Title (kind), and forbarbatos-wpf-app: the default package version quoted in prose, the count of Core flags in Picking which modules to include, and the per-flag descriptions. The template commands are repeated in the root README's Templates section and in the Aquarius README's Quick Start - change all three together. Template mechanics (symbols, conditionals, testing) arebarbatos-templates.
House voice
The prose records decisions and evidence, not mechanics.
- Say what a design was chosen over, and why. Valee README: "Built on Aquarius's
Watch.Onspecifically (notWatch.Effect) -Watch.Ononly reacts to the source's value changing, never toErrors/Metachanges a validation pass itself causes, which is what keeps two mutually-dependent fields from infinite-looping." - Say what was verified, and how. "(confirmed empirically)" in the Valee API reference on
RequiredAttributeshort-circuiting; "confirmed by testing" intemplates/README.md; "confirmed viaIsLoaded" in the KeepAlive table, backed byKeepAliveTests. Write it only after running it, and prefer a test that keeps it true. - Name the limits. Core README on push transports: "Worth being explicit about the limits of this: Firebase Cloud Messaging and Windows Notification Service don't map onto a client-managed persistent connection the way SignalR does ..."
- Map the port. Each Introduction has a "Familiar with ...?" blockquote (Vue's Composition API, Vue Router, vee-validate; "Familiar from .NET MAUI?" in Core, plus "Familiar from Vue's Pinia?" opening Core's Apsu section); where the port diverges from the original, say so and why, in place.
- Keep "already native" notes instead of growing API:
Already native: v-bind, v-for, v-html,
"Already native: error display" (Valee), "Patterns that are already native" (Aquarius). A
rejected idea goes to
Deliberately Out of Scope
as
**Thing** - reason, plus what to do instead. - Callouts only where it bites. Only
> [!IMPORTANT]is used, only in the Core docs: the SDK-suffixed TFM, the DeviceIdentity not-legal-advice note, synchronous splash-screen work, the pre-DI static facades, and Apsu's sync-action deadlock note (README and API reference). Other asides are bold-led blockquotes (> **Prerequisites**,> **Familiar with Vue Router?**). No[!NOTE]. - Dashes follow the file: the Core README and API reference mostly use
—; Aquarius, Router, Valee, the root README andtemplates/README.mduse only-. - Prose wraps at about 95 characters; table rows and long link lines stay on one line.
- No marketing adjectives, no "simply"/"just", no narrating what the code obviously does.
Checklist for one API change
Read the code - signature, defaults, exceptions, XML docs. Fix the XML docs too if they disagree with the behavior.
API-REFERENCE.md- the member row/bullet or type section in the file's dialect; in Core a new type also gets a row in its namespace's### Classes/### Interfacestable, where that namespace has one.README.md- the feature section: a worked example adapted from the sample (say which file), the rationale, the Vue mapping or divergence, any out-of-scope or already-native note.Menu - an entry for every new
##/###, in body order.Cross-links - README to API reference by absolute URL, API reference back by
README.md#...; sibling packages by absolute URL (a Router feature relying on AquariusSetuplinks the Aquarius README).Root
README.mdif the package summary, package list or templates changed; rootAPI-REFERENCE.mdif a namespace or package was added or removed.The sample - extend the package's own sample (a tab, route or field; one sample per package) with a comment saying what it demonstrates and why, and update the README's "See
samples/..." sentence that lists what the sample shows. Valee sample text goes into bothLocales/en-US.jsonandLocales/vi-VN.json; a Core feature that bindsBarbatos:Xxxcan show the file override in the Core sample'sappsettings.json.Templates - if a template uses the changed API or should offer the feature (a new
--IncludeXxxflag), loadbarbatos-templatesand updatetemplates/README.mdplus the copies listed above.Rename or removal - while the
[Obsolete]member exists it stays documented with its replacement, asAppGuid->AppIdis in AppInfo / PublisherInfo and in the Core README's> **`AppGuid` is deprecated:**blockquote. Then find every other mention of the old name:grep -rn "OldName" --include=*.md --include=*.cs --include=*.xaml --include=*.json \ src samples templates tests .claude README.md API-REFERENCE.mdPinned claims - if the change alters behavior a test pins (see Sources of truth), update the test and the claim together.
Run
check-docs.mjsand fix every line your change introduced.Agent skills - for any API or behaviour change, not only a rename, grep
.claude/skillsfor the member and fix every claim the change invalidated.
Symptom -> cause -> fix
| Symptom | Cause | Fix |
|---|---|---|
| A menu or "see below" link goes nowhere | Anchor guessed or heading renamed (the Aquarius README once linked (#if-v-if) for ### If (v-if / v-else / v-else-if)) |
Slug the real heading; run check-docs.mjs |
| The namespace table's links do nothing | Anchor missing a segment (#barbatoswpfreactivity-namespace for Barbatos.Wpf.Aquarius.Reactivity) |
#barbatoswpfaquariusreactivity-namespace |
| Link works on GitHub, dead on nuget.org | Relative link in a package README | Absolute https://github.com/Barbatos-Labs/Barbatos.Wpf/blob/main/... URL |
| Logo blank on nuget.org, fine on GitHub | Image host not on NuGet's allow-list (github.com/...?raw=true) |
raw.githubusercontent.com/... |
| New section exists but nobody finds it | No menu entry | Add it, nested under its real parent |
A link to #properties lands on the wrong type |
Repeated headings are suffixed -1, -2 |
Link the type heading |
| An anchor broke after a type change | Router/Valee type headings include the base list | Re-slug; grep the old anchor |
| Root and template docs contradict each other | One copy updated, the other not | templates/README.md is the detailed source; fix the root README to match |
| README fix not visible on nuget.org | nuget.org shows the readme of the pushed version | Ships with the next release |
Known drift (measured with check-docs.mjs)
None open: check-docs.mjs and check-docs.mjs --types both report "No problems". When a run
reports something you cannot fix in the same change, list it here, one bullet per file, and
drop the bullet once it is fixed.
Related skills
barbatos-package-authoring- the API change itself,[Obsolete]mechanics,AssemblyInfo.cs, versioning and release.barbatos-templates- thedotnet newtemplates behindtemplates/README.md.barbatos-wpf-testing- writing the test that backs a "confirmed by running it" claim.- The feature skills (
barbatos-wpf-host,barbatos-wpf-essentials,barbatos-aquarius-view,barbatos-aquarius-router,barbatos-valee-form,barbatos-apsu-store,barbatos-mcp-ai) - domain knowledge for what the section should say.