Skip to main content

Design Pattern Recognition

Auto-Skill’s Design Pattern Detector identifies 18 different patterns across three categories: architectural patterns, coding patterns, and workflow patterns. This helps generate skills with rich contextual understanding.

Pattern Categories

Structural organization patterns for codebases:
  • MVC — Model-View-Controller separation
  • Repository — Data access abstraction
  • Factory — Object creation pattern
  • Singleton — Single-instance classes
  • Strategy — Interchangeable algorithms
  • Observer — Event handling pattern
  • Adapter — Interface compatibility
  • Dependency-Injection — DI pattern

Pattern Detection Methods

File Path Analysis

Detect architectural patterns from directory structuremodels/, views/, controllers/ → MVC

Code Content Search

Scan file contents for pattern indicatorsasync, await → Async-Pattern

Tool Sequence Matching

Recognize workflows from tool usageWrite → Bash → Edit → Bash → TDD

Confidence Scoring

Calculate match confidence from indicator countMore indicators = higher confidence

DesignPattern Type

Detected patterns include rich metadata:
// From types/index.ts:248-259
export interface DesignPattern {
  patternId: string;              // e.g. "workflow-tdd"
  patternType: string;            // "architectural" | "coding" | "workflow"
  patternName: string;            // e.g. "TDD"
  confidence: number;             // 0.0 - 1.0
  description: string;
  indicators: string[];           // What triggered detection
  affectedFiles?: string[];       // Files containing the pattern
  codeExamples?: string[];        // Extracted code snippets
  metadata?: Record<string, unknown>;
}

Architectural Patterns

Detected from file paths and code structure:
// From design-pattern-detector.ts:32-80
const ARCHITECTURAL_PATTERNS: Record<string, PatternDefinition> = {
  MVC: {
    indicators: [
      "model",
      "view",
      "controller",
      "models/",
      "views/",
      "controllers/",
    ],
    description: "Model-View-Controller separation pattern",
    minConfidence: 0.6,
  },
  Repository: {
    indicators: ["repository", "repo", "data_access", "dal"],
    description: "Repository pattern for data access abstraction",
    minConfidence: 0.5,
  },
  Factory: {
    indicators: ["factory", "create_", "builder"],
    description: "Factory pattern for object creation",
    minConfidence: 0.5,
  },
  Singleton: {
    indicators: ["singleton", "_instance", "get_instance"],
    description: "Singleton pattern for single-instance classes",
    minConfidence: 0.6,
  },
  Strategy: {
    indicators: ["strategy", "algorithm", "policy"],
    description: "Strategy pattern for interchangeable algorithms",
    minConfidence: 0.5,
  },
  Observer: {
    indicators: ["observer", "subscriber", "listener", "event"],
    description: "Observer pattern for event handling",
    minConfidence: 0.5,
  },
  Adapter: {
    indicators: ["adapter", "wrapper", "facade"],
    description: "Adapter pattern for interface compatibility",
    minConfidence: 0.5,
  },
  "Dependency-Injection": {
    indicators: ["inject", "container", "provider", "di_"],
    description: "Dependency Injection pattern",
    minConfidence: 0.6,
  },
};
Detected when:
  • Directory structure has models/, views/, controllers/
  • File paths contain “model”, “view”, or “controller”
  • Code contains MVC-related keywords
Pattern Context:
{
  patternName: "MVC",
  whenToUse: "Building web applications with clear separation of concerns",
  benefits: [
    "Separates business logic from presentation",
    "Easier to test and maintain",
    "Multiple views can share same model"
  ],
  tradeOffs: [
    "Can be overkill for simple applications",
    "More files and indirection"
  ],
  commonMistakes: [
    "Putting business logic in controllers",
    "Tight coupling between layers"
  ]
}

Coding Patterns

Detected from code content:
// From design-pattern-detector.ts:82-113
const CODING_PATTERNS: Record<string, PatternDefinition> = {
  "Error-First-Handling": {
    indicators: ["try", "except", "raise", "error", "exception"],
    description: "Error-first error handling pattern",
    minConfidence: 0.4,
  },
  "REST-API-Design": {
    indicators: ["@app.route", "@router", "GET", "POST", "PUT", "DELETE"],
    description: "RESTful API design pattern",
    minConfidence: 0.5,
  },
  "Async-Pattern": {
    indicators: ["async", "await", "asyncio", "concurrent"],
    description: "Asynchronous programming pattern",
    minConfidence: 0.5,
  },
  "Decorator-Pattern": {
    indicators: ["@decorator", "@property", "@staticmethod"],
    description: "Python decorator pattern",
    minConfidence: 0.4,
  },
  "Context-Manager": {
    indicators: ["__enter__", "__exit__", "with ", "contextmanager"],
    description: "Context manager pattern (with statement)",
    minConfidence: 0.5,
  },
  "Builder-Pattern": {
    indicators: ["builder", "build()", "with_", "set_"],
    description: "Fluent builder pattern",
    minConfidence: 0.5,
  },
};
Detected when:
  • Code contains async, await, asyncio, or concurrent
