UditAkhourii/adhd Architecture: Main Components and Tree-of-Thought Engine
The UditAkhourii/adhd architecture comprises seven modular TypeScript components—Engine, Frames, Types, LLM Wrapper, Renderer, CLI, and Documentation—that orchestrate a five-phase tree-of-thought loop to transform problem statements into scored, clustered, and deepened ideas.
The UditAkhourii/adhd repository implements a tree-of-thought LLM orchestration system designed to break cognitive fixation through structured divergence and convergence. Its architecture separates concerns into distinct modules that handle everything from cognitive frame selection to terminal rendering, making the codebase extensible and testable.
Core Components of the UditAkhourii/adhd Architecture
The repository organizes functionality into seven primary modules. Each component owns a specific slice of the idea-generation pipeline, communicating through strict TypeScript interfaces defined in src/types.ts.
Engine
The Engine (src/engine.ts) serves as the central orchestrator, implementing the five-phase execution loop. It exposes the main run() function that coordinates the entire workflow: problem re-framing, frame selection, divergent generation, scoring, clustering, deepening, and provocation. The engine manages concurrency and aggregates RunEvent streams for real-time progress feedback.
Frames
The Frames module (src/frames.ts) maintains a curated registry of cognitive perspectives (e.g., hardware engineer, regulator, 10-year-old) and provides the selectFrames() utility. This function randomly selects a balanced subset of frames for each run, biasing toward "code" or "design" tagged entries when codeMode is enabled while guaranteeing at least one "wild" frame to ensure unconventional thinking.
Types
Types (src/types.ts) defines the domain model—including Idea, Branch, Cluster, RunResult, Score, and RunOptions—that creates type safety across the architecture. These plain TypeScript interfaces ensure that the engine, LLM wrapper, and renderer agree on data shapes when exchanging phase results.
LLM Wrapper
The LLM Wrapper (src/llm.ts) abstracts the underlying language model SDK behind callLLM() and provides JSON parsing utilities (parseJSON). It houses the system prompt templates—DIVERGE_SYSTEM, SCORE_SYSTEM, CLUSTER_SYSTEM, DEEPEN_SYSTEM, and REFRAME_SYSTEM—that instruct the model during each phase of the pipeline.
Renderer
Renderer (src/render.ts) handles human-readable output formatting through the renderText() function. It consumes a RunResult object and produces formatted terminal output with color coding, indentation levels, and "chip" style score displays for clusters and deepened ideas.
CLI
The CLI (src/cli.ts) wraps the engine as a command-line tool, exposing the adhd run command. It parses command-line flags (--frames, --topK, --codeMode), streams RunEvents to the console for progress indication, and delegates final output generation to the renderer.
Documentation
Documentation (documentation/how-it-works.md) provides the architectural rationale and algorithmic explanation, describing the philosophy behind the diverge-then-converge pattern and the "ADHD" cognitive mode.
The Five-Phase Execution Flow
Understanding how these components interact requires examining the runtime flow implemented in src/engine.ts.
Phase 0: Problem Re-framing
When stripAnchors is enabled, the engine invokes reframeProblem(), which calls the LLM with the REFRAME_SYSTEM prompt to strip implementation-specific assumptions from the input problem. This occurs in the initialization stage of the run() function.
Phase 1: Divergent Generation
The engine calls selectFrames() to choose perspective frames, then executes divergeBranch() for each selected frame. This function stitches the frame-specific prompt into DIVERGE_SYSTEM and requests ideasPerFrame short ideas from the LLM, creating parallel branches of thought.
Phase 2: Scoring and Clustering
All generated ideas undergo two critic passes:
scoreIdeas(): Applies theSCORE_SYSTEMprompt and calculates a weighted total using the formulanovelty × 0.35 + viability × 0.4 + fit × 0.25clusterIdeas(): UsesCLUSTER_SYSTEMto group semantically similar ideas intoClusterobjects
These passes filter out ideas containing "traps" and produce scored, clustered data structures.
Phase 3: Deepening and Provocation
The engine shortlists the top-K highest-scoring ideas for deepenIdea(), which invokes the DEEPEN_SYSTEM prompt to generate detailed sketches and child sub-ideas. Simultaneously, it identifies the highest novelty-plus-viability idea as the nonObviousPick and formats a provocative "What if...?" question without an additional LLM call.
Finally, the populated RunResult flows to renderText() for human consumption or stdout via the CLI.
Practical Implementation Examples
Running a Session Programmatically
Import the engine and renderer directly to embed ADHD in larger applications:
import { run, renderText } from "adhd";
const result = await run({
problem: "How can we reduce latency in our API gateway?",
context: "Node.js, Express, 2-region AWS deployment",
framesPerRun: 5,
ideasPerFrame: 6,
topK: 3,
concurrency: 4,
codeMode: true,
});
console.log(renderText(result));
This executes the full five-phase loop defined in src/engine.ts and returns a typed RunResult, which renderText() (exported from src/index.ts) formats into terminal-ready output.
Using the Command-Line Interface
Invoke the architecture via the CLI entry point in src/cli.ts:
npx adhd run "Enable offline-first editing for our collaborative markdown editor" \
--frames 7 --topK 4 --codeMode false
The CLI maps flags directly onto RunOptions interfaces, streams RunEvent progress notifications (e.g., frame:start, score:done), and prints the rendered result using the same renderText() function available programmatically.
Extending the Frame Set
Add custom cognitive perspectives by manipulating the exported FRAMES array before running the engine:
import { FRAMES } from "adhd";
FRAMES.push({
id: "quantum",
label: "Quantum physicist",
prompt:
"Treat the problem as if information is encoded in qubits. What superposition-style solutions appear?",
tags: ["design", "wild"],
});
New frames automatically participate in future runs subject to the selection logic in src/frames.ts, allowing domain-specific extensions without modifying core engine code.
Summary
- Modular Design: The UditAkhourii/adhd architecture separates concerns into Engine, Frames, Types, LLM Wrapper, Renderer, and CLI components.
- Tree-of-Thought Pipeline: The
run()function insrc/engine.tsorchestrates a five-phase flow: Re-framing, Divergence, Scoring/Clustering, Deepening, and Provocation. - Frame-Driven Divergence: Cognitive frames defined in
src/frames.tsforce perspective shifts, withselectFrames()ensuring balanced representation of technical and "wild" viewpoints. - Weighted Scoring: Ideas are evaluated using
novelty × 0.35 + viability × 0.4 + fit × 0.25within thescoreIdeas()pass. - Dual Interface: The same core engine powers both programmatic TypeScript imports and the
npx adhdCLI tool.
Frequently Asked Questions
What role does the Frame component play in the ADHD architecture?
The Frames component (src/frames.ts) provides the cognitive diversity mechanism by supplying perspective prompts (e.g., viewing a problem as a regulator versus a child). The selectFrames() function ensures each run includes a mix of domain-relevant and unconventional viewpoints, which is essential for the tree-of-thought divergence phase.
How does the Engine determine which ideas to deepen?
After the scoring phase, the engine filters out ideas containing "traps" and sorts the remainder by their weighted score (combining novelty, viability, and fit). The top-K ideas from this sorted list are passed to deepenIdea() using the DEEPEN_SYSTEM prompt, while the highest-scoring novel idea becomes the nonObviousPick for provocation.
Can I use ADHD without the CLI?
Yes. The core functionality is exported from src/index.ts as a programmatic API. You can import run and renderText directly into Node.js or Deno applications, bypassing src/cli.ts entirely while still executing the full five-phase architecture.
What is the purpose of the LLM Wrapper abstraction?
The LLM Wrapper (src/llm.ts) centralizes SDK interactions and prompt management. By isolating callLLM() and JSON parsing logic, the architecture can swap underlying providers or add retry logic without modifying the Engine or Frame components, and it keeps system prompts (DIVERGE_SYSTEM, SCORE_SYSTEM, etc.) version-controlled alongside the code.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →