How Paqad classifies a request

A deterministic classifier in the prompt hook labels each request in three stages: read the request and project, fill in complexity and risk from keyword rules, then adjust from module health and defect history. No AI model is called.

  • Planning
  • Checked against paqad-ai 1.91.1
  • Reviewed 25 September 2026 by Eliyce

What classification does

Classification turns your request into a set of labels: which workflow it is, which parts of the code it touches, how wide it is, what it affects, and how complex and risky it looks. paqad uses those labels to record the route and, for code changes, to pick the lane (see Routing and lanes).

It runs on every message, in the prompt hook of Claude Code and Codex CLI. It is fully deterministic: it reads the request text and files in your project, follows fixed rules and makes no call to an AI model. That makes it fast and repeatable, and also means it can misread an unusual request. The AI's own routing pick runs alongside it, and code edits are gated by the file being edited, not by the label.

Stage 1: read the request and the project

The first stage has a 300 millisecond time limit. If it runs out, the missing labels take safe defaults and classification carries on.

  • Workflow. The request is matched against a phrase table in priority order: pentest-retest (250), health-retest (245), pentest (240, including "security audit"), codebase-health (235), site-map-retest (233), site-map (232), root-cause-analysis (230), module-documentation (225), documentation-update (200), research (180), cleanup (170), bug-fix (160, "fix" or "bug") and feature-development (140, "implement", "build", "add", "feature", "develop"). If nothing matches and the request asks how, where, what, why, which, or says "explain", "example" or "show me", it becomes project-question.
  • Affected modules. Tried in order: file paths written in the request, then symbol names found in the code index, then retrieval matches when retrieval is on, then stack-based guesses (for example "migration" suggests database/migrations).
  • Scope. How far the change spreads (single-file, single-module, multi-module, system-wide), from the import graph of the resolved modules.
  • Impacts. Database, API, UI, compliance, customer-facing, reversibility and data sensitivity, from paths and words in the request.
  • Context budget hint. minimal, standard or deep, from scope and workflow.
  • Rule triggers. Which compiled project rules match the affected paths.

Stage 2: fill in complexity and risk

Complexity and risk come from keyword rules. A few examples:

  • "rename", "typo", "comment", "small", "tiny", "minor" or "one-line" suggest trivial complexity.
  • "migration", "schema", "column" or "table" suggest a schema change, which makes complexity and risk high.
  • "api", "endpoint" or "route" suggest an API change, and "page", "screen" or "component" a UI change, which make complexity medium.
  • "redesign" or "breaking api" make complexity high.

When the first stage resolved nearly everything with high confidence (a named file or symbol, a clear workflow, no sensitive rule triggers such as auth or payments, no question mark or "maybe"), the result is kept as it is. Otherwise the same rules are applied but the labels are tagged llm-confirmed or llm-guessed in the resolution map.

Despite the llm- names, no AI model is consulted in 1.91.1. The tags mark labels that came from keyword rules rather than hard project evidence, and they lower the confidence score.

Stage 3: adjust from project history

  • Module health. If any affected module is fragile, risk becomes high (tagged health-override). For a new feature that means the full lane. See Module health.
  • Defect history. paqad reads the recorded defect patterns in ~/.paqad/defect-patterns/ that mention the affected modules. A pattern seen more than 10 times sets a high risk floor; more than 5 times, or more than 3 matching patterns, sets medium (tagged defect-floor).
  • Plan versus actual. If at least three past plan-versus-actual records show the scope was badly under-estimated, complexity goes up one step; if at least three show it was badly over-estimated, it goes down one (tagged history-corrected). In 1.91.1 nothing writes these records yet, so this adjustment does not fire in practice.

A short history of recent runs is kept in .paqad/cache/classification-history.json (the last 50), which paqad-ai doctor reads for its "Classification override rate acceptable" check.

Confidence and the resolution map

Every result carries a resolution_map saying where each label came from, and a classification_confidence between 0 and 1.

Source tagWeight
deterministic, deterministic:mcp, deterministic:rag, deterministic:graph, deterministic:manifest, health-override, history-corrected, defect-floor1
llm-confirmed0.8
llm-overridden0.6
llm-guessed0.3
default and anything else0.1

Confidence is the sum of the weights divided by 15 (the number of labels that can appear), rounded to two decimals and capped at 1. A tag of session-resume can also appear when the labels were carried over from a change already in progress.

If the classification looks wrong

There is no command to override the lane. What you can do:

  • Name the files or modules in your request, which gives the classifier hard evidence.
  • Mark genuinely risky areas as sensitivity: high in docs/instructions/rules/module-map.yml; edits there are always held to the full lane.
  • Rely on the fact that edits outside docs/ and .paqad/ are gated as feature development whatever the label says.

Something on this page out of date or unclear? Open an issue on GitHub and name the page.