Pre-Commit Checks (Full)

SkillDev tools

Pre-commit checks — lint:fix -> build -> test

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Pre-Commit Checks (Full) skill

What this skill tells your AI

The instructions your AI receives, as published by sd0xdev/sd0x-harness in skills/precommit/SKILL.md and read by ahel’s review.

Trigger

  • Keywords: precommit, pre-commit, lint and test, quality gate

When NOT to Use

  • Quick checks without build (use /precommit-fast)
  • Verification loop without lint:fix (use /verify)
  • Just running tests (run directly)

Workflow Steps

StepGoalSafetySkip if Missing
comment_blocksReject over-long comment blocks (@rules/docs-writing.md § Code Comments)read-onlyyes
lint-fixAuto-fix code style issuesread-writeyes
buildVerify compilation succeedsread-onlyyes
test-unitRun full test suiteread-onlyyes

Failure behavior: continue-all (run all steps, report all results)

comment_blocks is a policy step, and the asymmetry is deliberate (POLICY_STEPS in scripts/precommit-runner.js): it can FAIL the run, but it never counts as "validation ran". A run where policy was the only thing that executed still reports ⚠️ NO CHECKS RUN, so a repo whose real checks are pytest/cargo cannot bank a ✅ PASS on a passing comment scan alone. It runs first because it is static and cheap.

Task

Run pre-commit checks: lint:fix -> build -> test

Step 1: Check for runner script

Use Glob to check if .claude/scripts/precommit-runner.js exists in the project root.

  • Found → run: node .claude/scripts/precommit-runner.js --mode full --tail 80
    • If runner emits ## Overall: ✅ PASS, use its output and skip to the Output section.
    • If runner emits ## Overall: ⚠️ NO CHECKS RUN, do NOT treat it as a pass — fall through to Step 2 ecosystem detection so the project's real checks run. The marker means no project validation executed and no policy step failed — every validation step was a skip or unavailable, and any policy step (comment_blocks) either skipped or passed (a FAILING policy step is ❌ FAIL, never this marker — line 30's asymmetry) — whether because the repo declares no runnable checks or because the required tools were not available to the runner (which orchestrates the ecosystem table below itself: it detects pyproject.toml/Cargo.toml/go.mod/… and runs those checks as first-class steps). The runner self-notes its own verdict (review-state.js note precommit pass|fail); on ⚠️ NO CHECKS RUN it notes nothing — the slot is untouched and the reminder persists, which is the correct reading of "nothing validated".
    • If runner fails (## Overall: ❌ FAIL), treat as a real precommit failure (do not silently fallback).
  • NOT foundAuto-install attempt (see precommit-fast for identical auto-install logic), then fallback to Step 2.

Step 2: Fallback (no runner script)

Detect the project ecosystem to run steps manually.

Ecosystem detection:

ManifestEcosystemLint-fixBuildTest
package.jsonNode.js{pm} lint:fix{pm} build{pm} test:ci / test / test:fast / test:unit
pyproject.tomlPythonruff check --fix .pytest tests/unit/
Cargo.tomlRustcargo clippy --fixcargo buildcargo test
go.modGogolangci-lint run --fixgo build ./...go test ./...
build.gradle / build.gradle.ktsJava (Gradle)./gradlew spotlessApply./gradlew build./gradlew test
pom.xmlJava (Maven)mvn spotless:applymvn compilemvn test
GemfileRubybundle exec rubocop -abundle exec rspec

How the runner executes this table (WB2b): a required tool missing from the environment (ruff, pytest, cargo, go, golangci-lint, mvn, bundle, the gradle wrapper — the runner never falls back to a global gradle) marks that step unavailable, which blocks ✅ PASS — incomplete validation must not let a sibling check mint the receipt. A repo-declared capability absent is an ordinary skip, but only on definitive non-membership evidence — never a manifest grep, and never an ambiguous probe failure (broken build config, broken task, network-dependent resolution), which stays unavailable: Ruby rubocop/rspec membership is read from Gemfile.lock text — rspec counts rspec or its executable provider rspec-core — after bundle check passes (a failing bundle check or unreadable lockfile is unavailable); Gradle spotless skips only on Gradle's own Task 'spotlessApply' not found diagnostic from gradlew help --task spotlessApply (a marker-less failure is unavailable — Gradle realizes tasks lazily, so a configured-but-broken task fails the probe exactly like an absent one); Maven spotless skips only on the No plugin found for prefix marker from mvn help:describe -Dplugin=spotless — any other failure is unavailable. All probes are bounded (PRECOMMIT_PROBE_TIMEOUT_MS, default 120s; output capped) and logged; a probe timeout is unavailable, never a skip. Python tests run pytest tests/unit/ when that directory exists, else bare pytest (config-driven discovery — a repo with no tests fails loudly on exit 5 instead of silently skipping). Clippy runs with --allow-dirty --allow-staged: precommit operates on a dirty tree by definition.

For Node.js projects, auto-detect package manager from lockfile.

Steppackage.json scriptIf missing
lint:fixlint:fixSkip with note
buildbuildSkip with note
testtest:citesttest:fasttest:unitSkip with note

After lint:fix completes, run git diff --name-only to capture auto-fixed files.

After a conclusive fallback run, self-note the outcome — the runner cannot see a run it did not perform, and the rounds count stays path-independent (a failure is a failure whichever engine ran it):

CHECKER=".claude/scripts/review-state.js"; [ -f "$CHECKER" ] || CHECKER="scripts/review-state.js"
node "$CHECKER" note precommit pass   # every executed check passed
node "$CHECKER" note precommit fail   # the checks ran and at least one failed

An inconclusive run (the checks could not execute at all) notes nothing — exactly like the runner's ⚠️ NO CHECKS RUN: the slot stays untouched and the reminder persists. The note is advisory; a failed note is reported and never fails the run.

Output

## Precommit (full)

## Results

| Step | Status | Notes |
|------|--------|-------|
| lint:fix | ✅/❌/⏭️/⛔ | ⏭️ = repo opted out (skip); ⛔ = required tool unavailable (blocks PASS) |
| build | ✅/❌/⏭️/⛔ | same legend |
| test | ✅/❌/⏭️/⛔ | same legend |

## Changed Files (after lint:fix)

- <files or "(none)">

## Overall: ✅ PASS / ❌ FAIL / ⚠️ NO CHECKS RUN (no project validation executed AND no policy step failed — validation steps all skipped/unavailable, policy steps skipped or passed; fall through to Step 2, needs human if nothing runnable exists)

## Checklist

- [ ] All available checks pass
- [ ] git status reviewed

Signals

GitHub stars
188
Forks
24
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
precommit-sd0xdev
Source
github.com/sd0xdev/sd0x-harness