Signal Classification
Home GitHub

Signal Classification

Part II: How Draft Thinks · Chapter 6

5 min read

You run /draft:init on a project. Draft needs to produce a comprehensive architecture document, but every project is different. A React single-page app has no backend routes. A Go microservice has no frontend components. A data pipeline has no authentication layer. Draft cannot treat every project the same way, so it reads the file tree first and classifies what it finds into signals — categories that tell it what your project actually contains, what sections deserve deep treatment, and what can be skipped entirely.

File Tree src/routes/ src/auth/ src/models/ src/services/ src/components/ tests/ config/ package.json Signal Detection backend_routes: 8 auth_files: 3 data_models: 6 services: 5 components: 22 test_infra: 15 background_jobs: 0 state_mgmt: 0 Architecture Sections API Definitions — HIGH Security Architecture — HIGH Component Map — HIGH Testing Infrastructure — HIGH Concurrency — SKIP State Management — SKIP
Signal classification pipeline: the file tree is scanned, files are categorized into 11 signal types, and signal counts determine which architecture sections get deep treatment or are skipped.

What Signals Are

Signals are categories of source files that reveal architectural concerns. During Phase 1 of architecture discovery, Draft walks your file tree and tags every file against 11 signal categories. The signal counts determine which sections of architecture.md get deep treatment, which get brief mention, and which are skipped. A signal count of zero means the architectural concern does not exist in your project. A count of 3 or more means it warrants exhaustive analysis.

This is how Draft adapts to your codebase without being told what kind of project it is. It does not ask "is this a web app?" — it finds route files, controller files, and API middleware, and concludes that API definitions need deep treatment.

The 11 Signal Categories

1. Backend Routes

