coding-guidance-cpp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited coding-guidance-cpp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill adds portable C++ implementation, refactoring, and review guidance.
This skill provides portable C++ engineering principles. Compose with:
security (threat modeling)
backend-systems-guidance (stronger backend architecture, reliability, and trust-boundary work), ui-guidance (graphical UI/web frontend), project-core-dev (repo-specific build/test commands)
selectively
local clang-tidy, compiler, or overlay rules rather than a portable principle skill
Keep this skill focused on portable C++ engineering judgment.
include-order rules in repo config or repo docs
platform/vendor bundles in repo config or overlays, not here
overlay
clang-tidyconfig or the reference note rather than adding it to the main skill
shorthand notes before editing.
existing code and tests. Ask only when multiple plausible C++ designs would change semantics.
lifetime, or error-handling contracts.
targets the repo supports.
Use this instead of the default implementation workflow when the task is primarily cleanup or restructuring:
a time.
behavior is unclear.
When reviewing (not implementing), skip the implementation workflow and use this instead:
Critical > Important >Suggestion.
error-path holes, thread-safety issues, security risks, performance mistakes with real impact, and missing tests.
Read these by failure theme, not as an exhaustive checklist.
raw pointer or reference
new and delete; bind resource lifetime to object lifetime with RAIIstd::unique_ptr by default; use std::shared_ptr only for realshared lifetime and std::weak_ptr to break cycles
simple
function, justify it
establish invariants instead of relying on later “remember to initialize” steps
temporaries or short-lived owners; when the lifetime proof is not obvious, return or store an owning value instead
reassign, or call operations whose post-move contract is explicit
boundaries with borrowed state unless the lifetime proof is explicit
.at(), iterators, range-for, orstd::span when bounds are uncertain
std::cmp_*, std::in_range,or a deliberate common type when integer domains differ
express the rule
static_cast, const_cast, reinterpret_cast, anddynamic_cast deliberately
std::bit_cast or byte-wise copy for object-representationreinterpretation; do not use reinterpret_cast where aliasing or lifetime rules make the behavior fragile
memset/memcpy tricks, or pointer arithmetic onnon-trivial, polymorphic, or lifetime-sensitive types
const and constexpr by default; mutability should be the exceptionenum class over plain enums and nullptr over NULLstd::array over C arrays, std::string_view for non-owning strings,and std::span for non-owning ranges when lifetime rules are clear
numeric conversion, or OS/library APIs when failure changes behavior
[[nodiscard]] when ignoring a result is likely a bugunits, or semantics would otherwise be implicit
ambiguous or silently select the wrong overload
override, avoid nearmisses, and do not rely on shadowing or signature accidents
parameter names, qualifiers, defaults, and ownership cues should not drift
objects, or strong typedefs are often clearer than comments
sentinels hard to confuse
relying on comments, magic values, or positional conventions
using namespace std in headersprefer language features unless a macro is the least-bad tool
that quietly change ODR or rebuild behavior
cycles, and transitive-include dependence are design smells
constinit for non-local static or thread-local objects that must notrely on dynamic initialization
hidden global initialization side effects
threads or ad hoc stop flags; std::jthread and std::stop_token are good defaults when the codebase already uses standard thread primitives
and views unless the container contract says otherwise
filesystem, process state, or ambient globals when the domain does not require those dependencies
std::optional, std::variant, andstd::expected when they encode real domain states better than sentinels or ad hoc conventions
intent clearer
legacy-C-leaning, or handwritten utilities when the replacement is clearer and already acceptable in the repo toolchain
Load references/cpp-advanced-design-judgment.md when the task involves public APIs, error-model choices, advanced language features, template-heavy interfaces, headers with broad rebuild impact, coroutines, synchronization strategy, ABI/plugin/C interop boundaries, or abstraction design. Keep ordinary feature work in the default rules above.
Use the full clang-tidy catalog as a source of recurring failure modes, not as a portable checklist to paste into every repo.
bugprone, cppcoreguidelines, modernize, performance, misc,portability, and the CERT/HIC++ aliases as high-signal prompts for code review and refactoring
include order, formatter preferences, test-framework style, platform APIs, and library-pack rules belong in repo config or overlays
clang-tidy, read its enabled checks before introducing newpatterns; local suppressions and allowlists often document real constraints
instead of satisfying each warning mechanically
triage of the current clang-tidy check catalog into portable principles, repo-level rules, and non-portable families that should stay out of this skill
deeper guidance for public API design, error models, advanced features, headers, synchronization, and abstraction choices
Use these when the right choice is not obvious:
plan before continuing; the change is bigger than it looks.
redesign the interface or add a one-line contract comment.
expected-style returns within one subsystem unless the boundary is explicit.
the operation offers no-fail, strong, or basic exception safety and structure the code to match.
containers, ownership types, or naming, follow them unless they create a correctness or safety problem.
metaprogramming unless they make the code simpler for this repo's likely maintainers.
exposing implementation detail, narrow the interface before adding more code.
dependencies into public headers, justify the compile-time and rebuild cost.
function needs more than 2-3 meaningful inputs, prefer a named type or helper struct.
or storage boundaries, prefer an owning type unless the lifetime proof is obvious from the interface.
“remember to initialize” step, move that requirement into construction or the type itself.
comments to explain literals, redesign the API before adding more call sites.
unnecessary includes, or hidden initialization, push behavior back behind a source boundary.
touch the real filesystem, or patch globals just to exercise core logic, introduce a seam before adding more behavior.
only when the setup is reused or the test intent becomes unclear.
problem. When narrowness conflicts with correctness or safety, prefer correctness. When it conflicts with style alone, prefer narrowness unless the task is explicitly a cleanup.
adjacent issue while you are in the file.
pain is a pattern; before extracting, check whether a free function, helper type, or composed object is the simpler move.
ownership, allocation, or algorithmic mistakes on hot paths.
lifetime, aliasing, or memory-order assumptions as high-risk until proven by evidence and tooling.
A change is done when:
known warning set as baseline debt outside the change
out with a concrete reason
memory safety, threading, or undefined-behavior risk
Critical and Important severity are addressed~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.