← the whole session plugin/skills/audit-pre-commit/SKILL.md

Pre-commit audit checklist — verify every diff against the 6 shipping principles before committing. Use before any commit, especially commits that touch user-facing code paths. Triggers: 'pre-commit', 'audit before commit', 'ready to commit', 'check before pushing', 'shipping checklist'.

Audit Pre-Commit

Before committing any code that touches user-facing paths, verify against all 6 shipping principles. In one reference setup each principle has a dedicated companion skill with deeper procedures; if you don't have those installed, the checklist under each principle here is self-contained and still fully checkable on its own.

The 6 Shipping Principles

1. Structured Logging, Not Console.log

Skill (if installed): fix-console-log-hotpath

  • No console.log in controllers, middleware, or route handlers
  • All logs use logger.info(), logger.debug(), logger.warn(), or logger.error()
  • Structured metadata (objects, not string concatenation)
  • console.log is ONLY acceptable inside if (process.env.NODE_ENV === 'development') blocks

2. Feature Flag Before Ship

Skill (if installed): how-to-use-feature-flags

  • New user-facing features start as IN_DEVELOPMENT (admin-only)
  • Feature is gated with isFeatureVisible() (frontend) or checkStagedRelease() (backend)
  • An admin can promote to IN_BETA then IN_PRODUCTION without a deploy
  • No new feature is visible to regular users on first commit

3. No Incomplete Code Ships

Check: Does the diff introduce API routes with no frontend caller? Backend fields with no consumer? Frontend UI that calls endpoints that don't exist yet?

  • Every API route has at least one caller (frontend or test)
  • Every new field on a model is read somewhere
  • If a route/field is intentionally pre-staged, add a // @staged: no caller yet — will be wired in [ticket/PR] comment
  • Dead code from removed features is deleted, not commented out

4. Defensive Coding with logger.error on Failure

Skill (if installed): defensive-error-audit

  • Every user-facing code path has try-catch
  • Catch blocks call logger.error() (backend) or logError() (frontend) with severity + uxImpact
  • Catch blocks NEVER make UX worse — fail-open for paying users, fail-closed only for security
  • No bare catch (e) {} or catch (e) { console.log(e) } — every catch logs structured error data
  • Features that could break UX are wrapped so failure = feature silently disabled, not app crash

5. logger.error Works Everywhere

Check: Does the file use the canonical error logging function?

  • Backend: const logger = require('../utils/logger') — then logger.error(msg, metadata)
  • Frontend: whatever this project's canonical error-logging import is (for example import { logError } from '@utilities/errorLogger' — then logError({ message, error, severity, uxImpact })). If this project has more than one frontend app, each one may have its own import path for the same canonical function — check the one this file's app actually uses.
  • If a file uses console.error instead, it MUST be replaced with the canonical logger
  • logger.error calls always include: message, error object, severity (1-100), uxImpact statement

6. Staggered Release with Rollout Tracking

Skill (if installed): staged-release-management. If you don't use a rollout-tracking product like Statsig, apply the same principle with whatever feature-flag/experiment system this project has.

  • Substantive features that could help OR harm UX use the staged release system
  • Feature starts at 0% rollout, expands via KPI signal score
  • Errors are tagged with stagedReleaseTagged: true and featureKey for circuit breaker
  • KPI bindings defined (engagement, churn, conversion — whichever apply)
  • Autotune/evaluation runs every 5 min — no manual timer-based rollout

7. Added Style Definitions Carry Consumption Intent Sourced From The Person, Not The Agent

Why this exists: A reusable style definition (a CSS class, a design-system template, a design token, a styled-component) is consumed by future agents who never saw the conversation that created it. If it does not say when and how to use it, those agents misapply it or invent hollow comments. The general rule: the intent of the code, and the intent for when and how to use it, must be articulated — and that articulation has to come from what the person you're building for actually said, not from an agent's abstraction of it.

The rule this check enforces: the intent of the code, and the intent for when and how to use it, must be articulated — that's the piece that's easy to skip. When a style definition is added, the intent for when and how to consume it must be articulated too, sourced from the actual person's own statements — not an abstraction of them, not an assumption about them, but what they actually said, plus whatever can be safely derived at ninety percent confidence from that.

What to check — if the staged diff ADDS any style definition (a new CSS class / @layer / selector ruleset in a stylesheet, a new design token / CSS custom property, a new styled / css template, a Tailwind @apply component class):

  • The definition carries a comment articulating the intent of the code — what it is for.
  • The comment articulates WHEN to use it (and, where it matters, when NOT to).
  • The comment articulates HOW to consume it — the actual application mechanics (e.g. which element gets the class, any companion class / marker it depends on to work).
  • That articulated intent is sourced from the actual person's verbatim statements about this style — their actual words, not an agent's abstraction, paraphrase, or assumption. Where their exact words don't cover a detail, only what can be safely derived at >=90% confidence from those words may be added; anything below 90% is left out, not invented.

The patch (when this is missing) — DO NOT auto-generate tidy prose: locate the verbatim utterances that produced this style (this session's transcript, the linked compaction, the originating request). Quote or closely paraphrase those words into the consumption-intent comment at the definition site. If those words don't exist or can't be found, do not fabricate intent — block and surface: "Style definition <name> added without consumption intent sourced from the person you're building for. Capture their actual words on when/how to use it before committing." A comment that describes only WHAT the code does (not when/how to consume it), or one written from agent abstraction rather than the person's own words, FAILS this check.

How to Run This Audit

For each file in git diff --cached --name-only:

  1. Is it a controller, middleware, or route handler? → Check Principle 1 (logging) and Principle 4 (defensive coding)
  2. Does it add a new feature? → Check Principle 2 (feature flag) and Principle 6 (staged release)
  3. Does it add API routes or model fields? → Check Principle 3 (completeness)
  4. Does it have catch blocks? → Check Principle 5 (canonical logger.error)
  5. Does it add a style definition (CSS class/token/template, styled-component, @apply class)? → Check Principle 7 (consumption intent sourced from the person)

Quick Grep Checks

# Principle 1: console.log in hot paths
grep -rn 'console\.log' $(git diff --cached --name-only) 2>/dev/null | grep -v node_modules | grep -v '__tests__'

# Principle 4: bare catch blocks
grep -rn 'catch.*{' $(git diff --cached --name-only) 2>/dev/null | grep -v node_modules

# Principle 5: console.error instead of logger.error
grep -rn 'console\.error' $(git diff --cached --name-only) 2>/dev/null | grep -v node_modules | grep -v '__tests__'

# Principle 7: ADDED style definitions (new CSS class/selector, custom property/token,
# styled-component, or @apply class) in the staged diff. Each hit must carry a
# when/how-to-consume comment sourced from the person.
git diff --cached -- '*.css' '*.scss' '*.js' '*.jsx' '*.ts' '*.tsx' 2>/dev/null \
  | grep -E '^\+' \
  | grep -E '^\+\s*\.[a-zA-Z_-]+\s*\{|^\+\s*--[a-zA-Z-]+\s*:|styled\.[a-z]+`|css`|@apply ' \
  | grep -v node_modules

Commit Message Annotation

After audit passes, include in commit message:

Audit: pre-commit checklist passed (logging, feature-flag, defensive, staged-release, style-intent)