Code Example Extraction:
// Automatically extracts surrounding context (±3 lines)
async function fetchData() {
  const response = await fetch(url);
  return await response.json();
}
Confidence increases with more indicators found.

Workflow Patterns

Detected from tool usage sequences:
// From design-pattern-detector.ts:115-136
const WORKFLOW_PATTERNS: Record<string, WorkflowPatternDefinition> = {
  TDD: {
    toolSequence: ["Write", "Bash", "Edit", "Bash"],
    description: "Test-Driven Development workflow",
    indicators: ["test", "assert", "pytest", "unittest"],
  },
  "Refactor-Safe": {
    toolSequence: ["Read", "Edit", "Bash"],
    description: "Safe refactoring with tests",
    indicators: ["refactor", "test", "extract", "rename"],
  },
  "Debug-Systematic": {
    toolSequence: ["Read", "Grep", "Bash", "Edit"],
    description: "Systematic debugging approach",
    indicators: ["debug", "print", "log", "trace"],
  },
  "Explore-Then-Implement": {
    toolSequence: ["Grep", "Read", "Read", "Write"],
    description: "Exploration before implementation",
    indicators: ["understand", "explore", "analyze"],
  },
};

Workflow Detection Algorithm

// From design-pattern-detector.ts:270-316
function detectWorkflowPattern(
  toolSequence: string[],
  sessionContext?: Record<string, unknown>
): DesignPattern | null {
  if (toolSequence.length === 0) return null;
  
  for (const [patternName, patternInfo] of Object.entries(WORKFLOW_PATTERNS)) {
    // Check if tool sequence contains the pattern
    if (!containsSubsequence(toolSequence, patternInfo.toolSequence)) {
      continue;
    }
    
    // Base confidence for sequence match
    let confidence = 0.7;
    
    // Boost confidence if session context has matching indicators
    if (sessionContext) {
      const contextText = JSON.stringify(sessionContext).toLowerCase();
      const matchingIndicators = patternInfo.indicators.filter((ind) =>
        contextText.includes(ind)
      );
      if (matchingIndicators.length > 0) {
        confidence = Math.min(0.95, confidence + 0.05 * matchingIndicators.length);
      }
    }
    
    return {
      patternId: `workflow-${patternName.toLowerCase()}`,
      patternType: "workflow",
      patternName,
      confidence,
      description: patternInfo.description,
      indicators: [`Tool sequence: ${patternInfo.toolSequence.join(" -> ")}`],
      affectedFiles: [],
      codeExamples: [],
      metadata: { toolSequence },
    };
  }
  
  return null;
}
Confidence Boosting: Workflow patterns get +0.05 confidence for each matching indicator found in session context, up to 0.95 maximum.

Pattern Context

Predefined context provides guidance on when to use each pattern:
// From design-pattern-detector.ts:142-194
const PATTERN_CONTEXTS: Record<string, PatternContext> = {
  MVC: {
    patternName: "MVC",
    whenToUse: "Building web applications with clear separation of concerns",
    benefits: [
      "Separates business logic from presentation",
      "Easier to test and maintain",
      "Multiple views can share same model",
    ],
    tradeOffs: [
      "Can be overkill for simple applications",
      "More files and indirection",
    ],
    commonMistakes: [
      "Putting business logic in controllers",
      "Tight coupling between layers",
    ],
  },
  Repository: {
    patternName: "Repository",
    whenToUse: "When you need to abstract data access layer",
    benefits: [
      "Decouples business logic from data access",
      "Easy to swap data sources",
      "Centralized data access logic",
    ],
    tradeOffs: [
      "Additional abstraction layer",
      "Can be over-engineering",
    ],
    commonMistakes: [
      "Leaking data access concerns to business layer",
    ],
  },
  TDD: {
    patternName: "TDD",
    whenToUse: "When building new features or fixing bugs",
    benefits: [
      "Better test coverage",
      "Forces you to think about requirements",
      "Refactoring confidence",
    ],
    tradeOffs: [
      "Slower initial development",
      "Requires discipline",
    ],
    commonMistakes: [
      "Testing implementation instead of behavior",
      "Skipping refactor step",
    ],
  },
};

PatternContext Type

// From types/index.ts:261-268
export interface PatternContext {
  patternName: string;
  whenToUse: string;
  benefits: string[];
  tradeOffs: string[];
  commonMistakes?: string[];
}

