# How Does the ADHD Engine Critic Detect and Flag Traps in Ideas?

> Discover how the ADHD engine's critic detects traps in ideas. Learn about hidden costs, schema validation, and segregated reporting for flagged concepts.

- Repository: [Udit Akhouri/adhd](https://github.com/UditAkhourii/adhd)
- Tags: internals
- Published: 2026-08-19

---

**The ADHD engine's critic detects traps by prompting the LLM to identify hidden costs in attractive ideas, validates the response against a schema that includes an optional `trap` field, and segregates flagged ideas into a dedicated array for separate reporting.**

The ADHD engine implements a tree-of-thought architecture with distinct divergent and convergent phases. During the convergent "critic" pass, the system evaluates generated ideas not just for quality scores, but for hidden pitfalls that appear attractive yet carry implementation risks. According to the UditAkhourii/adhd source code, this detection relies on specific prompt engineering, schema validation, and filtering logic within [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts).

## The SCORE_SYSTEM Prompt for Trap Detection

The critic operates through the **SCORE_SYSTEM** prompt defined in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts) (lines 71-88). This prompt explicitly instructs the LLM to enter "CONVERGENT mode" and act as a critic that scores each idea on three axes—**novelty**, **viability**, and **fit**—while simultaneously watching for deceptive attractiveness.

The prompt specifically requests an optional **"trap"** field when an idea looks promising but conceals hidden costs. Rather than dismissing the idea outright, the critic must describe the risk as a specific, actionable warning. For example, instead of labeling an idea as "bad," the trap description notes something like "solid for a prototype, breaks past 10k concurrent users."

```ts
// src/engine.ts - The prompt that enables trap detection (L71-L88)
const SCORE_SYSTEM = `You are in CONVERGENT mode. You are now the critic.
Score each idea on three axes 0‑10: novelty, viability, fit.

...  
- "trap" (optional): if the idea looks attractive but has a hidden cost
  (false economy, won't scale, premature abstraction), name it as a
  specific, actionable heads‑up — e.g. "solid for a prototype, breaks
  past 10k concurrent users" — not a dismissal like "bad idea."`;

```

## Schema Validation with ScoreRowSchema

The system enforces structured output through **ScoreRowSchema** ([`engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/engine.ts) lines 33-42). This schema defines the expected response shape, including an optional `trap?: string` property that captures the warning text when present.

The **Score** type defined in [`src/types.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/types.ts) mirrors this structure, ensuring type safety throughout the pipeline. When the LLM returns a trap description according to the SCORE_SYSTEM instructions, the field persists through all downstream processing, allowing the engine to distinguish between viable ideas and those requiring caution.

```ts
// Conceptual representation of ScoreRowSchema (L33-L42)
interface ScoreRow {
  id: string;
  novelty: number;
  viability: number;
  fit: number;
  strength: string;
  trap?: string;  // Optional field for hidden cost warnings
}

```

## The scoreIdeas Processing Pipeline

The **scoreIdeas** function ([`engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/engine.ts) lines 85-90) orchestrates the transformation from raw LLM response to structured data. It parses the JSON output against ScoreRowSchema, then maps each row into a **Score** object that preserves the optional trap value alongside numerical scores and strength statements.

During this mapping, the function calculates a weighted total score (novelty × 0.35 + viability × 0.4 + fit × 0.25) while maintaining the trap field as-is. This ensures that flagged ideas retain their full scoring context even as they are marked for special handling.

```ts
// Parsing the LLM response and preserving trap fields (L85-L90)
const rows = parseJSON(raw, ScoreRowSchema);
rows.forEach(r => {
  out.set(r.id, {
    novelty: r.novelty,
    viability: r.viability,
    fit: r.fit,
    total: r.novelty * 0.35 + r.viability * 0.4 + r.fit * 0.25,
    strength: r.strength,
    trap: r.trap,               // <-- trap string preserved if provided
  });
});

```

## Extracting and Segregating Trapped Ideas

After scoring completes, the engine filters the idea collection using the truthiness of the `score.trap` field ([`engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/engine.ts) lines 80-84). Ideas with defined trap strings populate a dedicated **traps** array, while the main shortlist excludes these entries to prevent developers from accidentally selecting risky options.

This segregation allows the UI layer in [`src/render.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/render.ts) to surface trapped ideas separately, presenting them as "attractive but risky" rather than eliminating them entirely. Developers can review the specific warnings—such as "false economy" or "premature abstraction"—while proceeding with safer alternatives from the primary shortlist.

```ts
// Collecting traps for dedicated reporting (L80-L84)
const traps = allIdeas.filter(i => i.score?.trap);
const shortlist = allIdeas
  .filter(i => i.score && !i.score.trap)   // exclude trapped ideas
  .sort((a, b) => b.score!.total - a.score!.total);

```

## Summary

- The **SCORE_SYSTEM** prompt explicitly requests trap detection for ideas with hidden costs, asking the LLM to provide specific warnings rather than dismissals.
- **ScoreRowSchema** validates an optional `trap?: string` field in the LLM response, ensuring type safety through [`src/types.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/types.ts).
- The **scoreIdeas** function maps trap values into Score objects alongside numerical ratings and weighted totals.
- Ideas with truthy `trap` values populate a separate **traps** array excluded from the main shortlist.
- Trapped ideas are surfaced separately in the UI via [`src/render.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/render.ts) for informed decision-making without polluting the primary recommendations.

## Frequently Asked Questions

### What constitutes a "trap" in the ADHD engine?

A trap identifies ideas that appear attractive initially but contain hidden costs, scalability limits, or architectural flaws. Valid trap descriptions provide specific, actionable warnings rather than vague dismissals, such as noting that a solution works for prototypes but fails under production load above 10,000 concurrent users.

### How does the critic distinguish between bad ideas and trapped ideas?

Bad ideas receive low viability or novelty scores, while trapped ideas may score highly on all axes yet contain a `trap` field describing the hidden risk. The engine excludes trapped ideas from the shortlist based on the presence of this field, not their numerical scores, allowing high-quality but risky ideas to be flagged rather than buried.

### Where is the trap detection logic implemented in the codebase?

The core logic resides in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts), specifically within the **SCORE_SYSTEM** prompt definition (lines 71-88), the **ScoreRowSchema** validation (lines 33-42), and the extraction logic (lines 80-84) that filters ideas into the traps array. The rendering logic lives in [`src/render.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/render.ts).

### Can trapped ideas still be selected by users?

Yes, the engine collects trapped ideas in a separate array available for UI rendering. While excluded from the automatic shortlist, [`src/render.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/render.ts) can display these ideas with their specific warnings attached, allowing developers to make informed decisions about accepting the risk versus choosing safer alternatives.