cpp-cert
Use when: reviewing, designing, implementing, or debugging C/C++ for SEI CERT secure-coding violations detected by clang-tidy cert-* checks: unchecked standard-library return values, command injection via system()/popen(), raw memory operations on non-trivial types, pointer arithmetic on polymorphic objects, exception throw/copy safety, signal-handler async-safety, predictable or unseeded RNGs, deprecated unsafe C functions, and other undefined-behavior or security-sensitive constructs.
Works with
--- name: cpp-cert description: Use when: reviewing, designing, implementing, or debugging C/C++ for SEI CERT secure-coding violations detected by clang-tidy cert-* checks: unchecked standard-library return values, command injection via system()/popen(), raw memory operations on non-trivial types, pointer arithmetic on polymorphic objects, exception throw/copy safety, signal-handler async-safety, predictable or unseeded RNGs, deprecated unsafe C functions, and other undefined-behavior or security-sensitive constructs. license: MIT --- # C++ CERT Secure Coding Use this skill when C or C++ code may violate a SEI CERT C/C++ Coding Standard rule: a construct that is undefined, unspecified, security-sensitive, or error-prone by the standard's secure-coding criteria, even when it compiles cleanly and appears to work. The goal is to make every CERT-relevant construct either compliant or explicitly justified: standard-library errors are checked, exceptions are safe to throw and copy, special members defend against misuse, signal handlers and threads stay within async-safe bounds, and no deprecated or undefined-behavior-prone API is used without a documented exception. **UTILITY SKILL.** INVOKES: read-only file access for supplied targets; no other tools or skills. FOR SINGLE OPERATIONS: use for focused CERT-rule review, secure-coding design, or violation triage. The clang-tidy `cert-*` checks are the canonical catalog this skill encodes. Some are standalone `cert-*` checks; others are aliases of `bugprone-*`/`misc-*`/`concurrency-*` checks. Cite the canonical `cert-<id>` check name in findings (it resolves whether the check is standalone or an alias) alongside the CERT rule ID, so the reader can cross-reference the standard and optionally automate detection. Check names below are valid as of clang-tidy 18-20; confirm against the analyzer version in use. ## Scope - Use this skill for the CERT rules clang-tidy can detect: modifying the `std`/`posix` namespaces (DCL58-CPP), reserved identifiers (DCL37-C/DCL51-CPP), paired allocation/deallocation overloads (DCL54-CPP), runtime `assert` where `static_assert` would work (DCL03-C), C-style variadic functions (DCL50-CPP), unnamed namespaces in headers (DCL59-CPP), non-uppercase literal suffixes (DCL16-C), unchecked standard-library return values (ERR33-C), unchecked string-to-number conversion (ERR34-C), `setjmp`/`longjmp` (ERR52-CPP), exceptions escaping before `main` (ERR58-CPP), throwing exception types whose copy constructor can throw (ERR60-CPP), throw-by-value/catch-by-reference (ERR09-CPP/ERR61-CPP), float loop counters (FLP30-C), signed-char-to-larger-integer conversion (STR34-C), comparing padding or object representations (EXP42-C/FLP37-C), assignments in selection statements (EXP45-C), inconsistent enumerator initialization (INT09-C), raw `memset`/`memcpy`/`memcmp` on non-trivial types (OOP57-CPP), default `operator new` for over-aligned types (MEM57-CPP), unguarded self-assignment (OOP54-CPP), copy constructors that mutate their argument (OOP58-CPP), move constructors that copy a base/member (OOP11-CPP), pointer arithmetic on polymorphic objects (CTR56-CPP), adding a scaled integer to a pointer (ARR39-C), copying `FILE`/`pthread_mutex_t` objects (FIO38-C), `system()`/`popen()` (ENV33-C), deprecated/unsafe C functions (MSC24-C/MSC33-C), `std::rand` for pseudorandom numbers (MSC50-CPP/MSC30-C), unseeded or constant-seeded RNGs (MSC51-CPP/MSC32-C), spurious-wakeup wait loops (CON54-CPP/CON36-C), signal-handler async-safety (SIG30-C/MSC54-CPP), terminating threads with signals (POS44-C), and asynchronous thread cancellation (POS47-C). - Apply it to API boundaries, class special-member design, error-handling paths, exception types, signal handlers, threading/cancellation code, and any use of C standard-library or POSIX functions. - Keep the review centered on CERT-rule compliance. A finding must map to a specific CERT rule and the concrete undefined/unsafe behavior the standard cites; general style preferences are out of scope. ## DO NOT USE FOR: - Performance tuning with no security/correctness dimension (out of scope: general copy/allocation-cost work), general object-lifetime/dangling analysis not tied to a CERT rule (out of scope: ownership/lifetime review), or data-race and synchronization-correctness review beyond the specific CERT concurrency rules listed (out of scope: general concurrency review). Name the out-of-scope concern and route it instead of judging it here. - CERT rules that clang-tidy cannot mechanically detect and that require full program analysis (e.g. complete taint tracking, integer-overflow proofs across translation units); name the rule and recommend dedicated analysis rather than asserting compliance. - Coroutine mechanics, build/link configuration, or correctness review with no CERT-rule mapping. ## Required Context Collect or infer before judging: - Target: files, diff, API, class definition, or function under review, and the language/standard (C vs C++, and the C++ version, since some rules - e.g. signal-handler constraints - depend on it). - Type and member shape: for classes, whether they own resources (raw pointers, `FILE*`, mutexes), have user-defined copy/move/assignment, are used as exception types, or are over-aligned. - API surface in use: which C standard-library/POSIX functions are called, whether return values are consumed, and whether Annex K bounds-checked variants are available. - Execution context: whether code runs in a signal handler, before `main` (static/global initializers), in a thread that may be cancelled or terminated, or as a condition-variable wait. - Existing tests and any suppressions (`NOLINT`, cast-to-void) already applied to CERT findings. If the target cannot be seen, or the language/standard cannot be established for a standard-dependent rule, return `Verdict: BLOCK` with one open question. Do not guess whether a type is trivially copyable, whether a function's return value matters, or whether code runs in a signal handler. Insufficient-context mode takes precedence over pattern-level decision rules: general rules may be cited as context, but no verdict other than `BLOCK` may rest on an unseen target or an undetermined execution context. ## Output Depth Default to `standard`. `quick` still reports missing required context, blockers, unmitigated HIGH/CRITICAL findings, and target-specific concerns; it only omits non-applicable checklist expansion. `standard` covers the applicable checklist with concise evidence. `exhaustive` enumerates the full checklist only when asked or when the change surface warrants it. Name the selected depth when the user asks for `quick` or `exhaustive`. ## Workflow 1. Establish context: language, C++ standard, and whether any code runs in a signal handler, before `main`, or in cancellable/terminable threads. 2. Audit declarations and namespaces: `std`/`posix` modifications, reserved identifiers, paired `new`/`delete` overloads. 3. Audit error handling: unchecked library return values, unchecked string-to-number conversions, exception escape before `main`, exception copy-constructor safety, throw/catch value category, `setjmp`/`longjmp`. 4. Audit memory and object operations: raw `mem*` calls on non-trivial types, over-aligned `operator new`, self-assignment guards, copy constructors that mutate the source, pointer arithmetic on polymorphic objects, copying `FILE`/mutex objects. 5. Audit expressions and types: float loop counters, signed-char-to-int conversions, comparison of padding/object representations. 6. Audit concurrency and signals: spurious-wakeup wait loops, signal-handler async-safety, thread termination by signal, asynchronous cancellation. 7. Audit security-sensitive API: `system()`/`popen()`, deprecated/unsafe C functions, `std::rand`, unseeded/constant-seeded RNGs. 8. For each finding, map it to its CERT rule, classify by severity, map to a verdict, and state the regression test or suppression justification each fix needs. ## Decision Rules The Checklist below is the gating source of truth when these rules overlap; the rules explain rationale. Each rule names the CERT rule ID and the clang-tidy check it encodes. The subheadings match the Checklist sections so a rule and its gating item are found together. Cross-cutting suppression rule: a CERT finding may be downgraded only by a documented, rule-specific exception (a CERT "exception" clause, an explicit `NOLINT` with rationale, or a cast-to-void for an intentionally ignored return where the rule permits it). An undocumented suppression is itself a finding. ### Declarations And Namespaces - When code adds declarations to namespace `std` or `posix` (other than the permitted explicit specializations of user-defined-type templates), it is undefined behavior - remove the modification (DCL58-CPP, `cert-dcl58-cpp`). - When an identifier uses a reserved form (leading underscore + uppercase or double underscore, or names reserved by the implementation), rename it (DCL37-C/DCL51-CPP, `cert-dcl37-c`/`cert-dcl51-cpp`). - When a class overloads a non-placement `operator new`, it must overload the corresponding `operator delete` in the same scope, and vice versa - add the missing partner (DCL54-CPP, `cert-dcl54-cpp`). - When a runtime `assert` tests a condition that is constant at compile time, use `static_assert` instead - it fails the build rather than at run time (DCL03-C, `cert-dcl03-c`). - When a function is defined as a C-style variadic (`...`) function, replace it with a C++ variadic template / parameter pack, which is type-safe (DCL50-CPP, `cert-dcl50-cpp`). - When an unnamed (anonymous) namespace appears in a header, every translation unit including it gets distinct symbols, risking ODR violations and bloat - move it to a source file or use `inline`/named entities (DCL59-CPP, `cert-dcl59-cpp`). - When an integer or floating-point literal uses a lowercase `l`-family suffix (`l`, `ll`, `lu`, `llu`), uppercase it (`L`, `LL`, ...) so it cannot be misread as a digit `1` (DCL16-C, `cert-dcl16-c`). ### Error Handling And Exceptions - When a checked standard-library function's return value is ignored, consume it and handle the error; if intentionally discarded and the rule permits, cast to `void` with a comment (ERR33-C, `cert-err33-c` - ships a CERT-specified function list; the related `bugprone-unused-return-value` is a separate, user-configured check with different defaults). - When converting a string to a number with `atoi`/`atol`/`atoll`/`scanf`-family without error checking, use `strtol`-family (or C++ facilities) and check the result (ERR34-C, `cert-err34-c`). - When `setjmp`/`longjmp` is used, replace it with structured control flow or C++ exceptions; `longjmp` across automatic objects does not run destructors and is undefined in many cases (ERR52-CPP, `cert-err52-cpp`). - When a `static`/`thread_local` object's initializer can throw, an exception thrown before `main` cannot be caught and calls `std::terminate` - make the initializer non-throwing or defer it (ERR58-CPP, `cert-err58-cpp`). - When a type is thrown as an exception, its copy constructor must not throw (a throwing copy during exception propagation calls `std::terminate`) - make the exception type's copy constructor `noexcept` (ERR60-CPP, `cert-err60-cpp`). - When throwing, throw an anonymous temporary by value; when catching a non-trivial type, catch by reference, to avoid slicing and extra copies (ERR09-CPP/ERR61-CPP, `cert-err09-cpp`/`cert-err61-cpp`). ### Memory And Object Operations - When `memset`/`memcpy`/`memmove`/`memcmp` (or `str*` equivalents) is applied to a non-trivial type, use the type's constructors, assignment, and comparison operators instead; raw byte operations bypass invariants and vtables (OOP57-CPP, `cert-oop57-cpp`). - When allocating an over-aligned type (alignment greater than fundamental) via the default `operator new`, the returned storage may be under-aligned - provide an aligned allocation path (MEM57-CPP, `cert-mem57-cpp`). - When a user-defined copy assignment operator on a class with a pointer/array/owning field does not guard against self-assignment, add a self-check or use copy-and-swap / copy-and-move (OOP54-CPP, `cert-oop54-cpp`). - When a copy constructor mutates its source argument, the copy is not a copy - make the source parameter `const` and copy without modifying it (OOP58-CPP, `cert-oop58-cpp`). - When a move constructor's mem-initializer list initializes a base or member through its copy constructor instead of its move constructor, it silently copies - move the base/member (OOP11-CPP, `cert-oop11-cpp`; the broader move-semantics-cost rationale is general performance work, mapped here only for the CERT rule). - When pointer arithmetic is performed on a pointer whose static type declares a virtual function, the dynamic type may have a different size, giving undefined behavior - index through the correct dynamic type or make the leaf type `final` (CTR56-CPP, `cert-ctr56-cpp`). - When a value already scaled by `sizeof`/`alignof`/`offsetof` is added to or subtracted from a pointer, the arithmetic scales it again by the pointee size, producing a doubly-scaled (often out-of-bounds) address - add the element count directly, not the byte count (ARR39-C, `cert-arr39-c`). - When a `FILE` or `pthread_mutex_t` object is declared by value or dereferenced as a value, it must not be copied - hold and pass it only through a pointer (FIO38-C, `cert-fio38-c`). ### Expressions And Types - When a floating-point variable is used as a loop counter, accumulated rounding makes the iteration count unpredictable - use an integer counter (FLP30-C, `cert-flp30-c`). - When a `signed char` is converted to a wider integer (assignment, comparison with `unsigned char`, or array subscript), cast through `unsigned char` first so non-ASCII bytes do not become negative (STR34-C, `cert-str34-c`). - When `memcmp` compares whole-object representations of types with padding, non-standard layout, or floating-point members, compare value representations field-by-field instead - padding and `-0.0/NaN` bits make the byte comparison wrong (EXP42-C/FLP37-C, `cert-exp42-c`/`cert-flp37-c`). - When an assignment (`=`) appears inside an `if` condition where a comparison (`==`) was probably meant, use `==`, or wrap a deliberate assignment in extra parentheses (EXP45-C; clang-tidy's `bugprone-assignment-in-if-condition` covers `if` conditions only and there is no dedicated `cert-exp45-c` check, so loop-condition and logical-operand cases need manual review). - When an enum mixes explicitly-initialized and implicitly-valued enumerators, two enumerators can silently collide; initialize none, only the first, or all enumerators consistently (INT09-C, `cert-int09-c`). ### Concurrency And Signals - When `wait`/`wait_for`/`wait_until`/`cnd_wait`/`cnd_timedwait` is called outside a loop that re-checks the condition predicate (or without a predicate argument), wrap it so spurious wakeups cannot proceed past an unmet condition (CON54-CPP/CON36-C, `cert-con54-cpp`/`cert-con36-c`). - When a signal handler calls non-async-signal-safe functions, uses C++-only constructs, or has non-C linkage, restrict it to async-safe functions and a plain C-linkage POD function (SIG30-C/MSC54-CPP, `cert-sig30-c`/`cert-msc54-cpp`; some C++-specific diagnostics are standard-dependent, so confirm the check's behavior for the target standard rather than assuming it is fully active or fully off). - When a thread is terminated by sending `SIGTERM` via `pthread_kill`, it kills the whole process - use a different mechanism or signal (POS44-C, `cert-pos44-c`). - When `pthread_setcanceltype` sets `PTHREAD_CANCEL_ASYNCHRONOUS`, switch to `PTHREAD_CANCEL_DEFERRED`; async cancellation can interrupt at an unsafe point (POS47-C, `cert-pos47-c`). ### Security-Sensitive API - When `system()` or `popen()`/`_popen()` runs a command processor (with a non-null command), replace it with a direct exec API that does not invoke a shell - it is a command-injection vector (ENV33-C, `cert-env33-c`). - When a deprecated or non-bounds-checked C function (`strcpy`, `strcat`, `sprintf`, `gets`, `asctime`, ...) is used, replace it with its bounds-checked Annex K variant or a safe alternative and check the result (MSC24-C/MSC33-C, `cert-msc24-c`/`cert-msc33-c`). - When `std::rand()`/`rand()` is used to generate pseudorandom numbers, use a `<random>` engine with proper distribution; `rand` has poor statistical quality and is unsuitable for security (MSC50-CPP/MSC30-C, `cert-msc50-cpp`/`cert-msc30-c`). - When a random-number engine is default-constructed, seeded with a constant, or left unseeded, seed it from a non-deterministic source (e.g. `std::random_device`) (MSC51-CPP/MSC32-C, `cert-msc51-cpp`/`cert-msc32-c`). ## Checklist ### Declarations And Namespaces - No declarations are added to `std`/`posix` except permitted user-type template specializations; no reserved identifiers are declared. - Every non-placement `operator new`/`operator delete` overload has its matching partner in the same scope. - Compile-time-constant assertions use `static_assert`, not runtime `assert`; no C-style variadic function definitions; no unnamed namespaces in headers; literal suffixes are uppercase. ### Error Handling And Exceptions - Checked standard-library return values are consumed and errors handled, or intentionally discarded with a documented cast-to-void. - String-to-number conversions check for failure; no `setjmp`/`longjmp`. - Static/global initializers cannot throw uncaught before `main`; exception types have non-throwing copy constructors; exceptions are thrown by value and caught by reference. ### Memory And Object Operations - No raw `mem*`/`str*` byte operations on non-trivial types; over-aligned types use aligned allocation. - Copy assignment guards against self-assignment; copy constructors do not mutate their source; move constructors move (not copy) their bases and members. - No pointer arithmetic on polymorphic-object pointers whose dynamic type may differ, and no `sizeof`/`offsetof`-scaled value added to a pointer; `FILE`/mutex objects are handled only by pointer. ### Expressions And Types - Loop counters are integers, not floating-point. - `signed char` is cast through `unsigned char` before widening; no representation/padding comparison via `memcmp` on padded/non-standard-layout/float types. - No assignment in a selection/loop condition where comparison was intended; enumerator initialization is consistent (none, first only, or all). ### Concurrency And Signals - Condition waits are wrapped in predicate-checking loops. - Signal handlers are async-safe, plain C-linkage, and free of C++-only constructs (for the applicable standard); threads are not terminated with `SIGTERM`; cancellation type is deferred, not asynchronous. ### Security-Sensitive API - No `system()`/`popen()` command-processor calls; deprecated/unsafe C functions are replaced with bounds-checked alternatives and checked. - Pseudorandom numbers use `<random>` with a properly seeded engine, not `std::rand` or an unseeded/constant-seeded generator. ### Suppressions And Tests - Every downgraded or suppressed CERT finding has a documented, rule-specific justification. - Each fixed violation has a regression test or static-analysis assertion that fails without the fix where one is feasible. ## Severity And Verdicts Severity reflects the CERT risk class and exploitability/UB reachability, not just pattern presence. - `CRITICAL`: a reachable violation that is undefined behavior or a direct security vulnerability in normal operation (command injection via `system()`, `longjmp` skipping destructors on a live path, `memcpy` over a polymorphic object, pointer arithmetic on a polymorphic pointer with differing dynamic type, signal handler calling non-async-safe functions). - `HIGH`: a violation that is UB or a security weakness but requires a specific input, error path, or platform to manifest (unchecked allocation/return value on an error path, throwing exception copy constructor, over-aligned `operator new`, unseeded RNG used for a security decision, unsafe string function with attacker-influenced length). - `MEDIUM`: a latent or context-bounded violation (self-assignment unguarded on a class that is unlikely to self-assign today, `signed char` widening on ASCII-only data, `std::rand` for non-security randomness) that future edits or inputs will amplify. - `LOW`: a hardening or hygiene issue (reserved-identifier naming, throw-by-value/catch-by-reference style where copies are cheap) with no current UB or security path. Verdicts: - `BLOCK`: missing required context, any `CRITICAL`, or any unmitigated `HIGH`. - `CONCERNS`: remaining `HIGH`/`MEDIUM` findings each have a documented exception, compensating control, or bounded reachability. - `CLEAN`: every applicable checklist item holds and fixed violations have regression coverage where feasible. For design-stage or definition-only targets with no tests yet, the best achievable verdict is `CONCERNS` with test expectations recorded per finding. A CERT finding must never be silently dropped because a fix is inconvenient: if remediation conflicts with a hard external constraint, record the residual risk and the documented exception rather than asserting compliance. ## Output Format ```text Verdict: BLOCK | CONCERNS | CLEAN Target: <files, diff, API, class, or function> Language/standard: <C or C++ and version, or unknown> Execution context: <signal handler | pre-main init | cancellable thread | normal, or unknown> Findings: 1. <short title> Severity: CRITICAL | HIGH | MEDIUM | LOW Classification: Confirmed violation | Likely violation | Open question | Documented exception | Test gap Evidence: <file:line, diff hunk, or design sentence> Rule: <declarations-namespaces | error-handling-exceptions | memory-object-operations | expressions-types | concurrency-signals | security-api | suppressions-tests> CERT: <CERT rule ID and clang-tidy check name, or N/A> Risk: <the undefined or unsafe behavior the standard cites, and when it triggers> Required fix: <the compliant construct> Test expectation: <regression test, static-analysis assertion, or N/A> Checklist status: - Declarations and namespaces: covered | missing | n/a - Error handling and exceptions: covered | missing | n/a - Memory and object operations: covered | missing | n/a - Expressions and types: covered | missing | n/a - Concurrency and signals: covered | missing | n/a - Security-sensitive API: covered | missing | n/a - Suppressions and tests: covered | missing | n/a Residual risk: <remaining caveats, deferred cross-skill questions, or None> ``` `Rule:` values map to checklist sections as follows: `declarations-namespaces` -> Declarations And Namespaces; `error-handling-exceptions` -> Error Handling And Exceptions; `memory-object-operations` -> Memory And Object Operations; `expressions-types` -> Expressions And Types; `concurrency-signals` -> Concurrency And Signals; `security-api` -> Security-Sensitive API; `suppressions-tests` -> Suppressions And Tests. When no material issues exist, write exactly `Findings: None` (allowed only with `CLEAN`) and list assumptions under Residual risk. For definition-only or design-stage targets that earn `CONCERNS` solely because tests cannot exist yet, emit one `Test gap` finding with `Rule: suppressions-tests` listing the required test expectations instead of an empty findings list. Insufficient-context mode: when the target cannot be seen or a standard-dependent rule's language/context cannot be established, emit exactly this reduced template and stop; do not emit execution context or checklist status with guessed values: ```text Verdict: BLOCK Target: <files, diff, API, class, or function> Findings: 1. <missing-context short title> Severity: LOW Classification: Open question Evidence: <which required context is missing> Rule: <declarations-namespaces | error-handling-exceptions | memory-object-operations | expressions-types | concurrency-signals | security-api> CERT: <CERT rule ID and clang-tidy check name, or N/A> Risk: <why no safe conclusion is possible> Required fix: <what context must be supplied> Test expectation: N/A ``` ## Examples - Unchecked return: `malloc(n); /* never tested */` ignores a NULL-on-failure result, risking a null dereference. Check the result before use, or cast to `void` only if the allocation is provably unnecessary. (ERR33-C.) - Raw memcpy on a non-trivial type: `std::memcpy(&dst, &src, sizeof(Widget));` where `Widget` has a `std::string` member corrupts the destination. Use copy assignment `dst = src;`. (OOP57-CPP.) - Throwing exception copy: an exception class with a `std::string` member copied by a throwing allocation can call `std::terminate` mid-propagation. Make the copy constructor `noexcept` (store the message in a `shared_ptr<const std::string>`). (ERR60-CPP.) - Command injection: `system(user_supplied)` runs a shell. Replace with `posix_spawn`/`exec*` and an argument vector, no shell. (ENV33-C.) - Polymorphic pointer arithmetic: `Base* b = derived_array; b += 1;` strides by `sizeof(Base)`, not the dynamic type, giving UB. Iterate as the concrete `Derived` type. (CTR56-CPP.) ## Definition Of Done A CERT-related change is ready only when: - Every detected violation is fixed to the compliant construct or carries a documented, rule-specific exception with residual risk recorded. - No standard-library error path is left unchecked, no exception can escape before `main` or throw during copy while propagating, and no banned API (`system`, unsafe C functions, `std::rand` for security, `setjmp`/`longjmp`) remains without justification. - Special members defend against self-assignment and do not mutate their source; no raw byte operations run on non-trivial types; no pointer arithmetic crosses a polymorphic boundary. - Signal handlers, thread termination, and cancellation comply with the applicable CERT concurrency rules for the target's language standard. - Fixed violations have regression tests or static-analysis assertions where feasible; if none were feasible, the Suppressions and tests item is n/a and does not block `CLEAN`. - Any CERT rule requiring analysis beyond clang-tidy's reach, or any cross-skill lifetime/concurrency question, is named and routed rather than assumed compliant.
More Debugging skills
diagnosing-bugs
mattpocock/skills
Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.
explore-code
lllllllama/rigorpilot-skills
Rigor Improve implementation leaf skill for auditable candidate implementation in deep learning research repositories. Use when the researcher explicitly authorizes exploratory work on an isolated branch or worktree to transplant modules, adapt a backbone, add LoRA or adapter layers, replace a head, or stitch together meaningful low-risk migration ideas with rollback-aware records in `explore_outputs/`. Do not use for end-to-end exploration orchestration on top of `current_research`, trusted baseline reproduction, conservative debugging, environment setup, verified contribution claims, or default repository analysis.
safe-debug
lllllllama/rigorpilot-skills
Rigor Debug / Rigor Audit skill for deep learning research work. Use when the user pastes a traceback, terminal error, CUDA OOM, checkpoint load failure, shape mismatch, NaN loss symptom, or training failure and wants conservative diagnosis before any patching, with debug fixes clearly separated from research contributions. Do not use for broad refactoring, speculative adaptation, automatic exploratory patching, or general repository familiarization.