Files in routes/, handlers/, controllers/, or **/api/**. Route decorators like @app.route, @router, @RequestMapping. These drive deep treatment of API Definitions and Cross-Module Integration sections. A project with 12 route files gets exhaustive endpoint cataloging. A project with zero gets those sections skipped.

2. Frontend Routes

Files in pages/, views/, or route configuration files. React Router setup, Next.js app/ directory, Vue Router. These trigger UI topology documentation in the Architecture Overview section — component hierarchy, page routing, navigation flows.

3. Components

Files in components/, widgets/, or component-typed files like *.component.ts and *.tsx in component directories. These add component hierarchy documentation to the Core Modules section.

4. Services

Files in services/ or files matching *Service.* and *_service.* patterns. Service layer files drive the Component Map and Core Modules sections, documenting business logic boundaries and inter-service communication.

5. Data Models

Files in models/, entities/, schemas/, or migration directories. Files matching *.model.* and *.entity.*. These drive the State Management and API Definitions sections — schema definitions, ORM models, migration systems, and data lifecycle documentation.

6. Authentication

Files in auth/ directories, auth middleware, guards. JWT and OAuth imports. These trigger deep treatment of the Security Architecture section: auth flows, token lifecycle, permission models, session management.

7. State Management

Files in store/, reducers/, or state directories. Redux, Vuex, Zustand, Pinia imports. These add frontend state management documentation: store structure, action flows, selector patterns, state shape.

8. Background Jobs

Files in jobs/, workers/, tasks/, or queues/. Celery, Sidekiq, Bull imports. These drive the Concurrency and Configuration sections with job scheduling, queue architecture, worker pool documentation.

9. Persistence

Files in repositories/, dao/, or database directories. ORM configuration files and migration directories. These drive the State Management section with connection pooling, query patterns, transaction boundaries.

10. Test Infrastructure

Files in test/, tests/, or __tests__/. Files matching *.test.* and *.spec.*. Test configuration files. These drive the Testing Infrastructure section: test frameworks, mock patterns, fixture strategies, coverage configuration.

11. Configuration

Files matching .env*, files in config/, files matching *.config.*, application.yml, and settings files. These drive the Configuration section: environment variable catalogs, config loading mechanisms, feature flags, runtime tunables.

Frontend (3) Frontend Routes pages/, views/, route configs Components components/, widgets/, *.tsx State Management store/, reducers/, Redux/Vuex Backend (4) Backend Routes routes/, handlers/, controllers/ Services services/, *Service.*, business logic Data Models models/, entities/, schemas/ Authentication auth/, guards/, JWT/OAuth Infrastructure (4) Background Jobs jobs/, workers/, queues/ Persistence repositories/, dao/, migrations/ Test Infrastructure tests/, *.test.*, *.spec.* Configuration .env*, config/, *.config.* 11 signal categories grouped by concern area: each drives specific architecture sections
Signal category grid: all 11 categories organized by concern area. Frontend signals (violet) drive UI documentation, Backend signals (blue) drive API and business logic sections, Infrastructure signals (amber) drive operational sections.

How Signals Drive Analysis Depth

Each signal category maps to specific sections of architecture.md. The mapping is explicit:

| Signal Category    | Count | Drives Section(s)                          | Depth     |
|--------------------|-------|-------------------------------------------|-----------|
| backend_routes     |  12   | API Definitions, Cross-Module Integration | HIGH      |
| services           |   8   | Component Map, Core Modules               | HIGH      |
| data_models        |   6   | State Management, API Definitions         | HIGH      |
| test_infra         |  15   | Testing Infrastructure                    | HIGH      |
| auth_files         |   3   | Security Architecture                     | HIGH      |
| persistence        |   4   | State Management                          | HIGH      |
| config_files       |   5   | Configuration                             | HIGH      |
| components         |   0   | Core Modules (component hierarchy)        | SKIP      |
| frontend_routes    |   0   | Architecture (UI topology)                | SKIP      |
| state_management   |   0   | State Management (frontend state)         | SKIP      |
| background_jobs    |   0   | Concurrency                               | SIMPLIFY  |

The thresholds are simple: zero files means skip or simplify the section. One to two files means include the section but keep it brief. Three or more files means the section warrants deep, exhaustive treatment. This prevents Draft from generating empty boilerplate sections for concerns that do not exist in your project, while ensuring real concerns get thorough documentation.

Adaptive Sections

Signal classification integrates with the Adaptive Sections system. If your codebase has no plugin, algorithm, or handler system, the Framework and Extension Points section is skipped entirely. If your project is a library with no running process, the Process Lifecycle section is adapted to "Usage Lifecycle." If your project is a frontend module, component hierarchy, route maps, state management, and styling system documentation are added. Signals drive what gets written — the architecture document is shaped by your actual code, not a generic template.

Signal-to-Context Mapping

Signals do not just determine section depth in architecture.md. They flow through the entire context pipeline. When architecture is condensed into .ai-context.md, sections that received deep treatment produce more detailed entries. Sections that were skipped are absent from the condensed output. This means the 200-400 line AI context file is automatically tuned to your project's actual architectural concerns.

The signal state is also persisted to draft/.state/signals.json for incremental refresh tracking. On subsequent runs of /draft:init refresh, Draft re-classifies signals and compares against the stored baseline:

Signal drift detected:
  NEW:     auth_files (0 → 5) — Security Architecture needs generation
  GROWN:   backend_routes (12 → 24) — API Definitions, Cross-Module Integration need expansion
  REMOVED: background_jobs (3 → 0) — Concurrency section can be simplified
  STABLE:  services (8 → 9), test_infra (15 → 16)

New signal categories appearing (zero to non-zero) indicate structural drift: your project has gained an architectural concern that did not exist before. Draft flags these for section generation. Removed categories (non-zero to zero) indicate pruning opportunities.

Example: A React + Express Project

Consider a full-stack TypeScript project: React frontend with Express backend, PostgreSQL database, JWT authentication, and Redis caching.

Draft walks the file tree and produces this signal classification:

Signal Classification:
  backend_routes:    8 files   → API Definitions, Cross-Module Integration: HIGH
  frontend_routes:   6 files   → Architecture (add UI topology): HIGH
  components:       22 files   → Core Modules (add component hierarchy): HIGH
  services:          5 files   → Component Map, Core Modules: HIGH
  data_models:       4 files   → State Management, API Definitions: HIGH
  auth_files:        3 files   → Security Architecture: HIGH
  state_management:  3 files   → State Management (frontend state): HIGH
  background_jobs:   0 files   → Concurrency: SIMPLIFY
  persistence:       3 files   → State Management: HIGH
  test_infra:       18 files   → Testing Infrastructure: HIGH
  config_files:      6 files   → Configuration: HIGH

Nearly every signal category is active. This is a feature-rich project with both frontend and backend concerns. The resulting architecture.md will be comprehensive: full API catalog, component hierarchy with React component tree, auth flow documentation with JWT lifecycle, frontend state management with Redux store structure, database schema with Prisma models, and testing infrastructure covering both Jest (frontend) and Supertest (backend).

The only section simplified is Concurrency — no background jobs means the concurrency model is straightforward Express request handling and React rendering. No need for worker pool documentation or queue architecture.

Now contrast this with a Go CLI tool that has zero frontend files, zero components, zero state management, and zero auth. That project's signal classification would trigger deep treatment for only a few sections (services, config, tests) and skip everything frontend-related. Same tool, same process, radically different output — shaped entirely by what the code actually contains.

The Classification Procedure

Signal classification is not heuristic. It is a file-matching procedure that runs during Phase 1 of architecture discovery. Draft counts files matching each category's detection patterns, excluding standard ignore paths (node_modules/, .git/, vendor/, draft/). The procedure is language-aware — a Python project looks for @app.route decorators while a Java project looks for @RequestMapping annotations — but the signal categories are universal across all languages.

$ # Simplified detection for backend routes (actual procedure is per-language)
$ find . -type f \( -path "*/routes/*" -o -path "*/handlers/*" \
    -o -path "*/controllers/*" -o -path "*/api/*" \) \
    ! -path "*/node_modules/*" ! -path "*/.git/*" | wc -l
12

The result is a signal summary held in memory for Phase 5 (Synthesis), where it drives section-by-section generation decisions. It is then persisted to draft/.state/signals.json as the baseline for future drift detection.

Signals Are Discovery, Not Configuration

You do not configure signals. You do not tell Draft "this is a web app" or "skip the frontend sections." Draft discovers what your project contains by reading the file tree. If your project gains authentication files six months from now, the next /draft:init refresh will detect the new signal category, flag it as structural drift, and generate the Security Architecture section for the first time. The architecture document evolves with your code.