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

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.

The SCORE_SYSTEM Prompt for Trap Detection

The critic operates through the SCORE_SYSTEM prompt defined in 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."

// 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 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 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.

// 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 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.

// 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 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 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.

// 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.
  • 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 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, 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.

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 can display these ideas with their specific warnings attached, allowing developers to make informed decisions about accepting the risk versus choosing safer alternatives.

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 →