pattern-recognition — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited pattern-recognition (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.
Pattern recognition is the cognitive and methodological discipline of identifying recurring structures across instances — separating signal from noise, naming the structure once detected, and elevating it into durable, transmissible knowledge. Drawing from Gestalt perception (Wertheimer 1923), expert intuition research (Klein 1998 recognition-primed decision; Chase & Simon 1973 chess chunking — masters perceive board positions as small numbers of meaningful patterns), and the software-pattern tradition (Alexander 1977 A Pattern Language; Gamma et al. 1994 Design Patterns), it treats pattern as a class noun: a regularity worth naming because it explains many observations through one structure.
Replaces symptom-by-symptom fixing (which burns tokens and effort without building leverage) with systemic detection-and-prevention that addresses the recurring class. Solves the problem that an agent operating symptom-by-symptom can fix the same bug five times in five different files and never see that the underlying root cause produces another instance next week — while an agent recognizing the pattern can propose a systemic fix, write an automated detection rule, and prevent the entire class from recurring. In a high-velocity agentic environment, manual review scales poorly; pattern recognition lets agents "see" the codebase as a system of rules rather than a collection of files. The eval-as-pattern-test pipeline is the durable artifact — every recognized pattern should become a testable eval so future sessions verify they detect it reliably under new inputs; without the eval, a skill section about "null-vs-zero confusion" may be read and then misapplied on the next input (the agent learned the name but not the detection logic). Closes the loop with prevention: the goal is not detecting the pattern more reliably; it is restructuring the system so the pattern becomes impossible (type constraint, hook, architectural change, lint rule that fails CI).
Distinct from debugging, which fixes one specific bug — this skill identifies the recurring class behind many bugs and proposes a structural fix that prevents the whole class; the same "recurring bug" prompt routes to debugging for the immediate fix and to this skill for the systemic rule. Distinct from code-review, which judges quality of a specific change at PR scope — this skill systematically detects recurring structural issues across the entire codebase; the same "recurring violation in PRs" prompt routes to code-review for blocking the PR and to this skill for adding a lint rule. Distinct from diagnosis, which triages an unknown software failure into a problem class before debugging begins — diagnosis owns per-incident triage; this skill owns cross-incident class analysis. Distinct from refactor, which restructures code once a pattern is identified (refactor enacts the change; this skill decides what needs changing). Distinct from naming-conventions, which establishes the rules themselves (this skill detects violations of rules that already exist). Distinct from lint-overlay, which owns the rule machinery (this skill decides which patterns warrant a rule). Distinct from skill-infrastructure (skill library health tooling and structural-graph audits) and tool-call-strategy (per-action tool selection). Pattern recognition is to a codebase what epidemiology is to a city's public health — a doctor (debugging) treats one patient with one infection; the epidemiologist (this skill) notices that fourteen patients across three hospitals all have the same infection, traces it back to a contaminated water source (root cause), names the outbreak, prescribes a public-health intervention (lint rule, type constraint, architectural fix) that prevents the next thousand cases, and updates the surveillance protocol so the next outbreak is caught at three cases instead of fourteen. The wrong mental model is that every recurring observation is a pattern — that two similar bugs justify a framework, a lint rule, or a refactoring sweep. They do not. The three-instance threshold is load-bearing: one is a bug, two is a coincidence, three is a pattern. Premature codification creates false rules that block valid code and produces "pattern-inflation" (pareidolia — seeing patterns in noise) where the team responds to every coincidence with abstraction. Adjacent misconceptions: that similar symptoms imply a shared root cause (they do not — a cluster of "null reference" errors may have 3 different call sites with 3 different missing guards; verify each cluster member shares a root before proposing a unified fix); that fixing at the symptom level eventually fixes the pattern (it does not — the symptom loop is the most expensive form of pattern work; without the 5-Whys to the root level, every new instance generates a new fix; aim for level 4-5, not level 1-2); that abstractions are always proportional to pattern recurrence (they are not — building a framework or lint plugin for one pattern is over-abstraction; detection should be proportional to frequency: one pattern = grep rule; three patterns = lint plugin; complex wrapper harder to maintain than the duplication is its own anti-pattern); that every match is a violation (it is not — false-positive discipline matters: test fixtures are intentional, token files are exempt, inline // @intentional: comments document legitimate deviations; document exclusion rules in the grep pattern itself, not in memory); that detection rules are evergreen (they are not — patterns have lifecycle states: Active / Fixed / Stale / Migrated; a fixed pattern's detection rule should be archived; a migrated pattern requires dual detection of old AND new violations); and that naming a pattern is enough (it is not — pattern recognition completes the loop through Codify, Detect, Prevent, and ideally Eval; the eval step is non-optional because a skill section documents a pattern for humans, but an eval tests whether an agent applies the pattern reliably under new inputs).
The methodology for identifying recurring structures across code, errors, board state, design systems, and domain data — then acting on them systematically rather than symptom-by-symptom. Names the six-step recognition loop (Observe → Cluster → Name → Codify → Detect → Prevent) with an optional Refine stage and the discipline at each stage. Catalogues code pattern classes (naming violations, duplication, anti-patterns, convention drift, missing guards, stale patterns) with detection methods and false-positive risks. Specifies the grep-based audit pattern as a six-step sequence (define → scan → count → sample → classify → triage) and the three-pass audit strategy (discovery → refinement → verification). Documents error-pattern clustering via normalize-then-hash extraction with ten error categories and severity-by-frequency triage rules. Names nine board-health patterns (stale in-progress, column overflow, WIP overflow, duplicate suspect, orphan in-progress, etc.) and the structural prevention each implies. Covers design pattern recognition (heading hierarchy contract violations, design token drift, triple-encoding requirement, component boundary violations) and domain-encoding patterns (null-vs-zero distinction, integer encoding for monetary amounts, magnitude-conversion at display boundary, source-rank trust hierarchy). Defines the eval-as-pattern-test pipeline and a 5-Whys ladder for root cause vs symptom analysis. Closes with pattern lifecycle states (Active / Fixed / Stale / Migrated), cross-session pattern persistence, a verification checklist, and six named drift traps (pareidolia, false clustering, stale patterns, over-abstraction, ignoring context, fixing at the wrong level).
Agents that operate symptom-by-symptom burn tokens without building leverage. An agent that recognizes patterns can propose systemic fixes, write automated detection rules, and prevent entire classes of bugs from recurring. This skill teaches the methodology — not just what to look for, but how to elevate a single finding into a durable detection and prevention mechanism.
The core discipline: require three instances before codifying a pattern. One is a bug. Two is a coincidence. Three is a pattern worth naming and automating. In a high-velocity agentic environment, manual review scales poorly — pattern recognition lets agents "see" the codebase as a system of rules rather than a collection of files. The premature codification of a pattern after one or two instances creates false rules that block valid code; the failure to codify after the third instance leaves the team to keep paying the same review cost on every future commit.
Observe → Cluster → Name → Codify → Detect → Prevent
↓ ↓ ↓ ↓ ↓ ↓
See it Group Give it Write Automate Make it
3x+ similar a name a rule checking impossibleAn optional Refine stage closes the loop: monitor the effectiveness of the fix and update the codified rule if false positives emerge or the pattern mutates.
| Pattern class | Examples | Detection method | False-positive risk |
|---|---|---|---|
| Naming violations | Generic names (data, result, temp, foo, item), wrong prefix, snake_case in camelCase context | Grep for common bad names; manual review | Low |
| Duplication | Same logic in 3+ places, repeated imports, copy-pasted error handlers and types | Grep for repeated code blocks; tools like jscpd | Medium — similar code may be intentional |
| Anti-patterns | String interpolation in SQL, any type usage, console.log in production, await inside forEach | Grep for known bad patterns; type-checker strict mode | Low to medium |
| Convention drift | Hardcoded hex instead of design tokens, raw px instead of spacing scale, import from wrong path | Grep for raw values and non-standard imports | Medium — intentional deviations exist |
| Missing guards | DELETE without WHERE, mutation without auth, missing tenant-scope filter, missing null check before .length | Grep for unguarded operations; read surrounding context | Medium — guards may be higher in call stack |
| Stale patterns | Old import paths, deprecated API usage, an old prefix that has been renamed, removed abstraction still referenced | Grep for known-deprecated patterns; check git blame | Low |
For any code pattern, the detection method follows this sequence:
include / exclude filters.output_mode: "count" or | wc -l gives scale before committing to review. >20 matches = significant systemic issue.output_mode: "content" with head_limit: 10 confirms the pattern is real.-v exclusions to remove known intentional patterns (vendor code, token files, fixtures).# Find hardcoded hex in component styles (excluding token sources)
grep -rE '#[0-9a-fA-F]{3,8}' src/ \
--include='*.scss' --include='*.module.scss' \
| grep -v '_design-tokens.scss' \
| grep -v '_foundation.scss' \
| head -20
# Each match: file:line → replace with var(--color-*) token from your token-source file# After renaming a project's ticket prefix from OLD- to NEW-, any OLD- reference is stale
grep -rE "OLD-[0-9]+" . --include='*.md' --include='*.ts' --include='*.js'
# → Replace OLD-XXXX with NEW-XXXX# DELETE without WHERE — data-safety violation
grep -rE 'DELETE FROM' . --include='*.ts' --include='*.sql' | grep -v 'WHERE'
# UPDATE without tenant-scope filter — multi-tenant isolation violation (requires manual review)
grep -rE 'UPDATE.*SET' src/ --include='*.ts' | head -20
# For each match: verify the tenant-id filter is in the WHERE clauseNot every grep match is a violation. Before filing or fixing:
// @intentional: <reason>).Document false-positive exclusion rules in the grep pattern itself, not just in memory. A rule that only exists in your head will be rediscovered and re-debated by the next agent.
A deterministic error-extraction phase (no model involved, no hallucination risk) clusters session-log errors into actionable categories.
| Category | Detection signature | Severity | Auto-response |
|---|---|---|---|
| Tool failure | Tool call returned error status ≠ 0 | Medium | Check tool availability, retry with backoff |
| Tool loop | Same tool called 3× with same params | High | Stop, analyze parameters, pivot strategy |
| Type error | error contains a type-checker code (e.g., TS + number) or "not assignable to type" | Medium | Fix types, check imports, check recent schema changes |
| Runtime crash | error contains "Uncaught" or stack trace | High | Debug with stack trace; may indicate missing validation |
| Stall / timeout | No tool output for >5 minutes | High | Check for infinite loop, resource exhaustion, blocked I/O |
| Permission denied | error contains "denied", "permission", "forbidden" | Medium | Check hook configuration; verify authorization; adjust scope |
| Permission tripwire | Permission denied on a protected resource (env files, credential files, .git/) | High | Do NOT retry; explain the security constraint to the user |
| Context exhaustion | Session ends mid-task or model reports context full | High | Previous session should have run a closeout protocol; check continuation signal; split task |
| Configuration error | error about missing env var, bad flag, or invalid config | Medium | Verify environment; check flags and settings; update config |
| Ghost context | Agent references files from a prior session | Medium | Run ls to verify existence; update memory |
Key insight: normalizing before hashing is what makes clustering work. Two errors that look different because one says line 47 and the other says line 52 are the same error. Strip the specifics first.
A cluster of 8 "Cannot read property of undefined" errors normalized to the same code path means there is one missing null guard, not 8 bugs. Fix the guard once; the cluster disappears. If the errors normalize to 3 different code paths, there are 3 root causes — do not collapse them into one ticket.
A board-health checker can detect nine board-level patterns. Each implies a process fix, not just an alert.
| Pattern | Threshold | Severity | Auto-Fix |
|---|---|---|---|
| Stale In Progress | >3 days no update | Warning | Move to Ready + comment |
| Stale Needs Planning | >14 days | Info | Archive |
| Column overflow | >column limit | Warning | Alert only |
| Resolved blocker | Blocking task is Done (dependency deadlock) | Warning | Comment (clear dependency) |
| Priority drift | P1/P2 in Ready >5 days | Warning | Alert only |
| WIP overflow | >N In Progress per agent | Critical | Alert only |
| Missing priority | No priority set | Info | Alert only |
| Duplicate suspect | >85% title similarity (Levenshtein) | Warning | Alert + link |
| Orphan In Progress | No assignee | Warning | Alert only |
Each pattern implies a structural fix:
| Pattern | Prevention |
|---|---|
| Stale In Progress | Agents must run a session-closeout protocol before ending a session — make it a mandatory hook |
| WIP overflow | The dispatcher must cap concurrent claims per agent; set a hard WIP_LIMIT in env |
| Duplicate suspect | Task creators must search the tracker before creating; add a pre-create search gate |
| Missing priority | Task templates must include a required priority field |
| Orphan In Progress | Claiming a task must set the assignee atomically — no claim without assignment |
| Priority drift | High-priority tasks should have clear owners; the dispatcher should prioritize them |
| Column overflow | Process needs a triage gate or WIP limit; adjust column policy |
These two patterns frequently co-occur: WIP overflow happens because agents claim tasks and then stall, creating stale in-progress tasks. The root cause is not "too many tasks claimed" but "tasks are claimed without a completion guarantee." The fix is a closeout protocol that forces resolution (Done or Blocked) before a new task can be claimed.
Triage action, not just reporting: when a pattern is detected, move stale tasks to Ready, flag duplicates for merge, and ping the owner of dependency deadlocks.
A heading hierarchy contract defines (typically) six semantic levels mapped to typography tokens with a strict component → level map. Pattern detection:
# Components defining their own font-size (violation of the contract)
grep -r "font-size:" src/ --include='*.module.scss' \
| grep -v '_foundation.scss' | head -20
# Components with hardcoded font-weight (should use heading token)
grep -r "font-weight:" src/components --include='*.scss' | head -20Rule: no component may define font-size, font-weight, or font-family for headings. Use the foundation heading tokens or semantic HTML (<h1>–<h6>) with foundation styles. If a title needs different styling, the heading hierarchy is wrong — fix the hierarchy in the token source, not the component.
Status meaning in any UI should be "triple encoded": color + icon + text.
icon and variant alignment; run an accessibility audit for color-only signals.| Pattern | Detection | Rule | ||
|---|---|---|---|---|
| Hardcoded colors | `grep -r "color:" --include='*.scss' \ | grep -v "var(--"` | Use CSS custom properties from your token source | |
| Raw pixel spacing off-grid | `grep -rE "margin:\ | padding:" --include='*.scss' \ | grep -E "[0-9]{2,}px"` | Use the spacing scale: 4, 8, 12, 16, 24, 32, ... |
| Hardcoded hex in component | grep "#[0-9a-fA-F]" --include='*.module.scss' | Hex belongs in the token source, not components | ||
| Missing dark mode | Check for the [data-theme="dark"] variant for each color variable | Every semantic color needs a .light and .dark variant | ||
| Inline styles in JSX | grep "style={{" --include='*.tsx' | Use CSS modules or class names |
Document the contract in a design guide and enforce via:
A single hardcoded color in one component is a one-line fix. But the same hardcoded color appearing in 15 components means a developer practice is broken — adding a new component will likely introduce color 16. The fix at the root-cause level is: (a) a lint rule that fails CI on hardcoded colors, and (b) a design-review gate before merge. Fixing 15 instances without the lint rule means instance 16 will appear next sprint.
Every domain has encoding conventions that, when misread, produce silent incorrect calculations — the most dangerous class of bug because the output looks valid. Monetary amounts are the classic example, but the same principles apply to any domain primitive (timestamps, percentages, dimensions, weights, currency codes).
| Principle | What it means | Common mistake | Consequence |
|---|---|---|---|
| Null vs zero distinction | null means "we don't know"; 0 means "we know and it's zero" | Treating null as 0 | Overstated outcomes (e.g., fake zero cost → fake 100% margin) |
| Integer encoding for monetary amounts | Store amounts as integer minor units (cents, satoshis) to prevent floating-point drift (0.1 + 0.2 ≠ 0.3) | Dividing by 100 mid-calculation | Floating-point precision loss accumulating across operations |
| Magnitude conversion at the display boundary only | Conversion from minor units to major units (cents → dollars) happens once, in formatters, never in business logic | Hidden /100 deep in a calculation chain | Magnitude bugs and precision loss |
| Source-rank trust hierarchy | Each data field has a rank: verified > calculated > estimated > defaulted | Treating estimated/defaulted values as authoritative | Overconfidence in unverified data |
| Customer-facing vs internal totals | Same number can mean two different things depending on perspective (e.g., shipping charged to customer ≠ shipping cost paid to fulfillment) | Confusing the two | Double-counting or sign error |
| Division-by-zero guard | A safe-percent helper returns null (or a sentinel) when the denominator is zero, never NaN or accidentally 0% | Displaying NaN or silently returning 0% | Misleading analytics |
# Premature minor → major conversion (may lose precision mid-chain)
grep -r "/ 100" src/ --include='*.ts' \
| grep -E 'cents|price|cost|total'
# Confusion between zero and null in domain fields
grep -r "amountCents === 0" src/ --include='*.ts' | head -10
# → verify the logic correctly distinguishes "unknown" from "zero"
# toFixed on minor units (wrong magnitude)
grep -r "toFixed" src/ --include='*.ts' | grep -v '/ 100'
# Missing minor → major formatting at the UI boundary
grep -rE "\{.*_cents\}" src/components/ | grep -v 'formatMoney'
# Unguarded division that could NaN
grep -r "safe-percent\|safeRatio\|safeDiv" src/ --include='*.ts' | wc -l
# → if the count is low, there may be unsafe divisions elsewhereThis is a high-frequency domain-encoding pattern violation in any codebase that handles partial data. The invariant: null means "we don't know," 0 means "we know and it's zero." Code that treats them identically will either:
Always write explicit checks:
if (amountCents === null) return null; // unknown, not zeroThe lesson generalizes beyond money: a lastSeenAt of null ≠ "seen at epoch zero"; an unknown shipping weight ≠ a zero-weight package; a missing assignedTo ≠ "assigned to no one on purpose." Build the null-vs-zero distinction into the type system at the boundary, and propagate it through the calculation chain.
Every recognized pattern should become a testable eval. This is how patterns survive beyond the session that discovered them — agents in future sessions can verify they detect the pattern reliably under new inputs.
{
"id": 1,
"name": "heading-hierarchy-violation-detection",
"prompt": "Review this SCSS for design token compliance:\n.chart-title { font-size: 16px; color: #333; font-weight: 600; }",
"expected_output": "Identifies #333 and font-size: 16px as token violations",
"expectations": [
"Flags #333 as hardcoded color — should use a color token",
"Flags font-size: 16px as raw value — should use a heading token or semantic <h3>",
"Does NOT flag font-weight: 600 if it matches the heading-h3 spec",
"Does NOT flag colors inside the token source files"
],
"model": "any frontier model"
}evals/fixtures/.evals/patterns.json that tests detection with known inputs and expected outputs.A skill section documents a pattern for human readers. An eval tests whether an agent can apply the pattern reliably under new inputs. Without the eval, a skill section about "null-vs-zero confusion" may be read and then misapplied on the next input — the agent learned the name but not the detection logic. The eval closes that gap.
This skill ships evals/evals.json with scenarios for recurrence thresholds, convention drift, error clustering, board-health patterns, root-cause depth, pattern lifecycle states, and negative routing boundaries. The eval artifact is intentionally kept as ordinary scenario JSON rather than a repo-specific fixture suite because the skill is portable and teaches a cross-codebase method.
Agents that fix symptoms create the illusion of progress while the root cause generates new instances. Pattern recognition locates the level at which a fix propagates to all instances.
| Symptom | Root cause pattern | Symptom fix | Root cause fix | ||
|---|---|---|---|---|---|
| Function crashes on null input | Missing null guard on parameter | Add null check | Non-null type narrowing at the boundary | ||
| Same bug in 3 files | Duplicated logic across files | Fix each file | Extract shared utility; replace callsites | ||
| Hardcoded hex colors everywhere | No design token available or lint rule | Replace hex one by one | Add token to the token source + CI lint rule | ||
| Users report "permission denied" weekly | Missing tenant-scope filter in query WHERE | Fix the query | Enforce a tenant-scope rule at the query layer; use a scoped-query helper | ||
| Tasks go stale in In Progress | Agents don't run the session-closeout protocol | Manually move tasks | A session-end hook enforces closeout | ||
| Type errors on every merge | Missing integration test | Fix case-by-case | Add cross-module type test in CI | ||
| Same design violation in every PR | No automated check | Review PRs manually | ESLint / Stylelint rule + design-review eval | ||
| Numeric display shows NaN | Safe-percent helper not used at display | Add `\ | \ | 0` at callsite | Enforce the safe-percent wrapper at all display boundaries via lint |
Work down to the level where a fix prevents all future instances, not just the current one.
Example: repeated null-check bug
amountCents is null, no guard exists.number instead of number | null.Fix at level 5: update the type signature to amountCents: number | null, add a comment explaining the null semantics, run type-check across all callers. This prevents the bug for all future callers, not just the one that crashed today.
Fixing at level 1 (add || 0) silently converts "unknown" to "zero assumed" — the wrong fix that creates a new category of silent error. Always aim for level 4–5 when possible. Levels 1–2 are debugging; levels 4–5 are process improvement.
Patterns are not permanent truths. They require maintenance.
| State | Meaning | Action |
|---|---|---|
| Active | Still occurring; detection rule running | Enforce, measure frequency |
| Fixed | Root cause resolved; new instances impossible | Verify with grep; archive if clean |
| Stale | Pattern was fixed but detection rule still runs | Prune detection rule; note in skill |
| Migrated | Pattern replaced by a different convention | Update detection to flag old AND new violations |
A detection rule for a pattern that no longer exists creates false positives and alert fatigue. After a root-cause fix ships:
[archived].When a convention changes (e.g., the ticket prefix is renamed from OLD- to NEW-), the detection rule must flag:
OLD- references (violations to fix).OLD- references introduced after migration (regressions to prevent).A single grep covers both: OLD-[0-9]+ catches all instances regardless of when they were written.
A detection rule added today may not catch future variants of the same pattern. Periodically verify that your detection rules still catch the pattern class, not just the specific instances you fixed. Rules age; patterns mutate.
Patterns span multiple sessions. Track them so discovery is not repeated:
memory/pattern-<name>.md with detection method and prevention status.If you detect a pattern that was supposedly fixed, investigate:
Before codifying a pattern, confirm:
// @intentional: dynamic SQL interpolation required because...).| Instead, use | Why |
|---|---|
code-review | Reviewing a specific PR for semantic logic and quality. Code-review owns the per-change judgment; pattern-recognition owns the cross-codebase recurrence analysis. |
debugging | Fixing one specific failing case — single-instance bug localization and resolution. Debugging owns the immediate fix; pattern-recognition owns the systemic rule that prevents the class from recurring. |
diagnosis | Triaging an unknown software failure into a problem class before debugging begins. Diagnosis owns the per-incident triage; pattern-recognition owns the cross-incident class analysis. |
refactor | Restructuring code once a pattern is identified. Refactor enacts the change; pattern-recognition decides what needs changing. |
naming-conventions | Establishing or auditing the naming rules themselves. Naming-conventions owns the rules; pattern-recognition detects violations of those rules. |
lint-overlay | Adding the lint rule that automates pattern detection. Lint-overlay owns the rule machinery; pattern-recognition decides which patterns warrant a rule. |
skill-infrastructure | Performing dependency and structural audits across the skill library graph. Skill-infrastructure owns the structural health-tooling perspective; pattern-recognition owns the recurring-violation perspective. |
tool-call-strategy | Deciding which tool (Grep / Glob / Read) to reach for during a scan. Tool-call-strategy owns the tool selection; pattern-recognition owns the analysis of what the tools find. |
<!-- skill-graph-context:start (generated — do not edit by hand) -->
Classification
reasoning-strategytruefoundations/cognitionWhen to use
Not for
Related skills
context-graph, skill-infrastructure, tool-call-strategylint-overlay, refactor, naming-conventions, diagnosis, debugging, code-reviewConcept
Keywords
recurring code pattern detection, anti-pattern audit, convention drift detection, error cluster triage, normalize-then-hash error grouping, five-whys root cause ladder, eval as pattern test, heading hierarchy violation, design token drift, null-vs-zero domain encoding<!-- skill-graph-context:end -->
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.