| name | why-tree |
| description | Diagnose a hard problem by building an evidence-graded "Why Tree" - a Goldratt Current-Reality Tree that fans many AI agents across the problem's branch-space, grades every node by the kind of evidence behind it (validating measured numbers' pipelines before trusting them), tries to refute its own load-bearing branches, and converges on the ONE system constraint plus the cheapest test that would prove it. Use when someone asks "why is X happening / why are we falling short of a goal", wants a root-cause analysis with real rigor (not a 5-minute 5-Whys), needs to find the real bottleneck before spending build effort, or asks to "stress-test our diagnosis" / "build a current-reality tree". Also runs an **Idea Audit** - evaluating a product/feature idea by first diagnosing the problem it claims to solve (idea quarantined from the swarm), then judging the idea against the located constraint - trigger on "evaluate my product idea", "should I build X", "would anyone pay for this", "would my product have solved this". Bilingual triggers - "почему мы не достигаем цели", "построй дерево текущей реальности", "найди настоящее узкое место", "оцени идею продукта", "поможет ли мой продукт решить эту проблему". Pairs with /constraint-finder, which returns the 5 Focusing Steps once the constraint is located. Token-heavy by design (multi-agent) - it warns and asks for a depth before launching (a cheap scout gate can triage whether the swarm is needed at all), and only earns its cost when one careful pass could confidently pick the WRONG cause. |
Why Tree
A Why Tree is 5-Whys grown up. Naive root-causing follows a single thread, stops at the first plausible cause, and cites nothing. A Why Tree (Goldratt's Current-Reality Tree) does the opposite: it searches the whole branch-space in parallel, grades every node by the evidence actually behind it, tries to refute its own load-bearing branches, and converges on the ONE constraint that, if removed, unblocks everything else - plus the negative branches (fixes that backfire) and the single cheapest test that would fork-decide the conclusion.
The output is a self-contained interactive HTML tree + a one-page decision doc (constraint located / do this / don't do that / cheapest test).
This rigor costs tokens - real Deep field runs have landed at ~90-115 agents / 5.5-6.6M tokens. The skill is transparent about that cost and gates on a depth choice before launching (Phase 0), and when the depth isn't obvious it offers a cheap scout gate (Phase 1.5) that measures whether the swarm is even needed. Do not skip the gate.
What makes it different from a normal root-cause analysis (read first)
- Branch-space first, depth second. Map all the candidate "why"s from many independent lenses before deepening any one. A single-thread analysis finds the first cause; a tree finds the real one.
- Every node is graded. Each node carries an answer-kind (is this MEASURED, an INSTANCE, EXTERNAL, a CLAIM, an INFERENCE, a HYPOTHESIS, or just FRAMING?) + a confidence grade + a citation — and every MEASURED node additionally carries a validation state (
raw/validated/triangulated/contested): a number is not yet a fact until its pipeline is checked. Ungraded assertions are banned. See references/answer-kinds.md.
- Refute before you trust. Load-bearing branches face an adversarial pass that tries to kill them. Branches that die are marked REFUTED/DOWNGRADED with the evidence that killed them - kept visible, not deleted (they're the most useful part).
- Converge to ONE. Goldratt: there is one constraint; everything else is noise. The tree forces convergence to 3-5 roots and names the single system constraint - often a policy/ownership problem wearing a tooling costume.
- Honest census. If the decisive nodes are still HYPOTHESIS (unmeasured), the tree says so out loud: "a map of where to look, not a verdict."
If you find yourself shipping five co-equal "root causes," a tidy single-thread chain, or a confident verdict built on unmeasured nodes - you did it wrong.
Phase 0 - Frame the apex + the token-cost gate (do not skip)
(a) Sharpen the apex. State the problem as ONE undesirable effect — a declarative STATEMENT of the bad thing, ideally a gap-vs-goal: "Too few X vs the N target by ", "Free→paid conversion is below T". Not a question ("Can we evaluate X?" / "Why is conversion low?") — a question can't have children that read as "…because…", which breaks the whole "why" chain. Keep any question as a title; the apex node is the statement. The apex is itself a FRAMING node - it's a hypothesis about what the real problem is, and the tree may reframe it. Push back if the apex is a solution in disguise ("why don't we have feature Y" is a smuggled answer, not a problem) — but when the user's actual ask is to evaluate that solution ("I want to build X — would it work?"), don't stop at the pushback: that's Idea Audit mode, see (a3). Also reframe a measurement / "how many" question ("how many X, how relevant, how many meetings?") into the underlying gap or decision ("can we evaluate ROI of Y - and what's the constraint?"); the counts are evidence (Phase 1), not the apex. Don't build a tree on a pure data-pull.
First — does this problem even need the skill? A blind head-to-head ablation (3 problems) found that on a clear-cut problem a single agent beat the full workflow at ~1/50th the cost. The machinery only earns itself when one mind can confidently go wrong: cohort/measurement traps, several plausible roots competing, a buildable mechanism hidden under a symptom, or more branches/evidence than one context can hold. If the answer is obviously legible to one careful pass, say so and answer it directly — do not run the workflow. (This is why Quick mode was removed: for a cheap sketch, a single agent dominates it.) When it is NOT obvious either way — the common case — do not guess: clear-cut is measurable, not readable. Recommend the scout gate (Phase 1.5) at the depth gate and let three blind cheap passes demonstrate convergence or divergence before anyone pays for the swarm.
(a2) Classify the apex: symptom vs target — it picks the output shape. Two kinds of gap-vs-goal apex want two different answers, and conflating them is a real failure mode (a target apex run as a pure constraint tree once silently dropped a whole growth lever because converge refuted everything down to one):
- Symptom apex — "X is leaking / under-converting / broken." The classic CRT: converge to the ONE binding constraint.
apexType:'symptom' (default).
- Target apex — "hit N by date / grow X→Y" — a number someone chose, reachable by several additive paths. Run the same tree plus a lever-decomposition: the parallel levers to N, each sized (volume × conversion → contribution), so the verdict is "here's the bottleneck AND the arithmetic for whether the levers sum to N" — not a lone bottleneck.
apexType:'target'.
- Say the fit out loud for a target apex: "This is a growth-target apex. A constraint tree hands you one bottleneck, not a portfolio that sums to N — I'll run it in lever mode so you also get the sized paths and an honest 'do they sum to the number?'." Levers are parallel paths, not rival causes: one may be deprioritized (with a stated reason) but never refuted away like a wrong cause.
(a3) Idea apex → Idea Audit mode (judge the idea against the tree, never the tree against the idea). When the invocation IS a proposed solution — "I want to build X / would X work / оцени идею продукта" — don't reject the smuggled solution; invert it. Goldratt already named this move: a proposed solution is an injection, and an injection is never judged against the symptom — only against the Current-Reality Tree (CRT→FRT, references/methodology.md). The wrapper protocol:
- Capture the idea verbatim, structured:
idea: {statement, claimedProblem, mechanism, buyer}. The claimedProblem ("onboarding takes 3-5 months") is a founder assertion — it enters the Phase-1 source registry as a CLAIM-tier source ({id:'founder', tier:'raw'}), never as a fact. Then extract the undesirable effect the idea presupposes (a "knowledge-navigation product for onboarding" presupposes "onboarding takes 3-5 months with no early signal on fit or progress") and confirm it with the user: "the tree diagnoses THIS problem; your idea gets judged against the constraint it finds." Scrub solution-shaped language from the apex: phrase it as facts about the world (what happens, how long, what it costs), never as the absence of the idea's mechanism — "no early signal" is honest when the idea is a knowledge tool (the field case), but if the idea IS an early-signal instrument, that clause is the pitch restated as an absence, and the swarm is anchored through the front door while the quarantine locks the back. If you can read the pitch off the apex, rewrite the apex before launching. That problem is the apex — apexType is still symptom or target per (a2); Idea Audit is a wrapper around the normal run, not a third tree shape.
- Quarantine the idea from the swarm (anti-anchoring). The idea must never appear in a scout/lens/deepen/refute prompt — a swarm that knows the pitch bends toward the causes the pitch needs, and the fit-check becomes circular. Same rule as scout branches and prior verdicts. Only the post-converge fit-check stage (Phase 2, step 6c) ever sees it. Watch the evidence brief: the user's dictated context usually contains the pitch verbatim (it did in the field run), so when freezing the Phase-1 brief carry the problem's facts and strip the idea/solution language — the brief is a leak vector into every prompt.
- Run the tree normally — depth gate, scout gate, data gate, all unchanged. After converge, the fit-check (+2 agents) maps the idea onto the finished tree and emits
ideaFit; the decision doc then leads with the idea verdict (Phase 5). Two mode interactions: if the scout gate ships direct, the fit-check pair still runs — against the scout consensus (the constraint + its decisive evidence) with a degraded contract: no tree means no node ids, so addresses/restsOn use the sentinel ['scout-consensus'] and the mini-doc's idea section is forced to the verify-first treatment ("judged against a scout consensus, not a drilled tree" — a fully orphanable verdict needs the full run). In the fit-check is : the run saves the idea in the output JSON with an marker and says so in the deliverable; the fit-check fires in the Phase-6 loop once the decisive tests come back (a fit verdict over an unsettled map would rest on hypotheses).
(b) Pick a depth - and state the cost plainly. Present these and wait for one explicit choice (the choice may be the scout gate — that IS a valid answer, and the recommended one when the user is unsure). Describe scale by agent-count and breadth, never by time:
| Depth | Agents (approx) | What it does | When |
|---|
| Scout gate | ~4-5 (~100-150k) | 3 blind cheap passes + convergence judge + consensus refuter (Phase 1.5) — measures whether this problem even needs the swarm. Ships the answer directly if clear-cut is demonstrated; escalates to a depth choice with receipts if not. | Recommended default when the user doesn't know the depth. |
| Standard | ~22-40 | 6-lens branch map + grade every node + measurement audit (validate/triangulate the load-bearing numbers) + one refute pass + converge to one constraint + drill the constraint branch to bedrock. | The default for a known-confusable decision. |
| Deep | ~32-60 by cap arithmetic; observed 90-115 | Adds loop-until-dry discovery, a 3-vote multi-lens refute panel, a wider measurement audit, full CLR audit, cheapest-test design, + the constraint drill. The exhaustive pass. | High-stakes, contested, oversized, expensive-to-get-wrong. |
| Test-plan | ~10-18 | Fan-out + grade + audit + light refute + converge — then stops at a branch-map + ranked cheapest-tests + Data Request (markdown; no drill, no narrate, no HTML). | When the decisive sources are human-only (internal BI, an ERP/1C, ad consoles) — the deliverable IS the test plan, because the verdict can only come from tests the user runs. |
(Agent count = lenses + deepen + measurement audit + refute fan-out (the multiplier) + converge + drill + narrate; a target apex adds +1 lever agent, Idea Audit adds +2 — fit + fit-skeptic. See the blueprint's cap arithmetic. Older "~12-16 / ~25-30" figures predate the caps + drill + audit steps.) Observed cost: ~30-60k output tokens per agent (real field runs — Standard: 26 agents ≈ 833k; Deep: 91 agents ≈ 6.6M and 111 agents ≈ 6.4M). The cap arithmetic gives Deep ≈ 32-60 agents, but loop-until-dry + the 3-vote refute multiplier compound in practice: quote Deep at ~90-115 agents / ~5-7M tokens, not the arithmetic floor. State explicitly, e.g.: "Deep runs ~90-115 subagents and consumes ~5-7M tokens. Confirm before I launch." Never launch Deep without confirmation; if running headless/delegated with a pre-granted "depth+cost authorized", proceed without pausing. The hard caps (MAX_DEEPEN/MAX_REFUTE/MAX_AUDIT) bound the worst case — an early uncapped run spawned 171 agents and the blowup rate-limited and degraded its own refute pass — so the caps are a correctness guard, not just cost. If the user gave a token budget (a "+Nk" directive), scale depth to it.
Test-plan mode is not Quick mode back from the dead. Quick was a cheaper verdict and lost to a single agent (the ablation above). Test-plan is a different output shape for a specific situation the full run mishandles: when Phase 1 shows the metrics that would decide the tree live behind sources only the USER can operate, a full run grades the decisive nodes HYPOTHESIS anyway and the human ends up running the real diagnosis afterwards. In that case half the value is test design — the tree serves as a table of contents, and the run continues through the Phase-6 update loop as test results come back. If the named sources are clearly human-only at invocation time, offer this mode in the gate.
(c) Confidentiality check. If the source evidence is a client's private data, ask whether the output may name them. Default to an anonymized tree. In Idea Audit, the most confidential thing in the run is the unlaunched idea itself — it lands verbatim in why-tree-output.json and inside an HTML built to survive being emailed, and the redirect is by construction a better product idea than the one on trial: ask whether the idea may be named in shared artifacts, and default to a redacted idea.statement ("a knowledge-navigation tool for onboarding") outside the local JSON.
Phase 1 - Inventory the evidence sources
Before launching, enumerate what the research agents may actually read - this determines how much of the tree can be MEASURED vs left as HYPOTHESIS:
- Web - Exa (
mcp__exa__*, mcp__exa-research__*) and/or the firecrawl skill for competitive/external facts, market data, public docs.
- Local files / data the user names - a folder, a CSV/JSON export, prior reports, transcripts, DB query results. Ask for paths.
- Live data - if a DB or API is reachable and the user authorizes it, agents can run their own reads (this is what produced the "6/6 sampled accounts had a 2nd seat" refutation in the source case).
- Curated/derived sources — ask for these explicitly. The dashboards, BI reports, finance P&L, and management reporting the business ALREADY trusts — where bots, definitions, and seasonality were cleaned once, upstream. The reflex question "what DB/API/files can I read?" misses them, and a field run paid for it: the only clean source for the decisive metric was a curated dashboard nobody asked about, and the human had to steer the skill to it by hand. Ask: "which of these metrics has a report you already trust?" When a raw-computed number and the curated source disagree, the node is CONTESTED (see
answer-kinds.md) and the discrepancy is itself a finding — usually a definition mismatch on the raw side.
- Prior runs (anti-contamination) - if a previous Why Tree exists for the SAME problem, you may reuse its frozen evidence brief (the Phase-1 facts), but do NOT read its decision-doc / tree / verdict. Reading the prior conclusion anchors the lenses and leaks (a converge agent once copied "171 agents" from a prior doc straight into its output). Re-derive from evidence, never from the old answer.
Compute the hard metrics FIRST. For data-grounded problems, actually pull/compute the key numbers in Phase 1 (run the query, read the files) and pass them into the workflow as a frozen evidence brief with "do NOT re-query". This grounds nodes as MEASURED instead of HYPOTHESIS, and stops N parallel agents from re-hammering the same DB/API. Pull shared/expensive evidence ONCE.
Build a source registry + run the cleanliness gate BEFORE freezing the brief. The frozen brief is a single point of contamination: if a dirty number enters it, every downstream node inherits the artifact wearing a MEASURED badge — and "do NOT re-query" guarantees nobody re-checks. So before freezing, register every source as {id, tier: canonical|curated|raw, known caveats} and run the pipeline-cleanliness checklist (references/answer-kinds.md) ONCE per source: who's in the denominator (bots/internal/test traffic)? does the metric's definition match the claim's meaning (placed-vs-paid, sessions-vs-users)? is the window seasonal? attribution sound? extract pre-filtered? any computation traps (join explosion, average-of-averages, partial periods)? what is this instrument structurally BLIND to (only-successes · only-completers · partial ID coverage · a DB row that exists only on success)? and if the metric claims what a SYSTEM DOES or TRACKS, was it verified by RUNNING the system and watching, not inferred from a code-grep? Every metric in the brief then carries its source id + a validation state; a number from an unchecked source enters as MEASURED validation:'raw' — which caps at grade Mod and can never support the constraint. Persist the registry as why-tree-sources.md next to the output JSON and reuse it in later runs and the Phase-6 update loop — source tiers, caveats, and standard exclusions are evidence, not conclusions, so reusing them doesn't violate anti-contamination (and a company data-context/warehouse-docs skill, if one exists, seeds the registry for free). This gate is one orchestrator-level pass, zero extra agents — and it is the cheapest fix for the field failure mode: a real run shipped three MEASURED/high-confidence "facts" (bots in the denominator; an API definition mismatch; a seasonal trend) that burned 4 of 6 follow-up iterations, all three catchable here.
Measurable-in-hand gate (do not skip). Before any node is graded HYPOTHESIS or CLAIM, ask: "would one more query/read over sources I can reach (already pulled, OR one query away from an authorized DB/API/analytics store) settle this?" If yes, it is not a HYPOTHESIS — run the check and grade it MEASURED. A node that is cheaply measurable but left unmeasured is a worse failure than a genuinely-external unknown, and they must not be lumped together. Because the frozen brief can't be enriched mid-run (it feeds every prompt — adding to it invalidates the whole run's cache), at Phase 1 enumerate the funnel/mechanism decomposition the owner has in mind (e.g. provide ICP → 3 reference leads → calibrate → generate → connect → send) and PULL every queryable stage BEFORE freezing; discovering mid-run that a decisive metric was one query away all along is exactly the failure this gate prevents. Tag every HYPOTHESIS/CLAIM node with a gap: in-hand (reachable now — compute it from the source, incl. data queryable-but-not-yet-pulled; never ship it ungraded), external (needs new data we genuinely can't reach), or experiment (needs a test). Only external/experiment gaps are legitimate unknowns (they become the Data Request); the workflow's deepen guard fails loud on any in-hand gap left ungraded.
Distribution-behind-threshold rule. Whenever you compute a funnel step as a threshold (≥N, hit-the-wall, activated, churned), also pull the distribution of the underlying quantity before making any causal claim about why people don't cross it. "83% never hit the 50-seat wall" is silent on whether they died at 5 of 50 or 48 of 50 — opposite diagnoses with opposite fixes. A threshold count may not carry a causal claim the distribution would overturn.
Write a one-line measurability note: "X and Y are queryable; the decisive number Z is not in any source we have - it will stay HYPOTHESIS and become the #1 cheapest-test." This honesty is the point - it tells the user what the tree can and cannot settle.
The pre-flight data-gate (ask ONCE, here — never mid-run). This is the one point where the skill should ask you for data. Before launching the (expensive) swarm, list the 3-5 metrics that will actually decide the tree, mark which are queryable from what you gave me and which are not, and ask a single question: "these decide it; [A,B] I can compute, [C,D] aren't in any source I have — do you have them / a source, and which of them has a dashboard/report you already trust (so I can triangulate my raw computations against it)? Or should they stay hypotheses and become the data request?" Wait for one answer, then launch. A single cheap round-trip here stops a 2M-token run from going blind on a number you had all along. Skip the gate only when the user pre-authorized "just run it" or the sources are obviously complete. Interaction lives at the edges — the Phase-0 depth gate, this data gate, the scout-gate routing, and the Phase-5/6 Data Request — never inside the swarm: 50 parallel agents can't pause for a question, so an agent that "wants to ask the user" mid-run must instead tag the node gap:external and route it to the Data Request.
"interview me" mode. If the user invokes with interview me (or names no data/files), run a short structured intake BEFORE Phase 2 — this is the channel for evidence that lives in someone's head, not in any queryable source (the team-knowledge an LLM can't pull). In one pass, ask for: the gap-vs-goal numbers; the 3-5 metrics they know off-hand; any files/DB/dashboards the agents may read; what should ALWAYS be filtered out of any query (test data, internal users, bots, fraud — the standard-exclusions question that catches denominator pollution before a single query runs); what the key entity/metric words exactly mean here ("when you say 'order'/'user'/'AOV', is that placed or paid, account or person? — the entity-disambiguation question); and the one or two unknowns they already suspect are decisive. Capture the answers as the frozen evidence brief + source registry, then proceed.
Phase 1.5 - The scout gate (measure clear-cut, don't guess it)
The open question a field user asked — "how do I recognize a clear-cut problem BEFORE spending 833k tokens?" — has no reading-based answer: confusability is not legible from the problem statement (a real run's constraint re-anchored twice under testing; nobody could have called that ex ante). But "one mind can confidently go wrong" is directly measurable: run three cheap minds blind and see whether they land in the same place.
Protocol (~4-5 agents, ~100-150k tokens — state this cost too):
- 3 blind scouts in
parallel(), each over the Phase-1 sources, each returning structured {constraint: one sentence, decisiveEvidence: {claim, source, kind}, wouldRefuteMe: the test that would kill my answer}. Independent — no scout sees another.
- Convergence judge (1 cheap agent): do the three name the SAME binding constraint?
{converged, clusters, consensus}.
- Consensus refuter (1 agent, only when converged): attack the consensus from the dirty-pipeline + data-says-otherwise angles, default-to-refute.
Routing:
- Converged + the decisive evidence is MEASURED from a validated source + survives the refuter → clear-cut is demonstrated. Ship the answer directly as a mini decision-doc ("3/3 scouts converged; consensus survived adversarial refutation; decisive evidence: X") at ~1/10 the full-run cost. Do not run the workflow. (In Idea Audit, ship-direct still owes the user the idea verdict — run the fit pair against the consensus under the degraded contract in (a3): sentinel
restsOn, forced verify-first.)
- Diverged (different constraints, or same constraint on different load-bearing evidence) → confusability is demonstrated, not assumed. Present the Phase-0 depth gate with the receipts: "three independent passes named N different constraints — this is exactly the case where one careful pass goes confidently wrong." The user now buys the swarm informed. Scout branches join the Phase-2 dedup pool as extra fan-out entries — but are NEVER injected into the lens prompts (anti-anchoring).
- Converged but the consensus rests on evidence agents cannot measure (human-only sources) → Test-plan mode — no depth of swarm can settle what only the user's queries can.
The guard that makes this safe — consensus is NOT clear-cut by itself. Independent minds converge on the intuitive story too: in the Fish Banks field run, three scouts would plausibly have agreed "players were too cautious" — the facilitator's own first read — and it is refuted by simulation (worst-case racing agents at N=3 still leave the ocean alive 775/1000). Votes don't gate; evidence + surviving one refutation attempt gates. A consensus killed by the refuter escalates to the full run with that kill as the receipt.
Record the outcome in the tree's provenance.triage ({scouts, converged, decision, receipt}) so the gate's calibration is auditable across runs — the Phase-6 update loop will expose any "shipped-direct" verdict that later proves wrong.
Skip the gate when: the user explicitly picked a depth; the user pre-authorized "just run it"; Phase 1 already shows the decisive sources are human-only (go straight to Test-plan); or the problem is so obviously trivial you'd answer it inline. When the user names no depth, the scout gate is the default recommendation at the Phase-0 gate — present it as the first option with its cost stated like any other depth, and get the one confirmation there (its ~100-150k is real money too; never spend it silently). One confirmation total: the Phase-0 answer "scout gate" authorizes the scouts AND, on escalation, the follow-up depth question with receipts.
Phase 2 - Run the Workflow (the engine)
Use the Workflow tool with the blueprint in references/workflow-template.md. (The blueprint's stage comments carry their own numbering — match stages by their phase() label, e.g. this list's step 6c = the blueprint's 'Idea fit' stage.) The shape (scaled by the chosen depth):
- Branch-space fan-out (
parallel() barrier) - one agent per lens, each blind to the others, each emitting candidate WHY-branches under the apex. Lenses: funnel/mechanics · data-skeptic (audit the numbers) · competitive/external · customer-psychology/segments · economics/incentives · product-eng-constraint. More lenses = wider net.
- Dedup + bucket (plain code, not an agent) - merge overlapping branches; bucket into journey stages + a cross-cutting group.
- Deepen + grade (
pipeline() per branch) - recursively ask "why does this happen?" loop-until-dry to bedrock (Deep) or one level (Standard); attach answer-kind + confidence + citation to every node using references/answer-kinds.md. Research agents pull evidence from Phase-1 sources here. Cap the fan-out (MAX_DEEPEN) — dedup first, rank by load-bearing, then drop the tail (and log() what was dropped).
3b. Measurement audit (bounded parallel(), ≤MAX_AUDIT) - for each load-bearing MEASURED node still validation:'raw', one auditor attacks the pipeline, not the causal logic: the cleanliness checklist (denominator, definition, window/seasonality, attribution, survivorship, computation traps) + triangulation — if a second independent source in the registry can compute the number, compute and compare. Agree → validated/triangulated; disagree beyond tolerance or in sign → contested (grade drops to Weak, both values stay visible, the node can't support the constraint, and the reconciliation auto-joins tests[]/dataRequest[]). This pass exists because the refute pass won't catch dirty numbers: refute hunts THIN evidence, and a MEASURED/Strong artifact doesn't look thin (the exact field failure — three artifacts shipped as high-confidence facts).
- Adversarial refute (perspective-diverse
parallel()) - for each load-bearing branch, independent skeptics each try to refute it from a distinct angle (data-says-otherwise / mechanism-broken / survivorship / mis-attribution / dirty-pipeline). The dirty-pipeline angle is ordered FIRST for branches resting on MEASURED evidence — strong-looking numbers are exactly where the classic angles don't look — and costs no extra agents (it re-orders the angle list, not the vote count). A branch that more than half the skeptics refute is marked or , keeping the killing evidence.
Phrasing (this is what makes the tree readable as a "why" chain): every node — apex, every root[].title, every node text — is a declarative problem/cause STATEMENT that reads as an answer to "why" of its parent. "Ad spend is never captured", not the topic label "Cost denominator"; "We can't attribute DMs to ads", not the bucket "DM stage". Stages are an analysis scaffold for grouping evidence, not causal claims — the rendered funnel is problem → root causes → constraint and stage names become only context tags, so never rely on a stage label to carry causal meaning. Never make a "stage" for the apex / verdict / framing itself — that content IS the apex statement + verdict, not a cause bucket (a stage titled "Apex" or "framing" is a generation bug). Keep role within the controlled vocabulary; don't invent roles like "apex-answer".
Save the JSON to disk (e.g. why-tree-output.json) before visualizing, so a failed render never loses the analysis.
Phase 3 - Visualize (invoke frontend-design)
Render the tree JSON into a single self-contained HTML file using assets/tree-template.html as the scaffold. Invoke the frontend-design skill for the aesthetic pass - this is the user's explicit ask: the visualization must be distinctly designed, not the GitHub-default look of the original artifact. (frontend-design is an external Anthropic-provided skill; if it is not installed, assets/tree-template.html still renders standalone and the aesthetic pass is optional.)
Requirements the visualization must hit:
- The narrative memo rendered FIRST -
narrative[] as a styled "Read this first" block at the top (above the tree), open by default, so the artifact self-explains in prose before anyone touches the interactive tree. This is the comprehension layer.
- A prominent one-line
verdict rendered under the apex (the answer; the apex states the problem) — styled by verdictStatus. When it is map, the header itself must wear an unmistakable amber "WORKING HYPOTHESIS — map, not verdict" treatment naming the #1 deciding test; never the confident act-ready styling. The census honesty must reach the headline: a field run shipped a beautiful act-ready verdict whose constraint stood on a HYPOTHESIS node that died on the first check — the reader must not need to scroll to the census panel to learn that.
- The lever portfolio (target apex only) - render
levers[] as a sized panel (each lever's contribution, Own/Win/Buy, effort; dropped levers shown greyed with their reason, never hidden) plus the sizing bottom line ("do the levers sum to N?"). Hide the panel when levers is absent (a symptom apex).
- The "Idea on trial" panel (Idea Audit only) - render
ideaFit near the top (after the memo, before the lever portfolio — the reader brought the idea): the idea statement plus its claimedProblem and buyer (the buyer line is half the WTP argument, and the claimed problem lets the reader check the apex was extracted honestly), the verdict badge (dissolves-constraint green · relieves-symptom amber · misses-constraint / negative-branch red), the nodes it addresses — with "includes the constraint" computed from the constraint chain, never asserted from the verdict enum — the policy-tool mismatch note, the absorbed-pain line with its kind/grade chip and its test, the segment fork (with its gap), the redirect, and the refutation state: contested (both sides visible), survived, or skipped — a fit that was never attacked must say so. Hide the panel when ideaFit is absent; when the JSON carries ideaFitDeferred or ideaFitError, render that where the panel would be — the user's question must never silently vanish. The badge obeys the same census honesty as the header: a fit verdict resting on HYPOTHESIS/CLAIM or raw/contested nodes wears the "(verify first)" treatment, never act-ready styling.
Keep assets/tree-template.html as the reusable scaffold (data swapped via the inline <script id="tree-data"> JSON block); write each run to its own output file. When splicing JSON into the block, escape every </ as <\/ (JSON-legal, HTML-identical) — a literal </script> inside any node text otherwise terminates the data block early and silently kills the whole artifact. To update a run's data later, replace ONLY the tree-data block inside the previously RENDERED, styled file — never regenerate from the bare template after the frontend-design pass (a field run lost the whole aesthetic layer that way: the rebuild silently shipped the undesigned scaffold, 58k → 51k bytes with the design gone).
Phase 4 - Verify (the CLR audit, non-negotiable)
Before showing anyone, audit the tree (Goldratt's "Categories of Legitimate Reservation"):
- Contradiction check - does any branch contradict another? Resolve or surface the tension explicitly.
- One-constraint check - is exactly ONE system constraint named? If five things are all "critical," convergence failed - send it back.
- Causality vs correlation - for each MEASURED->cause arrow, is the cause sufficient, or is there a hidden third factor? Mark INFERENCE honestly.
- Evidence-honesty census - compute the answer-kind mix. If the constraint-locating nodes are HYPOTHESIS, the headline must be "where to look," and the cheapest-test must target exactly those nodes.
- Refutation survived - every load-bearing branch must show it faced (and survived) the adversarial pass.
- Multi-level check - the constraint root must carry a non-empty nested
children[] chain down to bedrock. A childless constraint root is the flat-funnel bug — send it back to the drill step.
- Measurable-in-hand check (fail loud). Every HYPOTHESIS/CLAIM node must carry a
gap tag (in-hand / external / experiment). An in-hand node is a hard error — one query over data already pulled settles it, so the workflow's deepen guard warns loudly and the node must be computed and re-graded MEASURED before shipping. Only external/experiment gaps are legitimate, and they become the Data Request — never ship an in-hand gap as a "cheapest test" or a data-request line.
- Measurement-validity check — every load-bearing MEASURED node names its source-registry id and a
validation state. raw at the decision point means the measurement audit was skipped or capped past it — send it back. contested can never support the constraint, and its reconciliation must appear in tests[]/dataRequest[].
- Trend check — any Δ-over-time claim graded above INFERENCE must cite its YoY comparison or seasonal normalization (the Δ-over-time rule in
answer-kinds.md).
- Headline-matches-census check —
verdictStatus must be map whenever the constraint's loadBearing node is HYPOTHESIS/CLAIM or MEASURED-raw/contested, and the HTML header must visibly say so. A confident header on a map-status tree is the "beauty outruns reliability" bug — send it back to Phase 3.
Phase 5 - Output
Deliver two things:
- The interactive tree (the HTML).
- A one-page decision doc (markdown + matching HTML if the user reviews in HTML per their convention): Constraint located -> What to do -> What NOT to do (the negative branches) -> The single cheapest test that would fork-decide -> What I need from you (the Data Request: the ranked missing evidence that would upgrade the map to a verdict). The tree is the diagnosis; the doc is the "so what." For a target apex, lead the doc with the lever portfolio — a lever × contribution × Own/Win/Buy × effort table + the
sizing "do they sum to N?" line — then the binding constraint; the reader needs the paths-to-the-number before the bottleneck inside them. For an Idea Audit, lead with the idea on trial: verdict → why (the nodes it rests on) → the WTP test → where it might live (the segment fork) → what to build instead (the redirect) — then the constraint story. The reader brought an idea; answer the idea first, with the tree as the evidence.
State the headline honestly: if the system constraint is located but the funnel/mechanism constraint is not, say both - "the policy constraint is settled and needs no more data; the mechanism constraint is unlocated and one query would pin it."
Phase 6 - The test loop (update, don't re-derive)
The tree's life doesn't end at delivery: the user runs the cheapest tests / fills the Data Request and comes back. A field run did this loop four times by hand — formalize it. On "here are the test results" (or why-tree update):
- Load the saved
why-tree-output.json — this is the one case where reading the prior tree is correct. The Phase-1 anti-contamination rule forbids reading a prior verdict when RE-DERIVING a tree from scratch; amending a live tree with new empirics is the opposite operation and reads it by design.
- Re-grade only the touched nodes — a test result upgrades HYPOTHESIS→MEASURED (with the new cite +
validation), sets contested if it disagrees with an existing node, or kills a node: role REFUTED with the killing evidence kept visible, exactly like the adversarial pass.
- Re-converge ONLY if a load-bearing node fell — if the constraint's
loadBearing node died or went contested, re-run the converge+drill step over the updated branches (2-3 agents); otherwise zero agents — just recompute the census and verdictStatus in plain code.
3b. Orphan sweep (plain code, zero agents). When any node dies or goes contested, sweep every root action, negative, and ideaFit claim whose restsOn includes it: flag each as ORPHANED in the tree and the decision doc — "this recommendation rested on a node that just fell; re-derive or retract". Never leave a recommendation (or an idea verdict) standing on a dead node. The sweep's output fields (the renderer's contract): roots[].actionOrphaned: true · negatives[].orphaned: true + orphanedBy: '<dead node id>' · ideaFit.orphaned: true + ideaFit.orphanedBy: '<dead node id>'.
- Re-render by splicing the updated JSON into the existing styled HTML's
tree-data block (the Phase-3 rule — never rebuild from the bare template), and update the decision doc's headline.
The post-hoc idea-check (same machinery, new question). On "here's my idea — would it have helped?" / why-tree idea-check <idea> against a finished tree: load the saved JSON, run the Phase-2 step-6c fit-check (+2 agents) over the existing tree, splice idea + ideaFit into the styled HTML, and append the idea-on-trial section to the decision doc. Zero re-derivation — and this is how the mode was field-discovered: the user asked the idea question only after the diagnosis was done.
Each loop costs 0-3 agents. The point: the tree stays the living map of the diagnosis — grading the empirics as they land — instead of a snapshot that drifts from reality while the human debugs it elsewhere.
Guardrails
- Token honesty first - never launch Deep without an explicit cost warning and confirmation. The gate is the skill's conscience.
- One constraint, not a list - refuse to ship five co-equal roots. Force convergence to one.
- Grade every node - no ungraded assertions; every HYPOTHESIS must name the test that would settle it.
- Refute before trust - load-bearing branches must survive an adversarial pass, and the dead branches stay visible.
- Honest census - when the decisive nodes are unmeasured, say "map, not verdict." Confident verdicts on HYPOTHESIS nodes are the worst output.
- Don't smuggle the answer into the apex - a problem framed as a missing solution biases the whole tree.
- Interaction at the edges, fail loud in the middle - the user may be asked things ONLY at the edges: the Phase-0 depth gate, the Phase-1 pre-flight data gate (+ "interview me" intake), the Phase-1.5 scout-gate routing (ship-direct vs escalate-with-receipts), and the Phase-5/6 Data Request / test-results loop. Never mid-swarm. During the run, never invent and never punt: an
in-hand gap must be computed (the deepen guard fails loud if not), and only external/experiment gaps become the Data Request — the honest "here's exactly what I'd need from you" output.
- Levers are parallel paths, not rival causes - on a target apex, the "converge to ONE" discipline applies to root causes, not to growth levers. Never refute a lever away; a weak lever is
dropped with a stated droppedReason and stays visible. A target apex shipped as a lone bottleneck with no sized portfolio is the wrong output shape.
- A number is not a fact - MEASURED says a number exists;
validation says it means what the node claims. Unvalidated (raw) caps at Mod; the constraint may never rest on a raw or contested node; two sources disagreeing in sign is a CONTESTED node with both values shown, never a "fact". "Can I compute it?" and "is the pipeline clean?" are different questions.
- The headline may not outrun the census - when the decisive node is unmeasured or unvalidated,
verdictStatus:'map' must be visible in the header itself (amber, naming the deciding test), not only in the census panel at the bottom.
- Consensus is not clear-cut - the scout gate ships a direct answer only on convergence + MEASURED-validated decisive evidence + surviving a refutation attempt. Three independent minds converging on the intuitive story is how the confidently-wrong answer ships with extra confidence; votes never gate alone.
Anti-patterns
- A single-thread 5-Whys chain with a tidy bottom (no branching, no refutation = not a tree).
- Nodes asserted without an answer-kind or citation.
- "Five key root causes" with no convergence to one constraint.
- A confident recommendation resting on HYPOTHESIS-graded nodes, with no census disclosing it.
- Deleting refuted branches instead of keeping them with their killing evidence.
- Launching the deep workflow without telling the user it's token-heavy.
- Pausing the swarm to ask the user - mid-run questions can't be answered; tag the node
gap:external and route it to the Data Request instead.
- Shipping an
in-hand gap as a "cheapest test" or data-request line - if one query over data you already pulled settles it, compute it; don't outsource your own homework to the reader.
- Running the full workflow on a clear-cut problem a single agent would nail - the ablation shows that's wasted tokens; answer it directly and skip the gate.
- A flat apex → roots → constraint funnel with childless roots - the constraint branch must be a visible multi-level chain to bedrock, or it's not a tree.
- An uncapped fan-out (no
MAX_DEEPEN/MAX_REFUTE) - it balloons agent count and rate-limit-degrades the refute pass.
- A GitHub-default-looking tree - the visualization is a deliverable; run it through
frontend-design.
- Running a growth-TARGET apex as a pure constraint tree - it hands back one bottleneck and silently drops the parallel levers; a "hit N" apex needs the sized lever portfolio (+ "do they sum to N?"), not just the binding step.
- A tree with no narrative - the HTML must open with the
narrative[] memo; a raw interactive tree with no prose entry point fails the comprehension test.
- A MEASURED chip on an unaudited pipeline - bots in the denominator, a metric-definition mismatch, or a seasonal Δ shipped as a "fact". The field failure that cost 4 of 6 iterations: the tree confidently leads the wrong way until a human debunks its own "facts".
- Two sources disagreeing and the convenient one shipping as MEASURED - a sign-level divergence (−27% vs +12%) is a CONTESTED node and a finding, never a fact to build on.
- An act-ready verdict header on a
map-status tree - the census honesty must reach the headline, not hide in the bottom panel.
- Regenerating the HTML from the bare template after the design pass - splice the block into the styled file instead; the rebuild silently drops the aesthetic layer.
References & assets
references/methodology.md - Goldratt CRT, the WHY-branch logic, CLR audit, constraint location, Evaporating Cloud, negative branches.
references/answer-kinds.md - the evidence taxonomy + confidence grading rubric + citation rules (the core of the rigor).
references/workflow-template.md - the copy-paste Workflow() blueprint and the tree-JSON schema.
assets/tree-template.html - the reusable interactive-visualization scaffold.
assets/sample-tree.html - a non-confidential worked example.