| name | standards-check |
| description | Use after every implementation subtask, build iteration, or when asked to audit changed code. Runs pre-commit gate, then reviews against project-specific constraints from ADRs and CLAUDE.md. Invoke when the user says "check standards", "audit code", "ADR compliance", or "standards check". |
| argument-hint | [git-ref or file...] |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
| disable-model-invocation | false |
Standards Check — Pre-Commit Gate + Constraint Review
Argument received (optional): $0 — a commit range (e.g. HEAD~1..HEAD,
master..HEAD), specific files, or empty (defaults to uncommitted changes).
This skill runs a fast pre-commit gate followed by a project-constraint review.
Use after every implementation subtask and build iteration.
Use the script
Instead of running individual grep commands, use the standards check script:
scripts/check-standards.sh [git-ref] [file...]
Examples:
scripts/check-standards.sh
scripts/check-standards.sh HEAD~1..HEAD
scripts/check-standards.sh master..HEAD
Output: JSON to stdout with per-check results, file:line references, and overall verdict. Human-readable progress goes to stderr.
JSON output schema:
{
"script": "check-standards",
"timestamp": "2026-05-25T12:00:00Z",
"verdict": "PASS|BLOCK|WARN",
"files_checked": ["lib/foo/src/foo.c", "lib/foo/include/foo/foo.h"],
"pre_commit": {"status": "PASS|FAIL", "output": "..."},
"checks": [
{"id": "heap", "name": "No heap allocations", "rule": "ADR-002, ADR-003", "status": "COMPLIANT|VIOLATION|N/A", "matches": [], "severity": "BLOCKING"},
{"id": "zbus-chan", "name": "ZBUS_CHAN_DEFINE in headers", "rule": "ADR-002", "status": "COMPLIANT|VIOLATION|N/A", "matches": [], "severity": "BLOCKING"},
{"id": "printk", "name": "printk in non-test code", "rule": "CLAUDE.md", "status": "COMPLIANT|VIOLATION|N/A", "matches": [], "severity": "BLOCKING"},
{"id": "bus-api", "name": "Bus API without _dt suffix", "rule": "CLAUDE.md", "status": "COMPLIANT|VIOLATION|N/A", "matches": [], "severity": "BLOCKING"},
{"id": "zbus-rc", "name": "Unchecked zbus return values", "rule": "ADR-002", "status": "COMPLIANT|VIOLATION|N/A", "matches": [], "severity": "WARN"},
{"id": "kconfig-comp", "name": "Kconfig-only composition", "rule": "ADR-008", "status": "COMPLIANT|VIOLATION|N/A", "matches": [], "severity": "BLOCKING"}
],
"blocking": [],
"warnings": [],
"summary": "All checks passed."
}
Exit codes: 0 = PASS, 1 = BLOCK, 2 = WARN
Checks performed
The script runs these constraint scans:
| ID | Check | Rule | Severity |
|---|
heap | No malloc/free/k_malloc/k_free/k_calloc | ADR-002, ADR-003 | BLOCKING |
zbus-chan | ZBUS_CHAN_DEFINE only in .c files | ADR-002 | BLOCKING |
printk | No printk in src/ or lib/ | CLAUDE.md | BLOCKING |
bus-api | Use _dt variants (i2c_write_dt, spi_transceive_dt) | CLAUDE.md | BLOCKING |
zbus-rc | Check zbus_chan_pub return values | ADR-002 | WARN |
kconfig-comp | No target_link_libraries in app CMakeLists.txt | ADR-008 | BLOCKING |
Step 3 — Load project constraints
Read these files to understand the enforcement rules:
CLAUDE.md — the "Architecture rules" and "Embedded C coding rules" sections
docs/architecture/architecture-constraints.md — the ADR constraint table (auto-generated by /arch-sync)
These are the actual project constraints. Do not invent hypothetical rules.
Every check above derives from a named ADR or a rule in CLAUDE.md.
If architecture-constraints.md doesn't exist or is stale, invoke /arch-sync first to regenerate it, then proceed.
Step 4 — ADR constraint cross-reference
Read docs/architecture/architecture-constraints.md (generated by /arch-sync).
For each constraint that applies to a changed file, answer: does the change comply?
Mechanical checklist — derive from the constraints file, not this hardcoded table:
Read the "Active Constraints" table from architecture-constraints.md. For each row,
check whether any changed file touches the constrained area.
Common checks (always verify):
| Constraint (ADR) | Check |
|---|
| ADR-002 zbus ownership | Is ZBUS_CHAN_DEFINE only in .c files? |
| ADR-003 flat struct | Does any new env_sensor_data usage add pointers/heap? |
| ADR-004 trigger-driven | Is there any new polling loop or sensor manager? |
| ADR-005 fake sensor UIDs | Are fake sensor UIDs in range 0x0001–0x00FF? |
| ADR-008 Kconfig composition | Any target_link_libraries() in app CMakeLists.txt? |
Mark each: COMPLIANT, N/A (constraint doesn't touch changed files), or VIOLATION.
Important: Do not hardcode the constraint table. Read it from architecture-constraints.md each time. New ADRs may add constraints that are not listed in the common checks above.
Step 5 — Write the report
Derive a timestamp:
date -u +%Y-%m-%dT%H%M%S
Create docs/reviews/ if it doesn't exist, then write:
docs/reviews/standards-<timestamp>.md
Report template
# Standards Check — YYYY-MM-DD HH:MM UTC
**Files checked:**
- path/to/file1.c
- path/to/file2.h
**Diff size:** N files, M lines changed
## Pre-commit gate
**PASS** | **FAIL (N failures)** — <list failures>
## Blocking Issues (must fix)
<!-- Each issue: file:line — rule — explanation — suggested fix -->
<!-- If none: "No blocking issues found." -->
## Warnings (should fix)
<!-- Each: file:line — rule — observation — suggestion -->
## ADR Constraint Compliance
| Constraint | Status | Evidence |
|---|---|---|
| ADR-002 zbus ownership | COMPLIANT | ZBUS_CHAN_DEFINE only in .c files |
| ADR-003 flat struct | N/A | No env_sensor_data changes |
| ADR-004 trigger-driven | COMPLIANT | No polling loops or sensor managers |
| ... | ... | ... |
## Verdict
**PASS** | **PASS WITH WARNINGS** | **BLOCK**
Keep reports concise:
- PASS: under 150 words
- BLOCK: under 400 words
- One-sentence per issue
Red Flags — STOP and re-check
| Feeling | Reality |
|---|
| "Should pass" / "probably fine" / "looks correct" | You didn't run the verification |
| Claiming PASS without checking ALL ADR constraints | Mark each constraint explicitly |
| Marking ADR constraints as N/A without checking the diff | Verify each one against the actual changes |
| Using "looks fine" / "seems compliant" / "should be okay" | Evidence or nothing |
| Skipping Step 3 (constraint loading) because "I remember them" | Re-read them each time |
| Any wording implying compliance without having RUN the verification | No evidence = no claim |
Rules
- READ-ONLY: Never modify code during a standards check.
- Fast path for docs: If the diff only touches
docs/, run pre-commit and skip Steps 4-5 — only ADR-005 (UIDs in docs) might apply.
- Silence is success. If all constraint scans pass, the report is a quick PASS.
- Be mechanical, not judgmental. This skill checks compliance against named rules. It does not reason about intent or design quality — that's what
/review is for.
- Load constraints from the generated file. Read
docs/architecture/architecture-constraints.md each time. Do not hardcode the constraint table — new ADRs may have been added since the last check.
Terminal state: Report written to docs/reviews/standards-<timestamp>.md with an explicit verdict (PASS / PASS WITH WARNINGS / BLOCK).
Next steps
- If PASS → proceed to
/review for code review
- If PASS WITH WARNINGS → fix warnings, then proceed
- If BLOCK → fix blocking issues, re-run this skill