.agents/skills/api-docs/references/reviewing.md
Audit existing SkiaSharp docs for accuracy, freshness, examples, and hygiene — by scope. This is the
dual of adding.md (which fills blanks); review improves what is already filled. Review is
report-only by default; fixing is a separate, gated step.
You run this yourself, end to end — resolve scope, read source, compare, report, and (if approved) fix. One agent does the whole pass. Work in batches of ~25–40 files so each pass stays auditable and resumable.
skia-patterns.md — pre-verified domain facts (color layouts, struct defaults,
standard-based enums, caller-owned vs parent-owned). If a doc claim matches this file, it is correct —
do not "correct" it from your own reasoning about how a macro "should" expand.checklist.md — the CRITICAL/IMPORTANT/MINOR severity taxonomy you classify against.patterns.md — .NET XML doc syntax, verb conventions, cref vs xref rules.obsolete-api-map.md — obsolete members and the modern API to use instead.
§1 lists members that are always obsolete; §2 lists methods whose name also exists on the modern API
(disambiguate by signature). Using an obsolete member in an example is a compile failure → CRITICAL.Apply these facts; do not restate them in the docs.
AI doc writers confidently state "facts" without checking source — wrong parameter constraints, wrong
channel names, wrong byte layouts, invented overloads, wrong defaults — and frequently write examples
that call obsolete members or undeclared variables. Assume errors exist. A review that finds 0 issues
across many files almost certainly skimmed. Every factual finding must cite source (path:line).
Pick which docs to review. The docs live at docs/SkiaSharpAPI/<Namespace>/<Type>.xml; list them
directly and map each to its source at binding/<Namespace>/<Type>.cs (grep if the guess is wrong).
The user describes the target in plain language. For a theme ("the font docs"), scan the list and
select the matching files yourself — e.g. expand "font" to SKFont, SKTypeface, SKFontMetrics,
SKTextBlob, and the text APIs on SKPaint/SKCanvas, judging by each type's purpose not just its
filename. For "whatever changed" use git -C docs diff --name-only origin/main...HEAD; for the whole
library review every file. Shard into ~25–40-file batches; review is incremental against the
last-reviewed marker.
Run the deterministic checks on the batch with docs-format-docs (validation.md).
It finds objective defects with no model cost and emits findings in the shared contract.
Review each file (source first). From the filename, find and READ the C# source in binding/
BEFORE reading the XML and build a fact sheet: constructors, overloads, accessor kind per property
({ get; } vs { get; set; }), validation logic (throws/clamps/pads/truncates), numeric constants,
defaults. Then read each <Docs> block and run the checks below. A file reviewed with no source read
is incomplete.
Collect and dedupe findings in the shared contract. Deduplicate by (file, docId, class) plus
fuzzy message match; when the linter and your own review report the same defect, keep one row. On a
severity disagreement, take the highest.
(Gated) Fix. If fixing is approved, edit the XML directly for CRITICAL (and chosen IMPORTANT)
findings, and expand examples where types are example-poor — port the SKCanvas/SKShader bar to
barren types like SKFont, SKImageFilter.
Validate & format — only if step 5 made edits: run docs-format-docs and fix any build-failing
broken-XML errors (validation.md).
Land per-wave PRs on dev/... branches in the docs submodule.
path:line)MemberSignature ({ get; } → "Gets", { get; set; } → "Gets or sets").0/null/false; recurring trap: SKDocumentXpsOptions.Dpi is 0, not 72). If you cannot read the
source, do not assume 0 — a stated default you can't verify is UNVERIFIED, not a finding.
Inventing "should be 0" for a default you never checked in source is a false positive.skia-patterns.md and
the native header if present; check the bit math adds up.skia-patterns.md > your own knowledge
(never use the last for byte layouts). Cannot find the header → flag UNVERIFIED, not wrong.Classes: factual (a stated fact contradicts source), fabricated-member (docs/example reference a
type, member, or overload that does not exist in source).
For every ```csharp block in <remarks> CDATA, extract each constructor call, method call, and
property access, and:
grep the C# source in binding/ to confirm it exists with that exact signature/overload, and
that the overload accepts those argument types.override, base, event, class, struct, …).SKData?, SKTypeface.FromFamilyName), is null handled
before use?obsolete-api-map.md AND grep
its source for [Obsolete(...)]. A member from the map's §1 (or any [Obsolete(..., error: true)]
member) in an example is CRITICAL — it won't compile; a soft-obsolete ([Obsolete] warning-only)
member is IMPORTANT.
DrawText/MeasureText exist
in both an obsolete and a modern form (map §2). Judge by receiver and signature, not by name: the
deprecated forms are on SKPaint or are the SKCanvas overloads with no SKFont argument; the modern
forms are on SKFont or take an SKFont. font.MeasureText(...) and
canvas.DrawText(..., SKTextAlign, font, paint) are correct — never rewrite a valid modern call.
Only flag paint.MeasureText(...) and canvas.DrawText(string, x, y, paint).bitmap2 when only
bitmap was declared is a compile error).using/Dispose a parent-owned object (the canvas from SKDocument.BeginPage and
SKSurface.Canvas are parent-owned).Class: example.
To be added., TODO, bracketed remarks scaffolds like [Describe …]).<remarks> has real content, not a template blank.<see cref> uses the correct prefix (T:/M:/P:/F:); CDATA <xref:…> uses the bare UID, no
prefix (<xref:SkiaSharp.SKPath> correct; <xref:T:SkiaSharp.SKPath> broken).<see cref> class" (or "struct"
for value types).<value> "true if…".<see langword="null" />, not "default".<summary />, <value />, <returns />) that should have content (<remarks /> is OK).skia-patterns.md.Class: quality.
One finding per line, machine-parseable:
SEVERITY | class | <file> | <docId> | <message — what it says vs what source says (path:line)>
SEVERITY ∈ CRITICAL/IMPORTANT/MINOR per checklist.md. Then a per-file trace proving you read
source (so a skim is detectable):
TRACE | <file> | source:<binding/...cs lines a-b or NONE> | checked:<n> | issues:<n>
After deduplication, write a single Markdown report plus the machine block (one line per deduped finding)
to output/docs-review/ (gitignored). Nothing in docs/ changes unless the gated fix step runs.
# Review report — <scope> (<n> files)
## Summary
- Files reviewed: <n> Findings: CRITICAL <n>, IMPORTANT <n>, MINOR <n>
- Coverage gaps: <files with no source read, or "none">
- Assessment: Ready for release / Needs fixes / Major issues
## CRITICAL / IMPORTANT / MINOR
- `<file>` · `<docId>` — <message> → <fix>
## Extra findings (uncorroborated leads)
...
FINDING | <severity> | <class> | <file> | <docId> | <message>
path:line for every factual contradiction. No citation → not a finding.skia-patterns.md — the reference is pre-verified.