Why nonObviousPick Prioritizes Novelty Over Total Score in the ADHD Engine
The nonObviousPick prioritizes novelty over total score because the ADHD engine applies a two-step ranking strategy that first filters ideas by aggregate quality and then highlights the most novel viable candidate from the shortlist.
The nonObviousPick function is a core feature of the ADHD tree-of-thought engine in the UditAkhourii/adhd repository, designed to surface ideas that are both credible and surprising. If you have wondered why nonObviousPick prioritizes novelty over total score instead of simply returning the highest-ranked idea, the answer lies in a deliberate divergence-convergence pipeline. Understanding this design reveals how the engine balances viability with unexpected solutions.
How the ADHD Engine Filters Ideas by Total Score
Before nonObviousPick is ever calculated, the engine evaluates every generated idea through a scoring phase. Each idea receives a total value that weights novelty, viability, and fit, as defined by the Score type in src/types.ts near lines 16-18. The engine sorts all ideas by this aggregate score and retains only the top performers in a shortlist.
According to the source code, the Score.total field aggregates the individual dimensions to create an overall quality gate. This initial filter guarantees that only ideas strong across all metrics—high viability, strong fit, and meaningful novelty—advance to the next stage. You can see this scoring contract established at the top of src/types.ts.
How nonObviousPick Selects the Most Novel Viable Idea
Once the shortlist is locked, the engine shifts from filtering to highlighting. Rather than returning the idea with the highest total score from the shortlist, nonObviousPick applies a secondary ranking that intentionally weights novelty most heavily.
The Novelty-Weighted Formula in src/engine.ts
The selection logic lives in src/engine.ts at lines 88-95, where the shortlist is re-sorted using the expression b.score!.novelty + b.score!.viability * 0.5. The idea that ranks first after this sort becomes nonObviousPick. This calculation explicitly favors novelty while still rewarding viability through the 0.5 × viability term. As implemented in UditAkhourii/adhd, this means an idea with exceptional novelty can win even if its total score is not the absolute highest in the shortlist, provided it clears the initial quality threshold.
The "Non-Obvious-but-Viable" Design Goal
This behavior is intentional and documented in the engine’s comment header in src/engine.ts around lines 8-11. The design reflects a "non-obvious-but-viable" goal: the final recommendation must be practical enough to implement, yet distinct enough to avoid obvious or generic solutions. By splitting the process into a total-score filter followed by a novelty-centric selector, the engine ensures the pick is both credible and surprising.
Practical Example: Running the ADHD Engine
You can observe this two-stage behavior by calling the run entry point from src/index.js. The returned object contains both the shortlist (ranked by total score) and the nonObviousPick (chosen by the novelty-weighted rule).
import { run } from "./src/index.js";
(async () => {
const result = await run({
problem: "How can we improve remote team collaboration?",
ideasPerFrame: 4,
topK: 3,
});
// Top ideas filtered by total score
console.log("Shortlisted ideas:", result.shortlist);
// Final pick: highest novelty among viable ideas
const pick = result.nonObviousPick;
if (pick) {
console.log("🌟 Non-obvious pick →", pick.text);
console.log(" Novelty:", pick.score?.novelty);
console.log(" Viability:", pick.score?.viability);
console.log(" Total:", pick.score?.total);
} else {
console.log("No viable non-obvious idea found.");
}
})();
In this snippet, result.shortlist surfaces the strongest overall ideas according to Score.total, while result.nonObviousPick returns the idea selected by the novelty-centric formula in src/engine.ts. The console output often reveals a pick whose novelty score exceeds that of the top shortlist entry, demonstrating why nonObviousPick prioritizes novelty over total score in the final recommendation.
Summary
- The ADHD engine first filters ideas using
Score.totalinsrc/types.ts, ensuring only high-quality candidates reach the shortlist. - The
nonObviousPickthen re-ranks that shortlist insrc/engine.ts(lines 88-95) usingnovelty + 0.5 × viability. - This two-step approach guarantees the final pick is viable enough to be useful but novel enough to be non-obvious.
- The design intent is explicitly documented in the comment header of
src/engine.ts(lines 8-11).
Frequently Asked Questions
What is the difference between shortlist and nonObviousPick in ADHD?
The shortlist contains the top ideas ranked by aggregate Score.total in src/types.ts, representing the strongest overall candidates across novelty, viability, and fit. The nonObviousPick is a single idea drawn from that shortlist using the secondary novelty-weighted sort in src/engine.ts (lines 88-95). Together, they represent the filter stage and the highlight stage of the engine pipeline.
Why doesn't nonObviousPick simply choose the highest total score?
Choosing the highest total score would return the safest, most balanced idea, which is often the most obvious one. By weighting novelty more heavily after the initial quality filter, nonObviousPick fulfills the engine’s documented design goal of recommending solutions that are credible but unexpected. This is why the final selection step deliberately deprioritizes the total score in favor of standout novelty.
How does the ADHD engine calculate the total score for ideas?
The total score is defined in src/types.ts as an aggregated value combining novelty, viability, and fit. During the scoring phase, each idea is evaluated across these dimensions, and the composite total determines whether an idea qualifies for the shortlist. It acts as a quality gate before the novelty-centric nonObviousPick selection occurs.
Can I adjust the weight given to viability in nonObviousPick?
The current weighting is hardcoded in src/engine.ts as b.score!.novelty + b.score!.viability * 0.5. To change how much viability influences the final pick, you would need to modify the sort expression in that file and rebuild the pipeline. There is no external configuration flag exposed in src/cli.ts or the entry point to adjust this ratio at runtime.
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 →