# How ADHD Detects and Prunes Traps (Broken Ideas) Using LLM Scoring

> Discover how ADHD detects and prunes broken ideas using LLM scoring. It automatically excludes flagged traps, preserving them for your review, ensuring cleaner results.

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

---

**ADHD identifies broken ideas by prompting the LLM to flag hidden costs during scoring, then automatically excludes flagged "traps" from the shortlist while preserving them for user review.**

The ADHD framework (Adaptive Divergent-Hybrid Decision-making) treats **traps** as ideas that appear attractive on the surface but conceal critical flaws—scalability limits, false economies, or unsustainable tradeoffs. This article explains how the `UditAkhourii/adhd` repository implements systematic trap detection and pruning through three coordinated pipeline stages.

## Scoring Stage: LLM-Powered Trap Detection

Trap detection begins in [`engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/engine.ts) with a carefully engineered system prompt.

### The SCORE_SYSTEM Prompt

Lines 82-86 define `SCORE_SYSTEM`, which instructs the LLM to return an optional `trap` field:

```

trap (optional): if the idea looks attractive but has a hidden cost ... 
name it as a specific, actionable heads-up

```

This prompt structure ensures the model actively searches for disguised problems rather than glossing over them.

### Score Parsing with Zod Validation

The `scoreIdeas` function (lines 14-27) processes LLM responses using **Zod schema validation**. Each returned JSON object populates a `Score` type that may include:

```typescript
interface Score {
  novelty: number;
  viability: number;
  fit: number;
  strength: string;
  trap?: string;  // Optional trap description
}

```

Example LLM output:

```json
{
  "id": "websocket-central",
  "novelty": 4,
  "viability": 6,
  "fit": 7,
  "strength": "simple implementation",
  "trap": "breaks after ~10k concurrent users"
}

```

## Filtering Stage: Automatic Trap Exclusion

Once all ideas are scored, the engine performs **semantic partitioning** in lines 80-86 of [`engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/engine.ts).

### The Separation Logic

```typescript
// Extract trapped ideas
const traps = allIdeas.filter((i) => i.score?.trap);

// Build ranked list excluding traps
const ranked = allIdeas.filter((i) => i.score && !i.score.trap);

// Final shortlist contains no traps
const shortlist = ranked.slice(0, topK);

```

This filtering guarantees that:

- **Downstream processing** (focus/deepen passes) only operates on viable candidates
- **No trap accidentally reaches** the final recommendation set
- **All trapped ideas are preserved** in a separate array for transparency

### Why Separate Rather Than Delete?

ADHD preserves traps rather than discarding them because:

1. **User awareness**: Teams can learn from rejected patterns
2. **Auditability**: The decision trail includes *why* an idea failed
3. **Iterative refinement**: A trap in one context may be solvable in another

## Presentation Stage: Dedicated Trap Rendering

The [`render.ts`](https://github.com/UditAkhourii/adhd/blob/main/render.ts) module handles user-facing output through the `renderText` function (lines 60-66).

### Terminal Output Structure

Traps appear under a distinct visual section:

```typescript
// Simplified from render.ts lines 60-66
if (traps.length > 0) {
  lines.push(`\nTraps (watch-outs, not verdicts)${"-".repeat(20)}`);
  for (const t of traps) {
    lines.push(` ${index++}. ${t.text}`);
    lines.push(`    ⚠️  ${t.score?.trap}`);
  }
}

```

This presentation convention uses **"watch-outs, not verdicts"** language to signal that traps are heuristic flags, not absolute rejections.

## Complete Working Example

The following runnable TypeScript demonstrates trap detection in practice:

```typescript
import { run } from "./engine.js";

async function demo() {
  const result = await run({
    problem: "Create a realtime collaborative text editor",
    framesPerRun: 4,
    ideasPerFrame: 5,
    topK: 3,
  });

  console.log("=== Trapped Ideas ===");
  for (const trap of result.traps) {
    console.log(`💡 ${trap.text}`);
    console.log(`   👉 ${trap.score?.trap}`);
  }

  console.log("\n=== Shortlist (trap-free) ===");
  for (const i of result.shortlist) {
    console.log(`✔ ${i.text} (N${i.score?.novelty} V${i.score?.viability})`);
  }
}

demo();

```

**Sample output:**

```

=== Trapped Ideas ===
💡 Use a central WebSocket server for all edits
   👉 breaks after ~10k concurrent users

=== Shortlist (trap-free) ===
✔ Peer-to-peer CRDT sync (N9 V7)
✔ Operational transformation with selective persistence (N8 V8)

```

## Implementation Files Reference

| File | Purpose | Key Location |
|------|---------|--------------|
| [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts) | Core orchestration: scoring, trap filtering, shortlist creation | Lines 14-27, 80-86 |
| [`src/types.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/types.ts) | TypeScript definitions for `Score` with optional `trap` field | `Score` interface |
| [`src/render.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/render.ts) | Terminal output formatting with dedicated traps section | Lines 60-66 |
| [`tests/llm.test.ts`](https://github.com/UditAkhourii/adhd/blob/main/tests/llm.test.ts) | Unit tests verifying trap field parsing | Test suite |

## Summary

- **Detection**: The `SCORE_SYSTEM` prompt in [`engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/engine.ts) explicitly solicits trap descriptions from the LLM
- **Storage**: Traps populate the optional `Score.trap` string field, validated by Zod
- **Pruning**: The filtering logic separates trapped ideas before shortlist construction (lines 80-86)
- **Transparency**: [`render.ts`](https://github.com/UditAkhourii/adhd/blob/main/render.ts) displays traps distinctly, preserving visibility without polluting recommendations
- **Safety**: Downstream "focus" and "deepen" passes operate exclusively on trap-free candidates

## Frequently Asked Questions

### What qualifies as a "trap" in ADHD?

A trap is any idea with a **hidden cost that undermines its apparent value**. Common patterns include scaling bottlenecks, legal risks, maintenance burdens, or false economies. The LLM identifies these during scoring based on the problem context and the explicit `trap` prompt instruction.

### Can a trapped idea ever reach the final shortlist?

**No.** The filtering logic in [`engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/engine.ts) (line 83) builds `ranked` exclusively from ideas where `!i.score.trap` is true. The `shortlist` array is sliced from this pre-filtered list, making trap inclusion architecturally impossible without code modification.

### How does ADHD handle ambiguous trap classifications?

When the LLM returns a `trap` value, ADHD treats it as definitive for exclusion purposes. However, the "watch-outs, not verdicts" framing in [`render.ts`](https://github.com/UditAkhourii/adhd/blob/main/render.ts) reminds users that these are **heuristic flags** from language model inference. Teams can manually review traps via the `result.traps` array and override decisions outside the automated pipeline.

### Is trap detection configurable or disableable?

The current implementation in `UditAkhourii/adhd` has **hardcoded trap detection** as part of the core scoring protocol. The `SCORE_SYSTEM` prompt (lines 82-86) always requests trap analysis. To disable trap detection, you would need to modify the prompt and remove the filtering logic in the `scoreIdeas` flow.