How the Layer Detector Identifies Architectural Layers from File Structure in Understand-Anything

TLDR: The layer detector identifies architectural layers by matching normalized file path segments against a predefined pattern table, then grouping files into logical layers with deterministic IDs, falling back to an LLM-based analysis when heuristic detection is insufficient.

The layer detector in the Egonex-AI/Understand-Anything repository analyzes knowledge graph nodes to automatically identify architectural layers from file structure. This heuristic analyzer examines directory names within file paths to classify code into logical layers such as API, Service, Data, or UI layers, providing a structured view of codebase architecture without requiring manual annotation.

How the Heuristic Layer Detection Works

The detection process operates in three distinct phases defined in packages/core/src/analyzer/layer-detector.ts. Each phase transforms raw file paths into structured architectural abstractions.

Pattern Definition in LAYER_PATTERNS

The detector relies on a static mapping table called LAYER_PATTERNS (lines 16-67) that associates directory name patterns with architectural layer definitions. This table contains groups of directory names—such as "routes", "service", "model", or "ui"—each mapped to a specific layer name and description. The order of entries is significant: the detector uses a "first match wins" strategy when evaluating paths against these patterns.

Path Matching with matchFileToLayer

For every file node in the knowledge graph, the matchFileToLayer function (lines 80-96) normalizes the file path using forward slashes and lowercasing, then splits it into segments. Each segment is compared against every pattern in LAYER_PATTERNS, including plural form variations. The first directory segment that matches a pattern determines the file's architectural layer. If no pattern matches, the file is assigned to the default Core layer.

Layer Grouping via detectLayers

The detectLayers function (lines 101-144) orchestrates the classification process. It iterates through all file-type nodes, applies the path matching logic, and aggregates files by their discovered layer names. For each group, it constructs a Layer object containing:

  • A deterministic kebab-case ID formatted as layer:<name>
  • The layer name and description (sourced from the pattern table when available)
  • An array of node IDs belonging to that layer

Files lacking a filePath property are automatically placed in the Core layer during a secondary validation loop.

LLM-Based Fallback Detection

When heuristic pattern matching fails to capture complex architectural patterns, the detector provides an LLM-driven alternative that analyzes file paths using natural language understanding.

Prompt Construction with buildLayerDetectionPrompt

The buildLayerDetectionPrompt function (lines 50-67) generates a structured prompt containing every file path from the knowledge graph. This prompt requests the LLM to propose layer classifications and returns a JSON schema defining the expected response format, enabling structured parsing of the model's architectural suggestions.

Response Parsing and Application

The parseLayerDetectionResponse function (lines 77-120) validates and extracts layer definitions from the LLM's JSON response. Subsequently, applyLLMLayers (lines 122-184) maps these model-provided patterns onto the knowledge graph nodes, creating layer objects that follow the same structure as the heuristic output. This fallback path activates when the user explicitly requests LLM-driven inference or when the static pattern table fails to classify significant portions of the codebase.

Practical Implementation Example

The following TypeScript example demonstrates both heuristic detection and the LLM fallback workflow:

import { detectLayers, buildLayerDetectionPrompt } from
  '@understand-anything/core/analyzer/layer-detector.js';
import type { KnowledgeGraph } from '@understand-anything/core/types.js';

// Build a knowledge graph with file nodes
const graph: KnowledgeGraph = {
  nodes: [
    { id: '1', type: 'file', filePath: 'src/routes/user.ts' },
    { id: '2', type: 'file', filePath: 'src/service/auth.ts' },
    { id: '3', type: 'file', filePath: 'src/model/user.ts' },
    { id: '4', type: 'file', filePath: 'src/ui/dashboard.tsx' },
    { id: '5', type: 'file', filePath: 'src/util/logger.ts' },
  ],
  edges: [],
};

// Run heuristic detection
const layers = detectLayers(graph);
console.log(layers);
/* Output:
[
  { id: 'layer:api-layer', name: 'API Layer', nodeIds: ['1'], ... },
  { id: 'layer:service-layer', name: 'Service Layer', nodeIds: ['2'], ... },
  { id: 'layer:data-layer', name: 'Data Layer', nodeIds: ['3'], ... },
  { id: 'layer:ui-layer', name: 'UI Layer', nodeIds: ['4'], ... },
  { id: 'layer:utility-layer', name: 'Utility Layer', nodeIds: ['5'], ... }
]
*/

For LLM-driven classification:

import { buildLayerDetectionPrompt, parseLayerDetectionResponse, applyLLMLayers } from
  '@understand-anything/core/analyzer/layer-detector.js';

const prompt = buildLayerDetectionPrompt(graph);
// Submit prompt to LLM...
const llmLayers = parseLayerDetectionResponse(llmResponse);
if (llmLayers) {
  const layeredGraph = applyLLMLayers(graph, llmLayers);
}

Summary

  • The layer detector identifies architectural layers by matching directory names in file paths against the LAYER_PATTERNS table, with the first match determining the layer assignment.
  • Unmatched files and nodes without file paths default to the Core layer.
  • The detectLayers function produces structured layer objects with deterministic IDs (layer:<name>) and associated node references.
  • An LLM fallback provides intelligent layer inference when heuristic patterns are insufficient, using buildLayerDetectionPrompt, parseLayerDetectionResponse, and applyLLMLayers.
  • All implementation resides in packages/core/src/analyzer/layer-detector.ts.

Frequently Asked Questions

What happens if a file doesn't match any layer pattern?

Files that fail to match any entry in LAYER_PATTERNS are automatically assigned to the Core layer. This fallback ensures that all file nodes receive a layer classification even when directory names don't follow conventional architectural patterns.

How does the layer detector handle files without file paths?

During the layer construction phase in detectLayers, the detector performs a secondary validation loop that places any file node lacking a filePath property into the Core layer. This handles edge cases where knowledge graph nodes represent abstract or generated entities without physical file locations.

Can I customize the layer patterns for my specific architecture?

While the raw analysis focuses on the static LAYER_PATTERNS table, the architecture supports customization through the LLM-driven detection path. By using buildLayerDetectionPrompt and applyLLMLayers, you can inject custom layer definitions without modifying the core heuristic table, allowing project-specific architectural classifications.

When should I use the LLM-driven detection instead of heuristics?

Use LLM-driven detection when your codebase follows unconventional directory structures that don't match common patterns like "routes", "service", or "model", or when you need to identify domain-specific architectural layers that aren't covered by the static LAYER_PATTERNS table. The heuristic approach remains faster and more deterministic for standard architectures.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →