Understanding the depth and parentId Fields in the ADHD Idea Type
The depth field tracks how many levels an idea sits below the root of a divergence tree, while parentId references the immediate ancestor idea that spawned it, together enabling hierarchical traversal and branching logic.
The ADHD (AI-driven Divergence-Heavy Design) tool models brainstorming as a tree of related concepts, where each node is an Idea type defined in src/types.ts. The depth and parentId fields serve as the structural backbone of this hierarchy, allowing the system to trace lineage, render visual trees, and prioritize which branches to expand.
What the depth Field Represents
The depth property is a numeric indicator that measures an idea's vertical position within the divergence hierarchy.
- Value
0marks a root divergence—the first-level split from the original problem statement with no ancestors. - Values
1,2, … indicate ideas that have been deepened one or more levels, representing sub-ideas generated from earlier concepts.
This field serves multiple critical functions in the ADHD engine:
- Prioritization – The system uses depth to identify and expand the most promising branches when running divergence heuristics.
- Visualization – Rendering engines rely on depth values to create indented lists or tree diagrams that show conceptual nesting.
- Scoring context – Deeper ideas often reflect more refined or novel angles, allowing the scorers in
src/engine.tsto weight abstraction levels appropriately.
According to the ADHD source code in src/types.ts, the property is declared with the explicit comment 0 = root divergence, 1+ = deepened【source】.
What the parentId Field Represents
The parentId field stores the id of the immediate predecessor from which the current idea was derived.
- Definition – It contains the UUID string referencing the parent Idea that spawned this node during the divergence process.
- Optionality – This field is deliberately omitted for root ideas (where
depth = 0) because they have no ancestral node. - Traversal – By following
parentIdreferences, the engine can reconstruct full ancestry chains for back-tracking and explanation generation.
The parentId definition appears alongside depth in src/types.ts【source】, forming a lightweight pointer system that avoids storing full object references.
How depth and parentId Model the Divergence Tree
Together, these two fields create a standard tree structure without circular references:
| Depth | parentId | Meaning |
|---|---|---|
0 |
omitted | Root idea (no parent) |
1 |
root's UUID | First-level child of the root |
2 |
depth-1 idea's UUID | Grandchild (sub-idea of a depth-1 idea) |
n |
ancestor's UUID | Further nesting follows the same pattern |
When the engine executes a run via engine.run(...), it instantiates new Idea objects by assigning unique id values, computing depth based on the current recursion level, and recording the parentId of the spawning node. Later stages—including scoring, clustering, and deepening—navigate this graph efficiently using these hierarchical markers.
Working with Hierarchy in Code
Creating a Root Idea
Root ideas initialize the divergence process with depth: 0 and no parentId:
import { v4 as uuidv4 } from "uuid";
const rootIdea = {
id: uuidv4(),
frameId: "frame-1",
text: "Enable voice-controlled navigation",
depth: 0, // root divergence
// parentId omitted intentionally
};
Adding a Deepened Child Idea
Child ideas increment the depth and reference their parent's identifier:
const childIdea = {
id: uuidv4(),
frameId: "frame-2",
text: "Integrate with speech-to-text API",
depth: 1, // one level deeper than the root
parentId: rootIdea.id, // reference to its parent
};
Traversing the Ancestry Chain
To reconstruct the lineage of any idea, map ids to objects and follow the parentId pointers:
function getAncestors(ideaId: string, ideas: Idea[]): Idea[] {
const map = new Map(ideas.map(i => [i.id, i]));
const lineage: Idea[] = [];
let cur = map.get(ideaId);
while (cur?.parentId) {
const parent = map.get(cur.parentId);
if (!parent) break;
lineage.unshift(parent);
cur = parent;
}
return lineage;
}
Rendering a Visual Tree
The src/render.ts utilities group children by their parentId to produce indented output:
function renderTree(ideas: Idea[]) {
const byParent = new Map<string | undefined, Idea[]>();
ideas.forEach(i => {
const key = i.parentId ?? "root";
if (!byParent.has(key)) byParent.set(key, []);
byParent.get(key)!.push(i);
});
function render(nodeId: string | undefined, indent = 0) {
const children = byParent.get(nodeId) ?? [];
children.forEach(c => {
console.log(" ".repeat(indent * 2) + "- " + c.text);
render(c.id, indent + 1);
});
}
render(undefined); // start at roots
}
Key Files Implementing These Fields
| File | Purpose |
|---|---|
src/types.ts |
Declares the Idea interface including depth and parentId definitions |
src/engine.ts |
Orchestrates idea generation and manages branching logic using these fields |
src/render.ts |
Contains tree visualization utilities that parse the hierarchy |
tests/llm.test.ts |
Validates idea creation and hierarchy behavior in the test suite |
Summary
depthindicates vertical position in the divergence tree, where0represents root ideas and higher integers represent successive layers of refinement.parentIdstores the UUID of the immediate ancestor, omitted only for root nodes to maintain acyclic structure.- Together they enable efficient traversal, visual rendering, and intelligent branching in the ADHD brainstorming engine.
- The implementation resides primarily in
src/types.tswith consumption acrosssrc/engine.tsandsrc/render.ts.
Frequently Asked Questions
What happens if parentId references a non-existent idea?
The traversal logic in src/engine.ts and utility functions like getAncestors include null checks that break the chain if a parent lookup fails, preventing runtime errors while potentially logging warnings about orphaned nodes.
Can an idea have multiple parentId values?
No, the parentId field is singular by design. ADHD models strict hierarchical trees rather than directed acyclic graphs (DAGs), ensuring each idea has exactly one lineage path back to a root divergence.
Why is parentId optional in the TypeScript type?
The field is typed as optional (parentId?: string) specifically to accommodate root ideas at depth: 0, which logically have no parent. This design choice enforces referential integrity where only non-root nodes carry ancestral pointers.
How does the engine prevent infinite loops when deepening ideas?
The divergence process in src/engine.ts enforces depth limits and tracks visited id values during recursion. Since parentId references always point to shallower depths (lower numbers), the structure inherently prevents cycles by moving toward the root.
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 →