How Layer Detection Maps Code to Architectural Tiers in Understand-Anything

The layer detection system in Understand-Anything assigns every file node in the knowledge graph to a logical architectural tier using heuristic directory-pattern matching, with optional LLM-driven refinement for custom mappings.

In the Egonex-AI/Understand-Anything repository, the analyzer component automatically infers architectural layers from project structure. This capability bridges the gap between raw file paths and high-level architectural understanding, enabling the tool to categorize code into logical tiers such as API, Service, and Data layers.

Heuristic Directory-Pattern Matching

The primary mechanism for layer detection relies on predefined folder patterns that map directory names to architectural tiers.

The LAYER_PATTERNS Configuration

The system uses a built-in LAYER_PATTERNS list defined in layer-detector.ts (lines 16-67) to identify which folders belong to specific layers. Common mappings include:

  • "routes" → API Layer
  • "service" → Service Layer
  • "model" → Data Layer

These patterns include plural forms and cover conventional naming conventions for controllers, repositories, utilities, and UI components.

Path Normalization and Segment Matching

The matchFileToLayer(filePath) function (lines 80-95) normalizes file paths, splits them into segments, and checks each segment against the pattern list. The first matching pattern wins, returning the corresponding layer name. Files that fail to match any pattern are assigned to the fallback Core layer.

This implementation iterates over path segments sequentially, ensuring predictable assignment based on the most specific directory match encountered first.

LLM-Driven Refinement

When heuristic matching proves insufficient, the system can leverage language models to propose custom layer definitions based on actual file contents and project context.

Building the Detection Prompt

The buildLayerDetectionPrompt function (lines 150-169) constructs a markdown-formatted prompt containing an indented list of all file paths from the knowledge graph. This prompt is sent to the LLM to solicit architectural analysis and layer categorization suggestions.

Parsing and Applying LLM Suggestions

After receiving the LLM response, parseLayerDetectionResponse (lines 174-200) extracts JSON arrays from raw or fenced-code blocks, validating each layer entry against expected schema.

The applyLLMLayers function (lines 222-284) then matches file paths against the LLM-provided filePatterns. Files matching a pattern are assigned to that layer, while unassigned files are placed in an Other layer. This refinement process allows the system to adapt to domain-specific architectures that fall outside standard conventions.

Implementation Workflow

The complete layer detection workflow follows this sequence:

  1. Graph Construction - Build the knowledge graph with file nodes from the codebase
  2. Heuristic Detection - Execute detectLayers(graph) (lines 100-144) to create a Map<string, string[]> of layer names to node IDs, generating Layer objects with IDs created via toLayerId
  3. Optional LLM Refinement - Build the prompt, send to LLM, parse response, and apply custom layers using applyLLMLayers

The detectLayers function handles the initial pass, constructing layer objects and ensuring every file receives a tier assignment, either through pattern matching or the Core fallback.

Practical Code Examples

The following TypeScript examples demonstrate the layer detection API using the core analyzer functions:

import { detectLayers, buildLayerDetectionPrompt, parseLayerDetectionResponse, applyLLMLayers } from '@understand-anything/core/analyzer';
import type { KnowledgeGraph } from '@understand-anything/core/types';

// Example: a tiny synthetic graph
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.vue' },
    { id: '5', type: 'file', filePath: 'src/util/helpers.ts' },
  ],
  edges: [],
};

// 1️⃣ Heuristic detection
const heuristic = detectLayers(graph);
console.log('Heuristic layers →', heuristic.map(l => l.name));
/* → ["API Layer","Service Layer","Data Layer","UI Layer","Utility Layer"] */

// 2️⃣ LLM‑driven detection (pseudo‑LLM call)
const prompt = buildLayerDetectionPrompt(graph);
console.log('Prompt sent to LLM:', prompt);

// Assume `llmResponse` is the raw string returned by the model:
const llmResponse = `
[
  { "name": "API", "description": "HTTP entry points", "filePatterns": ["src/routes/"] },
  { "name": "Domain", "description": "Business logic", "filePatterns": ["src/service/","src/model/"] },
  { "name": "Presentation", "description": "UI components", "filePatterns": ["src/ui/"] }
]
`;
const llmLayers = parseLayerDetectionResponse(llmResponse);
if (llmLayers) {
  const refined = applyLLMLayers(graph, llmLayers);
  console.log('LLM‑refined layers →', refined.map(l => l.name));
  // → ["API","Domain","Presentation","Other"]
}

Key Implementation Files

The layer detection logic spans several files within the understand-anything-plugin package:

File Role Location
layer-detector.ts Core implementation of heuristic detection, LLM prompt building, response parsing, and layer application packages/core/src/analyzer/layer-detector.ts
types.ts TypeScript definitions for KnowledgeGraph and Layer interfaces packages/core/src/types.ts
layerStats.ts Utility for aggregating statistics per layer dashboard visualization packages/dashboard/src/utils/layerStats.ts
layer-detector.test.ts Unit tests ensuring pattern matching accuracy and fallback behavior packages/core/src/__tests__/layer-detector.test.ts

Summary

  • Layer detection in Understand-Anything uses a two-tier approach: heuristic pattern matching followed by optional LLM refinement.
  • The matchFileToLayer function in layer-detector.ts handles directory-segment matching against LAYER_PATTERNS, with Core as the fallback tier.
  • LLM-driven refinement allows custom architectural mappings through buildLayerDetectionPrompt, parseLayerDetectionResponse, and applyLLMLayers.
  • Files processed via LLM methods that match no patterns are assigned to an Other layer.
  • The system generates Layer objects with unique IDs via toLayerId, storing mappings as Map<string, string[]> of layer names to node IDs.

Frequently Asked Questions

How does the layer detector handle files in unconventional directory structures?

Files that do not match any entry in the LAYER_PATTERNS list are automatically assigned to the Core layer during heuristic detection. When using LLM refinement, unmatched files are placed in an Other layer, ensuring every file node receives a tier assignment regardless of naming conventions.

Can I customize the layer patterns without using the LLM feature?

Yes. The LAYER_PATTERNS constant in layer-detector.ts (lines 16-67) can be modified to include custom folder names and layer mappings. Patterns are checked sequentially, so you can prioritize specific directories by ordering them earlier in the array.

What format does the LLM need to return for layer detection?

The LLM must return a JSON array where each object contains name, description, and filePatterns properties. The parseLayerDetectionResponse function (lines 174-200) handles both raw JSON and fenced code blocks (triple backticks), validating the structure before applying the mappings via applyLLMLayers.

How does layer detection impact the Understand-Anything dashboard?

After layers are resolved, the layerStats.ts utility aggregates code metrics per tier for visualization. This allows the dashboard to display architectural statistics—such as file count and complexity distribution—across the API, Service, Data, and other detected layers, providing high-level architectural insights derived from the detectLayers output.

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 →