Skip to content

Repository files navigation

ACH Workbench

A browser-based implementation of Analysis of Competing Hypotheses, the structured analytic technique developed by Richards J. Heuer, Jr. at CIA and taught across the U.S. intelligence community.

It ranks explanations by the evidence against them rather than the evidence for them, flags reporting that feels compelling but discriminates nothing, shows what the judgment is balanced on, and emits a finished product using ICD 203 estimative language — with probability and confidence stated as the separate things they are.

Runs entirely in the browser. No backend, no telemetry, no network calls.

The workbench with the sample case loaded


Why this exists

Most analytic errors are not arithmetic errors. They come from building a case for the first plausible explanation and then reading every subsequent report as support for it. ACH is the standard countermeasure: list the hypotheses first, rate every item of evidence against all of them, and prefer the hypothesis with the least evidence against it.

The technique is simple enough to do on paper and tedious enough that people skip the parts that matter — diagnosticity and sensitivity. Those parts are the reason this tool exists.

What it does

Refutation-based ranking. Hypotheses are ordered by weighted inconsistency, ascending. Supporting evidence is computed and displayed but never drives the ordering, so you can see when a leading hypothesis is winning by default rather than on its merits.

Weighted evidence. Each item carries a NATO Admiralty reliability grade (A–F) and an analyst-assigned relevance (1–5). A rumour and a forensic finding do not move the matrix equally.

Diagnosticity scoring. Evidence that rates identically against every hypothesis is flagged as non-diagnostic. This is Heuer's least intuitive and most useful result: an item can be true, vivid, central to the narrative, and still carry no weight in choosing between explanations. The sample case includes one deliberately.

Sensitivity analysis. For every item, the tool recomputes the ranking with that item withdrawn, and reports both whether the leader changes and how much the margin over the runner-up narrows. A judgment resting on a single uncorroborated report is identified as such.

ICD 203 output. The BLUF uses the seven-band estimative probability lexicon (almost no chancealmost certain). Confidence is assessed separately from probability, as the standard requires, and is driven by source quality, diagnosticity, matrix coverage, and how well the margin survives losing any single report.

Key Assumptions Check. Assumptions are recorded with their own confidence and an explicit "would be invalidated if" condition, which then feeds the indicators-to-watch section of the report.

Markdown export. A complete analytic product: BLUF, ranking table, evidence with diagnosticity, sensitivity, confidence with drivers, assumptions, indicators, and a stated method-and-limitations section.

The hypothesis and evidence matrix

The worked example

The bundled case — Meridian Port Authority, the Republic of Castellia, and every source in it — is entirely fictional. It is constructed so the obvious answer is the wrong one.

A ransom note was left on 41 hosts. The intuitive read is criminal ransomware. But no working payment channel ever existed, encryption spared the finance systems and targeted crane control, operators spent 31 days querying berth schedules without exfiltrating anything, and the binaries carry artifacts inconsistent with the family they impersonate. The matrix ranks criminal ransomware third of four.

That result is asserted by a test, so a change to the scoring model that breaks the lesson breaks the build:

the sample case > reaches the counter-intuitive conclusion the case is built to teach

The case also demonstrates the honest-limitations path. The tool reports moderate rather than high confidence, because withdrawing a single item — E1, the ransom note — collapses the separation between the top two hypotheses entirely.

The generated analytic product

Method

Ratings use Heuer's five-point scale — CC very consistent (+2), C consistent (+1), N neutral (0), I inconsistent (−1), II very inconsistent (−2) — plus NA, which is tracked as a gap rather than silently treated as neutral.

Each item's weight is reliability × (relevance / 3), where reliability maps A=1.0 down to E=0.3, and F ("cannot be judged") sits at 0.5.

A hypothesis's score is the weighted sum of its inconsistent ratings only. Lower is stronger. Ties break toward higher support, so a corroborated hypothesis edges out a merely un-refuted one.

Diagnosticity is the standard deviation of an item's ratings across hypotheses; zero means it discriminates nothing.

Confidence is basis × (0.35 + 0.65 × avg_reliability), where basis combines diagnostic share, matrix coverage, and the worst-case margin under single-item removal. Source quality gates the result multiplicatively rather than contributing a term — a complete, internally consistent matrix built entirely on unreliable reporting is a well-organised guess and should not score as anything else.

Limitations

The percentages are not probabilities. They are a softmax over negated inconsistency: monotonic with the ranking and useful for readability, but not derived from base rates or likelihood ratios and carrying no calibration guarantee. The ordering is the finding. For genuinely probabilistic work, use explicit Bayesian updating with stated priors.

Weights are judgments, not measurements. Reliability grades and relevance scores are analyst inputs. The tool makes those judgments explicit and auditable; it does not make them correct.

ACH reduces confirmation bias; it does not remove it. The matrix can only rank the hypotheses you entered. The hypothesis you failed to consider is the largest residual risk in any ACH product, and no amount of arithmetic inside the matrix will surface it.

Not a substitute for tradecraft. This is a calculator for a technique, and it will faithfully compute a well-formed answer from a badly framed question.

Running it

npm install
npm run dev

Then open the printed localhost URL. Everything persists to localStorage — nothing is transmitted anywhere, and the app degrades gracefully where storage is unavailable.

Build a static bundle (it runs fine from file://, so it works air-gapped):

npm run build

Run the test suite:

npm test

Regenerate the README screenshots — headless Chrome at 2× device scale, no dev server needed:

npm run build && node scripts/screenshots.mjs

Query parameters

  • ?sample=1 — load the demonstration case over whatever is in storage
  • ?report=1 — open directly to the generated product

Project layout

Path What's in it
src/scoring.ts The analytic engine — weighting, ranking, diagnosticity, sensitivity, confidence
src/report.ts Markdown product generation
src/sample.ts The fictional worked example
src/types.ts Data model, rating scale, Admiralty grades
src/scoring.test.ts 39 tests over the scoring model
scripts/screenshots.mjs Headless Chrome screenshot pipeline

Disclaimer

This is an independent educational project. It is not affiliated with, endorsed by, or derived from any government agency, and contains no non-public information. All sample data is fictional. The ICD 203 estimative lexicon and the NATO Admiralty Code are publicly published standards.

Further reading

  • Richards J. Heuer, Jr., Psychology of Intelligence Analysis (CIA Center for the Study of Intelligence, 1999) — Chapter 8 covers ACH
  • Heuer & Pherson, Structured Analytic Techniques for Intelligence Analysis
  • ODNI Intelligence Community Directive 203, Analytic Standards

License

MIT — see LICENSE.

About

Analysis of Competing Hypotheses workbench — refutation-based hypothesis ranking, diagnosticity and sensitivity analysis, and ICD 203 estimative language. Runs entirely offline.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages