>- Conventions and a checklist for writing, updating, and correcting Doxygen documentation comments in WIL's public C++ headers under `include/` so they match the repository's style and build without warnings. Applies only to headers under `include/` — not `tests/` or other code. Use when adding or fixing `//!` or `/** */` doc comments, `@param`/`@tparam`/`@return` tags, `@ref`/`@see` cross-references, or briefs, or when resolving warnings from the Doxygen `docs` build target.
npx skills add https://github.com/microsoft/wil --skill doxygen-comments
WIL's public API is documented with Doxygen comments in the headers under include/wil/, and the docs are generated from
docs/Doxyfile. Use this skill to add, update, or fix those comments so they stay consistent with the codebase and generate
cleanly.
This skill applies only to WIL's public headers under include/ (primarily include/wil/*.h). Do not apply these
conventions to test code (tests/), documentation sources (docs/), packaging, or build scripts — those files are not part of
the generated API reference. If a request targets files outside include/, this skill does not apply.
Do not rewrite comments purely for style, and do not document private/internal helpers (see "Public API only" below).
//! line comments or /** ... */ block comments. Match the stylealready used in the surrounding file / nearby declarations instead of mixing both. //! is common for file banners and member
comments; /** */ is common for free functions and templates.
@, never \. Use @param, @tparam, @return, @brief, @ingroup, @ref, @see, @note, @file,etc. The codebase uses zero backslash-style tags — keep it that way.
JAVADOC_AUTOBRIEF makes the first sentence (up to the first period) the brief.Keep it on its own physical line; start the detailed description on the next line. An explicit @brief is rarely needed.
.clang-format (ColumnLimit: 130) and applies to comment text too.EXTRACT_ALL = NO and EXTRACT_PRIVATE = NO, so private members and undocumented internals are notemitted. Focus documentation on the public surface; don't add Doxygen tags to private helpers expecting them to appear in the
output.
details namespaces. WIL's implementation details live in namespaces named details (and similarly namedvariants such as details_abi). These must not emit documentation — wrap the entire namespace in a /// @cond … /// @endcond
pair (note the /// marker used for these structural tags) so Doxygen skips its contents. Put /// @cond on its own line
immediately before the namespace and /// @endcond immediately after its closing brace. See the example below.
~~~ fenced example for functions whose correctuse isn't clear from the signature alone — e.g. callback or functor contracts (what the callback must do and return), paired or
multi-step call sequences, RAII helpers whose placement or lifetime matters, round-trip or reverse operations, or subtle
buffer/ownership conventions. Skip examples for self-explanatory helpers such as simple getters, predicates, or arithmetic.
Doxygen fenced code blocks are delimited with ~~~ (any matching run of three or more tildes); inside //! banners, prefix
each example line with //!.
@ref <name> and @see, and group related members with @ingroup <group>(for example @ingroup outparam).
wil::; STL-mirroring pieces live under wistd::.PREDEFINED macro over a per-guard escape; use WIL_DOXYGEN only when needed. Doxygen evaluates #if guardsagainst docs/Doxyfile's PREDEFINED list, which already forces many conditions true in docs — e.g.
WINAPI_FAMILY_PARTITION(partition)=1, WIL_USE_STL=1, WIL_ENABLE_EXCEPTIONS, WIL_RESOURCE_STL, and many __cpp_lib_*
feature macros. First check whether the guard is already satisfied there; if so, no escape is needed. If a declaration is
gated on a feature macro that is broadly useful, add that macro to PREDEFINED rather than sprinkling escapes. Only when the
condition can't be satisfied that way — notably the mutually-exclusive __WIL_* / __WIL_*_STL header-wrapper guards in
resource.h/registry.h — OR || defined(WIL_DOXYGEN) into the condition (convert #ifdef X / #ifndef X to
#if defined(X); when the line wraps, continue with a trailing \ and put defined(WIL_DOXYGEN) on the next line). A
standalone #ifdef WIL_DOXYGEN block is for doc-only constructs with no real declaration to attach to.
WI_NOEXCEPT → noexcept,WI_NODISCARD → [[nodiscard]], and others in docs/Doxyfile's PREDEFINED), so document the logical signature rather than
the macro-heavy source.
When adding or fixing comments, verify:
@param/@tparam name matches the signature — no stale, missing, misspelled, or reordered names. This is the mostcommon source of WARN_IF_DOC_ERROR warnings.
@return is present and accurate for functions that return a meaningful value; omit it for void._failfast, and_nothrow/NoThrow variants — state how the function reports failure (throws, fail-fasts, or returns an HRESULT).
@ (convert any \param, \brief, etc.).@ref/@see targets exist and are spelled correctly.10. Internal details/details_* namespaces are wrapped in /// @cond … /// @endcond so their contents are excluded from
the generated documentation.
11. Conditionally-compiled public declarations are visible in docs — the guard is either already satisfied by PREDEFINED
or ORs in || defined(WIL_DOXYGEN) (reserved for conditions PREDEFINED can't cover, like the header-wrapper guards).
12. Non-obvious functions carry a ~~~ usage example — anything with a callback contract, a paired/multi-step call sequence,
or subtle ownership/buffer semantics shows how to call it; trivial helpers do not.
Doxygen is configured with WARN_IF_UNDOCUMENTED = YES and WARN_IF_DOC_ERROR = YES, and formats warnings as `$file:$line:
$text, so a docs build points directly at problems. From an already-configured build directory, run the docs` target (it
requires Doxygen on PATH, and WIL_BUILD_TESTS = ON, which is the default):
ninja docs # run from the configured build directory, e.g. build/msvc
The docs target just runs Doxygen, so it is independent of the selected configuration. Review its output for new warnings
referencing the files you touched — mismatched parameters, undocumented public members, and broken references all surface there.
Generated HTML lands under the build directory. If Doxygen is not installed, at minimum re-check each comment against the current
signature using the checklist above.
Correcting stale parameter names and backslash tags:
// Before — backslash tags, @param name doesn't match the signature, missing @return.
/** Opens the widget.
\param widgetName The name to open.
*/
HRESULT open_widget_nothrow(PCWSTR name, wil::unique_hwidget& widget);
// After — @-style tags, names match the signature, failure mode and return documented, wrapped at 130 columns.
/** Opens the named widget.
Returns an error code rather than throwing, so it is safe for callers built without exceptions.
@param name Name of the widget to open.
@param widget Receives the opened widget on success.
@return `S_OK` on success, or a failure `HRESULT` from the underlying `OpenWidget` call. */
HRESULT open_widget_nothrow(PCWSTR name, wil::unique_hwidget& widget);
Hiding an internal details namespace so Doxygen excludes it from the output:
/// @cond
namespace details
{
// Internal implementation — intentionally undocumented.
template <typename T>
using ensure_trivially_destructible_t = typename ensure_trivially_destructible<T>::type;
} // namespace details
/// @endcond
Adding a WIL_DOXYGEN escape so a guarded public declaration still appears in the docs:
// Before — only compiled when <objbase.h> has been included, so Doxygen never sees this signature.
#if defined(__WIL_OBJBASE_H_)
template <typename T>
com_ptr<T> make_com_ptr(T* ptr);
#endif
// After — OR in defined(WIL_DOXYGEN) (which Doxygen predefines) so the signature is documented.
#if defined(__WIL_OBJBASE_H_) || defined(WIL_DOXYGEN)
template <typename T>
com_ptr<T> make_com_ptr(T* ptr);
#endif
This skill is an intentional starting point. The conventions above are grounded in the current headers and docs/Doxyfile, but
the checklist and examples are expected to grow as we refine it. When a rule here disagrees with real, nearby code in the file you
are editing, prefer matching the surrounding code and flag the discrepancy.
Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
Use when the user asks to run Codex CLI (codex exec, codex resume) or references OpenAI Codex for code analysis, refactoring, or automated editing. Uses GPT-5.2 by default for state-of-the-art software engineering.
Implement memory-safe programming with RAII, ownership, smart pointers, and resource management across Rust, C++, and C. Use when writing safe systems code, managing resources, or preventing memory bugs.
Python/HTSlib workflows for genomic files. Use when reading, querying, filtering, or writing SAM/BAM/CRAM, VCF/BCF, FASTA/FASTQ, or tabix data with pysam, including pileup, coverage, indexing, and CRAM references.
Evaluate scientific claims and evidence quality. Use for assessing experimental design validity, identifying biases and confounders, applying evidence grading frameworks (GRADE, Cochrane Risk of Bias), or teaching critical analysis. Best for understanding evidence quality, identifying flaws. For formal peer review writing use peer-review.
Use when a user asks to debug or fix failing GitHub PR checks that run in GitHub Actions; use `gh` to inspect checks and logs, summarize failure context, draft a fix plan, and implement only after explicit approval. Treat external providers (for example Buildkite) as out of scope and report only the details URL.
Documentation generation workflow covering API docs, architecture docs, README files, code comments, and technical writing.
Use when the user wants to translate a repository README, make a repo multilingual, localize docs, add a language switcher, internationalize the README, or update localized README variants in a GitHub-style repository.
Take microsoft/doxygen-comments from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.