File-Based Detection

Architectural and coding patterns are detected from file analysis:
// From design-pattern-detector.ts:318-434
function detectPatternsFromFiles(
  filePaths: string[],
  fileContents: Map<string, string>
): DesignPattern[] {
  const patterns: DesignPattern[] = [];
  
  // --- Architectural patterns (check file paths) ---
  for (const [patternName, patternInfo] of Object.entries(ARCHITECTURAL_PATTERNS)) {
    const indicatorsFound: string[] = [];
    const affectedFiles: string[] = [];
    
    // Check file paths
    for (const filePath of filePaths) {
      const pathLower = filePath.toLowerCase();
      for (const indicator of patternInfo.indicators) {
        if (pathLower.includes(indicator)) {
          indicatorsFound.push(`Path: ${filePath}`);
          affectedFiles.push(filePath);
        }
      }
    }
    
    // Check file contents
    for (const [filePath, content] of fileContents) {
      const contentLower = content.toLowerCase();
      for (const indicator of patternInfo.indicators) {
        if (contentLower.includes(indicator)) {
          indicatorsFound.push(`Found '${indicator}' in ${filePath.split("/").pop()}`);
          if (!affectedFiles.includes(filePath)) {
            affectedFiles.push(filePath);
          }
        }
      }
    }
    
    // Calculate confidence
    if (indicatorsFound.length > 0) {
      const confidence = Math.min(
        1.0,
        indicatorsFound.length / (patternInfo.indicators.length * 2)
      );
      
      if (confidence >= patternInfo.minConfidence) {
        patterns.push({
          patternId: `arch-${patternName.toLowerCase()}`,
          patternType: "architectural",
          patternName,
          confidence,
          description: patternInfo.description,
          indicators: indicatorsFound.slice(0, 10),
          affectedFiles: [...new Set(affectedFiles)].slice(0, 10),
          codeExamples: [],
          metadata: {},
        });
      }
    }
  }
  
  // --- Coding patterns (similar process) ---
  // ...
  
  // Sort by confidence descending
  patterns.sort((a, b) => b.confidence - a.confidence);
  return patterns;
}

Confidence Calculation

// Confidence = indicators found / (total indicators * 2)
const confidence = Math.min(1.0, indicatorsFound.length / (patternInfo.indicators.length * 2));

// Must meet minimum threshold
if (confidence >= patternInfo.minConfidence) {
  // Pattern detected
}

Code Example Extraction

Code snippets are extracted around matching indicators:
// From design-pattern-detector.ts:436-454
function extractCodeExample(
  source: string,
  indicator: string,
  contextLines: number = 3
): string | null {
  const lines = source.split("\n");
  
  for (let i = 0; i < lines.length; i++) {
    if (lines[i].toLowerCase().includes(indicator.toLowerCase())) {
      const start = Math.max(0, i - contextLines);
      const end = Math.min(lines.length, i + contextLines + 1);
      const example = lines.slice(start, end).join("\n");
      return example.slice(0, 200);  // Max 200 chars
    }
  }
  
  return null;
}
Code examples include ±3 lines of context around the indicator match, truncated to 200 characters.

Pattern Suggestions

Suggest relevant patterns based on intent and domain:
// From design-pattern-detector.ts:476-509
function suggestPatternsForContext(
  intent: string,
  problemDomain: string
): Array<{ pattern: string; relevance: number }> {
  const suggestions = new Map<string, number>();
  
  const intentLower = intent.toLowerCase();
  const domainLower = problemDomain.toLowerCase();
  
  // Match intents
  for (const [intentKey, patterns] of Object.entries(INTENT_PATTERN_MAP)) {
    if (intentLower.includes(intentKey)) {
      for (const pattern of patterns) {
        suggestions.set(pattern, Math.max(suggestions.get(pattern) ?? 0, 0.8));
      }
    }
  }
  
  // Match domains
  for (const [domainKey, patterns] of Object.entries(DOMAIN_PATTERN_MAP)) {
    if (domainLower.includes(domainKey)) {
      for (const pattern of patterns) {
        suggestions.set(pattern, Math.max(suggestions.get(pattern) ?? 0, 0.7));
      }
    }
  }
  
  // Sort by relevance descending
  return [...suggestions.entries()]
    .map(([pattern, relevance]) => ({ pattern, relevance }))
    .sort((a, b) => b.relevance - a.relevance);
}

Intent-to-Pattern Map

// From design-pattern-detector.ts:200-205
const INTENT_PATTERN_MAP: Record<string, string[]> = {
  implement: ["Factory", "Builder-Pattern", "Strategy"],
  refactor: ["Refactor-Safe", "Extract-Method"],
  debug: ["Debug-Systematic", "Error-First-Handling"],
  test: ["TDD", "Mock-Pattern"],
};

