.agents/skills/api-docs/SKILL.md
Write and review XML API documentation for SkiaSharp.
docs/ directory is a Git submodule pointing to mono/SkiaSharp-API-docsmdoc — if new APIs were added, run Phase 1 before editingdocs/SkiaSharpAPI/
├── SkiaSharp/ # Main namespace
│ ├── SKCanvas.xml # One XML file per type
│ ├── SKPaint.xml
│ ├── SKImage.xml
│ └── ...
├── HarfBuzzSharp/ # HarfBuzz namespace
├── SkiaSharp.Views.*/ # Platform-specific views
└── index.xml # Extension methods (auto-synced, don't edit)
When new APIs have been added, XML doc files must be regenerated before documenting them.
dotnet tool restore
dotnet cake --target=docs-download-output # Download latest NuGets from CI feed
dotnet cake --target=update-docs # Regenerate XML docs (api-diff + mdoc update + format)
New members appear with "To be added." placeholders. Skip this phase if:
Extract placeholders to JSON using the docs tool:
pwsh .agents/skills/api-docs/scripts/docs-tool.ps1 extract docs/SkiaSharpAPI/ -Output output/docs-work/
This produces one JSON file per XML file, containing only members with "To be added." placeholders. The output/ directory is gitignored so local runs don't pollute the repo.
This phase is lightweight — you are an orchestrator, not a writer. Read only what you need to plan the work, then delegate immediately.
Read the manifest — output/docs-work/manifest.json tells you how many files, types, and fields need documentation. Use this to plan the write phase.
Read the reference docs — these will be passed to writer agents:
Do NOT pre-read JSON files or source code — the writer agents will do their own discovery. Pre-reading is wasted work that duplicates what writers do.
Launch one background general-purpose agent to write documentation for all files in manifest.json.
Writer agent prompt:
You are an API DOCUMENTATION WRITER. Fill all placeholder fields in the JSON
files with accurate, well-written .NET XML documentation.
STEPS:
1. Read the patterns file at .agents/skills/api-docs/references/patterns.md
2. Read the domain knowledge at .agents/skills/api-docs/references/skia-patterns.md
3. For each JSON file listed in output/docs-work/manifest.json:
a. Read the JSON file
b. Find and READ the corresponding C# source in binding/ (ESSENTIAL for accuracy)
c. Fill all "To be added." fields following the rules below
d. Write the completed JSON back to the same path
JSON INTEGRITY RULES (NON-NEGOTIABLE):
- NEVER add new keys to the JSON that are not already present in the file
- NEVER add new entries (members) to the JSON that were not extracted
- Only modify values of EXISTING keys — the extract tool determines scope
- The "_extractedKeys" array in each entry lists exactly which fields you may fill
- If a member has only "remarks" extracted, fill ONLY "remarks" — do NOT add
"summary", "params", or other fields even if you think they could be improved
WRITING RULES:
- NEVER invent API calls — verify every method/overload exists by reading C# source
- NEVER guess numeric values — read MemberValue from JSON, cross-reference source
- Fill ALL params in ALL overloads — each overload independently complete
- Read-only properties use "Gets" — check source for { get; } vs { get; set; }
- Use <see langword="null" /> not <see langword="default" /> for nullable params
- Use <see langword="true" /> and <see langword="false" /> for boolean literals in prose
STANDARD VALUES (CICP, Vulkan, OpenType, etc.):
- For enum members referencing external standards, you MUST read the C/C++ header
in externals/skia/ where the enum is defined and verify numeric values
- Do NOT rely on your own knowledge of standards for specific numeric values
(gamma values, bit depths, transfer function parameters, etc.)
- If you cannot find the header, state "value from standard" without inventing
specific numbers (e.g., say "assumed display gamma" not "assumed gamma 2.2")
REMARKS RULES:
- Type-level entries (memberType=type) have remarksRequired=true with a CDATA template.
Complete it fully — never leave [bracketed placeholders]. Include description,
disposal note if applicable, and a code example.
- Member-level: set remarks to "" for simple members, or write rich markdown for
important methods (factory methods, Draw*, etc.)
CONTENT FORMAT:
- XML refs: <see cref="T:..." />, <paramref name="..." />, <see langword="null" />
- In CDATA remarks: use <xref:...> instead of <see cref>
- Set remarks to "" for self-closing <remarks />
TRUST HIERARCHY for native type facts (bit layouts, byte orders):
1. Native C/C++ header in repo (if you can find and read it) — AUTHORITATIVE
2. skia-patterns.md reference file — PRE-VERIFIED, trust it
3. Your own knowledge — DO NOT USE for byte layouts. Never invent macro expansions.
Do all work directly. Do NOT launch sub-agents or delegate.
Wait for the writer agent to complete before proceeding to Phase 5.
Launch three background general-purpose agents in parallel to independently validate the documentation. Each reviewer reads the source code fresh — they did NOT write the docs and have no blind spots from the writing process.
IMPORTANT — adversarial mindset: AI documentation writers typically introduce 15–30 factual errors per batch of ~800 fields. A review that finds 0 issues almost certainly skimmed. Each agent MUST read source code and provide evidence.
Agent 1: Factual Claim Verifier — cross-references every factual claim against source:
You are a FACTUAL CLAIM VERIFIER. Your ONLY job is to find documentation claims
that contradict the actual source code.
ADVERSARIAL CONTEXT: AI doc writers confidently state "facts" without checking
source. Common errors include: wrong parameter constraints, wrong channel names,
wrong byte layouts, and invented API overloads. Assume errors exist.
Do all work directly. Do NOT launch sub-agents or delegate.
FIRST: Read .agents/skills/api-docs/references/skia-patterns.md — this is your
reference for domain-specific facts (byte layouts, naming conventions, type
categories). You will use this to verify claims about native types.
SOURCE-FIRST PROTOCOL — for each JSON file in output/docs-work/:
1. Identify the type name from the filename
2. Find and READ the corresponding C# source file in binding/ BEFORE reading the JSON
3. Build a fact sheet: constructors, methods, property accessors (get vs get+set),
validation logic (throws? clamps? pads? truncates?), numeric constants, defaults
4. NOW read the JSON and compare every claim against your fact sheet
SPECIFIC CHECKS:
- Parameter constraints ("exactly N", "must be", "cannot be"): does the source
actually validate/reject, or silently accept? Read the METHOD BODY, not just signature.
- Data format claims (bit layouts, channel names, byte orders): verify against
skia-patterns.md and the native C/C++ header if available in the repo.
- Default value claims: find the actual default in source (e.g., struct zero-init vs constants)
- "Gets or sets" vs "Gets": check if property has { get; set; } or only { get; }
- Cross-library: SkiaSharp and HarfBuzzSharp are DIFFERENT libraries with different conventions.
STANDARD VALUE VERIFICATION (CRITICAL):
- For enum members that cite external standards (CICP, ITU-T, Vulkan, OpenType),
you MUST locate and read the C/C++ header where the enum is defined (check
externals/skia/include/ or binding/ generated files)
- Cross-reference the MemberValue in JSON against the enum constant in source
- If documentation claims a specific numeric property of a standard (e.g., "gamma 2.2",
"10-bit precision", "64-bit packed"), verify it is consistent:
- Does the bit math add up? (e.g., "64-bit with 10+10+10+10 packed" = only 40 bits → ERROR)
- Does the gamma match the correct CICP value number?
- If you cannot find the header, flag the claim as UNVERIFIED rather than assuming correct
- Provide file path + line number for every standard value you verify
TRUST HIERARCHY for native type facts (bit layouts, byte orders, macro expansions):
1. Native C/C++ header in repo (if you can find and read it) — AUTHORITATIVE
2. skia-patterns.md reference file — PRE-VERIFIED, trust it if header unavailable
3. Your own knowledge — DO NOT USE for byte layouts. Never invent macro expansions.
If you cannot locate the native header for a type, you MUST defer to
skia-patterns.md. Do NOT "correct" a claim that matches skia-patterns.md
based on your own reasoning about how a macro "should" expand. The reference
file was verified against the actual source.
OUTPUT FORMAT — you MUST include a verification trace per file:
[filename.json] SOURCE: binding/SkiaSharp/SKFoo.cs (read lines 1-85)
Claim: "exactly four characters" (docId: M:SkiaSharp.SKFoo.Parse)
→ Source line 22: if (s.Length < 4) s = s.PadRight(4); → SILENTLY PADS
→ CRITICAL: should say "padded with spaces if shorter than 4 characters"
Claim: "Gets or sets the width" (docId: P:SkiaSharp.SKFoo.Width)
→ Source line 45: public int Width { get; } → GET ONLY
→ CRITICAL: should say "Gets"
ISSUES: [list]
A file review with NO source file reads is INCOMPLETE and will be rejected.
Finding 0 issues across all files should be rare — state your confidence level.
Agent 2: Code Example Verifier — verifies every code example uses real APIs:
You are a CODE EXAMPLE VERIFIER. Your ONLY job is to verify that every code
example in the documentation uses real APIs with correct signatures.
ADVERSARIAL CONTEXT: AI doc writers frequently invent method overloads, use
wrong parameter types, and write examples with C# syntax errors. In past runs,
we found examples using reserved keywords as variable names (var override = ...)
and constructing structs that no public API actually accepts. Assume errors exist.
Do all work directly. Do NOT launch sub-agents or delegate.
For each JSON file in output/docs-work/:
1. Find every code block in remarks fields (look for ```csharp in CDATA sections)
2. For each code block:
a. Extract every method call, constructor call, and property access
b. grep binding/ source code to verify it exists with that exact signature
c. Check: does the overload accept those parameter types?
d. Check for C# reserved keywords used as variable names:
override, base, event, class, struct, delegate, abstract, virtual, etc.
e. Check null safety: if a method returns nullable (SKData?), does the
example handle null before using the result?
OUTPUT FORMAT — you MUST use this structure for each file:
[filename.json] CHECKED N code examples
Example 1 (docId): "var surface = SKSurface.Create(...)"
→ grep binding/SkiaSharp/SKSurface.cs: found Create(SKImageInfo) at line 42 ✓
→ variable names OK ✓
Example 2 (docId): "var override = new SKFontPaletteOverride"
→ CRITICAL: "override" is a C# reserved keyword
ISSUES: [list] or NONE
A review that checks 0 code examples is INCOMPLETE. Finding 0 issues across
all files should be rare — state your confidence level if you find nothing.
Agent 3: Quality Reviewer — catches style, completeness, and naming issues:
You are a documentation QUALITY REVIEWER. Read the checklist at
.agents/skills/api-docs/references/checklist.md, the patterns at
.agents/skills/api-docs/references/patterns.md, and the domain knowledge at
.agents/skills/api-docs/references/skia-patterns.md for guidelines.
Do all work directly. Do NOT launch sub-agents or delegate.
For each JSON file in output/docs-work/:
1. Check for remaining "To be added." values that should have been filled
2. Check type-level entries (memberType=type) have real remarks content,
not template placeholders like [Describe...] or [Show...]
3. Check summaries add value beyond just restating the member name
4. Check <see cref> references use correct prefix (T: M: P: F:)
5. Check boolean params use "true to..." and boolean returns use "true if..."
6. Check nullable params use <see langword="null" /> not "default"
7. Check remarks don't make false comparisons with other types
(e.g., "Unlike X, which is immutable" — verify before accepting)
8. Check enum member descriptions accurately describe the member's
specific value, not a similar-looking sibling enum member
9. Check domain facts against skia-patterns.md (naming conventions, byte layouts,
type categories). If documentation matches the reference, it is correct.
10. For native byte layout claims, compare against skia-patterns.md. If the
documentation matches the reference file, it is CORRECT — do not override.
Never invent C macro expansions to "disprove" the reference.
Report CRITICAL and IMPORTANT issues only. Include file, docId, and fix.
After all 3 reviewers complete: Fix all CRITICAL issues reported by any reviewer. Edit the JSON files directly to correct each issue. Then proceed to Phase 6.
After fixing all CRITICAL review issues, merge the JSON back into XML:
pwsh .agents/skills/api-docs/scripts/docs-tool.ps1 merge output/docs-work/
The merge tool has built-in safety checks:
MemberSignature and TypeSignature elements before and after merging each file and aborts with a fatal error if any were lost_extractedKeys (prevents agents from overwriting existing documentation with "improved" versions). Rejected fields emit a warning.Then run formatting to clean up:
dotnet cake --target=docs-format-docs