adhd
LibraryUditAkhourii/adhd
Parallel divergent ideation for coding agents using tree-of-thought.
Overview
ADHD is a skill implementing tree-of-thought with pruning, spawning parallel divergent reasoning under isolated cognitive frames to avoid premature convergence. It scores, prunes traps, and deepens survivors, enhancing creativity for AI agents.
README Preview
\n \n \n \n\n\n# ADHD — a skill for agents\n\n[](https://github.com/UditAkhourii/adhd/actions/workflows/ci.yml)\n[](https://www.npmjs.com/package/adhd-agent)\n[](./LICENSE)\n[](./documentation/install.md)\n[](https://adhdstack.github.io/)\n[](https://thenewstack.io/claude-code-adhd/)\n[](https://discord.gg/NbWwkwwGw)\n\n\n\n> ### 🎮 [**Join the ADHD Discord →**](https://discord.gg/NbWwkwwGw)\n> This is where the real-time thinking happens: frame design, eval problems, trap-hunting, and neurodivergence-inspired research on reasoning architectures. If you've got opinions on premature convergence, cognitive frames, or just want to argue about the next eval problem — **[come argue with us live](https://discord.gg/NbWwkwwGw).**\n\n> 👉 [**Join the ADHD community →**](https://tally.so/r/WO1Nzj) as a contributor, maintainer, early adopter, or just a member. One short form. We coordinate frame contributions, eval problems, integrations, and adopter onboarding there.\n\n> **An architectural fix for premature convergence in autoregressive reasoning.**\n\nLinear Chain-of-Thought anchors on whatever it says first. Tree-of-Thought widens the search but still walks a single shared context, so the anchoring persists across branches. **ADHD treats this as an architectural problem, not a prompting one** — it spawns N isolated reasoning processes under deliberately distorted cognitive frames, with zero shared context during divergence, then runs a separate critic pass to score, cluster, prune traps, and deepen the survivors.\n\nReach for it on **design decisions, fuzzy debugging, naming, API surface design, strategy, and any prompt of the shape *"give me a few ways to…"***.\n\n📄 **Preprint:** [ADHD: Parallel Divergent Ideation for Coding Agents](https://adhdstack.github.io/) · 👤 **Author:** Udit Akhouri — [@akhouriudit](https://x.com/akhouriudit) · [LinkedIn](https://www.linkedin.com/in/udit-akhouri-10160a168/)\n\n---\n\n## Side-by-side: baseline vs ADHD\n\nOne eval problem, s
FAQ (2)
TroubleshootingHow to fix the wildcard frame missing about half the time when running `adhd --frames 1`?
This is a bug in selectFrames() in src/frames.ts when n === 1. It selects one random frame, appends the wildcard, then the final .slice(0, n) removes that wildcard unless the first frame was already wild-tagged.
**Immediate workaround:** use --frames 2 or higher. The wildcard guarantee works correctly for n >= 2:
adhd "your prompt" --frames 2
**Permanent fix:** reserve the wildcard before selecting the remaining frames so it can never be truncated:
const wildPick = wild[Math.floor(Math.random() * wild.length)];
const rest = shuffle(pool.filter((f) => f.id !== wildPick.id))
.slice(0, Math.max(0, n - 1));
return n <= 1 ? [wildPick] : [...rest, wildPick].slice(0, n);
Add a unit test asserting that every result from selectFrames(1) contains exactly one frame with the wild tag.
TroubleshootingHow do I stop one failed LLM call from canceling the whole branch fan-out and discarding completed results?
Replace Promise.all with Promise.allSettled for both the divergence fan-out (frames.map(...)) and the deepen pass (toDeepen.map(...)). Then process fulfilled results separately and collect rejected branches instead of letting the first rejection abort the run.
Example pattern:
const settled = await Promise.allSettled(
frames.map((frame) => divergeBranch(frame))
);
const branches: Branch[] = [];
const failedFrames: { frameId: string; error: string }[] = [];
settled.forEach((result, i) => {
if (result.status === "fulfilled") {
branches.push(result.value);
} else {
const frameId = frames[i].id;
const error = String(result.reason);
failedFrames.push({ frameId, error });
emitter.emit("frame:failed", { frameId, error });
}
});
Apply the same change to the deepen pass. Add failedFrames to RunResult in types.ts:
type RunResult = {
// existing fields
failedFrames: { frameId: string; error: string }[];
};
The CLI can then print partial failures such as ✗ <frame> failed: <reason>. The run should hard-fail only when every branch failed:
if (branches.length === 0) {
throw new Error("All LLM branches failed");
}
This handles network/LLM-layer throws such as rate limits, timeouts, and unrecoverable malformed responses. JSON-parse failures inside divergeBranch, scoreIdeas, and clusterIdeas already fail open by returning empty results. For rerun support, an optional checkpoint keyed by (frame_id, input_hash) can skip completed branches and retry failed ones with backoff.