# How Clustering Surfaces Underlying Angles of the Idea Space in ADHD

> Discover how ADHD clustering surfaces strategic angles in idea spaces. This technique moves beyond keywords to reveal structural dimensions, enabling deeper design reasoning.

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

---

**ADHD's cluster pass explicitly forbids keyword-based grouping and instead forces the LLM to extract higher-level strategic angles, stamping every idea with its structural dimension so engineers can reason about the design space rather than superficial phrasing.**

The ADHD framework uses a dedicated cluster pass to reveal **how clustering surfaces underlying angles of the idea space**. By intentionally avoiding keyword-based grouping, the engine exposes deeper organizing principles that connect otherwise disparate concepts. According to the UditAkhourii/adhd source code, this transformation happens through a carefully engineered prompt and a set of enrichment steps defined in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts) and [`src/types.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/types.ts).

## How the Cluster Pass Surfaces Underlying Angles

### The Angle-First Prompt Design

The system prompt for clustering is deliberately restrictive. It instructs the model to *"group ideas into 3-6 clusters by their UNDERLYING ANGLE (not by surface keywords)"* and to return short, conceptual labels such as `"remove-the-server plays"` or `"cache-shaped plays"`. This prompt logic is defined in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts) at lines 91-94.

By prohibiting keyword matching, the prompt compels the LLM to reason about *why* ideas belong together. The resulting labels represent structural dimensions—dimensions like hardware-centric, budget-driven, or regulatory approaches—rather than shared vocabulary.

### Cluster Generation via `clusterIdeas`

The `clusterIdeas` function in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts) (lines 31-57) orchestrates the actual clustering. It accepts the problem statement and the flat list of generated ideas, then sends them to the LLM alongside the angle-based system prompt.

The LLM returns a JSON array where each element contains:

- A `label` string describing the underlying angle.
- An `ideaIds` array pointing to the ideas that share that angle.

This JSON structure is typed in [`src/types.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/types.ts), which defines the `Cluster` interface consumed downstream by the stamping logic.

### Stamping Angles onto Every Idea

Once the LLM returns the cluster set, the engine iterates over the array and writes the angle label directly onto each matching idea. In [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts) at lines 73-76, the code performs the enrichment:

```typescript
// Simplified representation of engine.ts L73-L76
clusters.forEach(c => {
  c.ideaIds.forEach(id => {
    const idea = ideaMap.get(id);
    if (idea) idea.cluster = c.label;
  });
});

```

After this step, every `Idea` object carries a `cluster` property. The framework can now render ideas grouped by their conceptual angle rather than by generation order or lexical similarity.

## Consuming Cluster Output in Your Code

The `RunResult` type in [`src/types.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/types.ts) (lines 38-41) exposes the cluster data to callers through a top-level `clusters` array. Engineers can inspect this array to see the complete map of underlying angles discovered during the run.

In practice, a typical call to the `run` function looks like this:

```typescript
import { run } from "adhd";

(async () => {
  const result = await run({
    problem: "Design a rate-limiter that survives leader election.",
    framesPerRun: 5,
    ideasPerFrame: 6,
  });

  // result.clusters surfaces the underlying angles:
  // [
  //   { label: "remove-the-server plays", ideaIds: ["id1", "id3"] },
  //   { label: "push-work-to-client plays", ideaIds: ["id2", "id5"] },
  // ]
  console.log("Clusters (underlying angles):", result.clusters);

  // Each idea carries its angle label:
  for (const idea of result.branches.flatMap(b => b.ideas)) {
    console.log(`${idea.text}  ←  ${idea.cluster}`);
  }
})();

```

Because `result.clusters` and `idea.cluster` are both populated, downstream views such as the `shortlist` view can group ideas by their strategic dimension. This gives teams a clear map of how the design space is organized and makes it easier to select non-obvious but viable directions.

## Summary

- ADHD's **cluster pass** is the second phase of the focus stage, specifically designed to reveal structure rather than preserve a flat list.
- The system prompt in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts) explicitly bans keyword grouping and demands **underlying angles** like `"remove-the-server plays"`.
- The `clusterIdeas` function sends the prompt to an LLM and receives a JSON array of clusters containing a `label` and `ideaIds`.
- The engine stamps each `Idea` object's `cluster` field with its angle label in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts) at lines 73-76.
- Callers receive the full clustering map through `RunResult.clusters`, enabling angle-based analysis and rendering.

## Frequently Asked Questions

### How does clustering surface underlying angles of the idea space?

ADHD's cluster pass forces the LLM to ignore surface-level keywords and instead extract the higher-level concept that connects a set of ideas. By requiring labels that describe structural dimensions—such as hardware-centric or budget-driven approaches—the prompt surfaces the true organizing principles of the design space.

### What is the difference between keyword-based grouping and angle-based clustering?

Keyword-based grouping would place ideas together simply because they share similar terminology, which often creates superficial clusters. Angle-based clustering, as implemented in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts), requires the model to identify the strategic rationale behind each idea, producing conceptual dimensions that reveal how the problem space is actually structured.

### Where does the cluster label get stored in the ADHD data model?

After the `clusterIdeas` function returns the cluster array, the engine iterates through each cluster and assigns its `label` to the `cluster` property on every matching `Idea` object. This enrichment logic lives in [`src/engine.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/engine.ts) lines 73-76, and the field is part of the `Idea` type defined in [`src/types.ts`](https://github.com/UditAkhourii/adhd/blob/main/src/types.ts).

### How can I access the cluster output after running the ADHD engine?

The `run` function returns a `RunResult` object that includes a `clusters` array. Each element contains the angle `label` and the `ideaIds` belonging to that angle. You can also traverse `result.branches` and read the `cluster` property on individual ideas to see which underlying angle each idea represents.