Domain-to-Pattern Map

// From design-pattern-detector.ts:207-212
const DOMAIN_PATTERN_MAP: Record<string, string[]> = {
  api: ["REST-API-Design", "Adapter", "Repository"],
  database: ["Repository", "DAO"],
  async: ["Async-Pattern", "Observer"],
  web: ["MVC", "REST-API-Design"],
};

Usage Example

import { createDesignPatternDetector } from "./core/design-pattern-detector";

const detector = createDesignPatternDetector();

// 1. Detect workflow pattern from tool sequence
const workflowPattern = detector.detectWorkflowPattern(
  ["Write", "Bash", "Edit", "Bash"],
  { primary_intent: "test", workflow_type: "TDD" }
);

if (workflowPattern) {
  console.log(`Detected: ${workflowPattern.patternName}`);
  console.log(`Confidence: ${Math.round(workflowPattern.confidence * 100)}%`);
}

// 2. Detect patterns from files
const filePaths = [
  "src/models/user.ts",
  "src/views/user-view.tsx",
  "src/controllers/user-controller.ts"
];

const fileContents = new Map([
  ["src/models/user.ts", "export class User { /* ... */ }"],
  ["src/views/user-view.tsx", "export function UserView() { /* ... */ }"],
  ["src/controllers/user-controller.ts", "export class UserController { /* ... */ }"]
]);

const patterns = detector.detectPatternsFromFiles(filePaths, fileContents);

for (const pattern of patterns) {
  console.log(`\n${pattern.patternName} (${pattern.patternType}):`);
  console.log(`  Confidence: ${Math.round(pattern.confidence * 100)}%`);
  console.log(`  Files: ${pattern.affectedFiles?.join(", ")}`);
}

// 3. Get pattern context
const context = detector.getPatternContext("TDD");
if (context) {
  console.log(`\nWhen to use TDD: ${context.whenToUse}`);
  console.log(`Benefits: ${context.benefits.join(", ")}`);
}

// 4. Suggest patterns for context
const suggestions = detector.suggestPatternsForContext("implement", "api");
console.log(`\nSuggested patterns:`);
for (const { pattern, relevance } of suggestions) {
  console.log(`  ${pattern} (${Math.round(relevance * 100)}% relevant)`);
}

API Reference

detectWorkflowPattern
function
Detect workflow pattern from tool sequenceParameters:
  • toolSequence: string[] — Ordered tool names
  • sessionContext?: Record<string, unknown> — Optional session context
Returns: DesignPattern | null
detectPatternsFromFiles
function
Detect architectural and coding patterns from filesParameters:
  • filePaths: string[] — File paths to analyze
  • fileContents: Map<string, string> — File path → content map
Returns: DesignPattern[] — Sorted by confidence descending
getPatternContext
function
Get contextual information about a patternParameters:
  • patternName: string — e.g. “MVC”, “TDD”, “Repository”
Returns: PatternContext | null
suggestPatternsForContext
function
Suggest relevant patterns for intent and domainParameters:
  • intent: string — User intent (implement, refactor, debug, test)
  • problemDomain: string — Technical domain (api, database, async, web)
Returns: Array<{ pattern: string; relevance: number }> — Sorted by relevance

Pattern Summary Table

PatternTypeMin ConfidenceKey Indicators
MVCArchitectural0.6models/, views/, controllers/
RepositoryArchitectural0.5repository, repo, data_access
FactoryArchitectural0.5factory, create_, builder
SingletonArchitectural0.6singleton, _instance
StrategyArchitectural0.5strategy, algorithm, policy
ObserverArchitectural0.5observer, subscriber, event
AdapterArchitectural0.5adapter, wrapper, facade
Dependency-InjectionArchitectural0.6inject, container, provider
Error-First-HandlingCoding0.4try, except, raise, error
REST-API-DesignCoding0.5@app.route, GET, POST
Async-PatternCoding0.5async, await, asyncio
Decorator-PatternCoding0.4@decorator, @property
Context-ManagerCoding0.5enter, exit, with
Builder-PatternCoding0.5builder, build(), with_
TDDWorkflow0.7Write → Bash → Edit → Bash
Refactor-SafeWorkflow0.7Read → Edit → Bash
Debug-SystematicWorkflow0.7Read → Grep → Bash → Edit
Explore-Then-ImplementWorkflow0.7Grep → Read → Read → Write

Next Steps

Pattern Detection

See how design patterns integrate with pattern detection

Skill Generation

Learn how patterns enrich generated skills

Session Analysis

Understand workflow type detection

Pattern Detection

Explore pattern detection details

Build docs developers (and LLMs) love