# Shipped wordlist provenance — ENABLE1

The third-party-code-legal pattern (`docs/2026-08-08-third-party-code-legal.md`)
applied to DATA. This site's entire product is a dictionary lookup, so the
dictionary's identity, licence and exact bytes are the thing to pin — the same
argument that makes `../../d3-private-converters/vendor/*/PROVENANCE.md` exist
for three vendored decoders.

## The file

- **File:** `enable1.txt` — the ENABLE1 word list, one lowercase word per line,
  LF endings, one trailing newline.
- **Edition:** **172,820 words.** Every entry matches `/^[a-z]+$/` — no capitals,
  no hyphens, no apostrophes, no diacritics. Both facts are asserted by
  `tools/wordsieve-index.js` (`readWordlist`) and by `tests/structure-d9.js`, so
  a substituted or silently-edited list fails the build rather than producing a
  plausible-looking index over a different dictionary.
- **SHA-256 (as shipped):**
  `7979be70952cc5d293589ab0785c8620c6fcd6b9a3fe855ab00d112b6f14529f`
  — 1,743,049 bytes. Pinned in `tests/structure-d9.js`.

## Where it came from, and exactly what was done to it

- **Fetched 2026-08-16** from Peter Norvig's word-list archive,
  <https://norvig.com/ngrams/enable1.txt> (redirects to
  `https://www.norvig.com/ngrams/enable1.txt`), which the index page at
  <https://norvig.com/ngrams/> lists as "enable1.txt — The ENABLE word list
  (172,819 words)". That page's count is a line count of a file with no trailing
  newline; the file holds 172,820 words.
- **Upstream SHA-256:**
  `61ba1392a5b6199dd161fae7b483cd262fb8a88c0d49bd2c9ecb6753e755697f`
  — 1,743,327 bytes.
- **The one modification: a single trailing `\n` was appended.** Nothing else.
  That is verifiable in one command, and it is why the two hashes above differ:

      curl -sSL https://norvig.com/ngrams/enable1.txt | sha256sum
      # matches the UPSTREAM hash recorded above

  The shipped file is that list with the exclusions applied and one newline
  appended. To reproduce it, and to check that nothing beyond the exclusion list
  changed, re-merge the removed terms into the shipped file and hash the result:
  it must equal the upstream hash. `tests/structure-d9.js` runs exactly that
  check on every build.

  The newline is required by `tools/wordsieve-index.js`, which refuses to index
  a list without one rather than silently dropping or keeping a ragged last
  entry.
- **No words were added, removed, reordered or re-cased.** The shipped
  dictionary is somebody else's editorial work and this repo does not curate it;
  if a word looks wrong, that is a fact about ENABLE1, and
  `/word-unscrambler/` says so on the page instead of quietly patching the list.

## Mirrors disagree, so the count is pinned rather than described

`enable1.txt` circulates in variants and a count alone does not identify an
edition. Measured 2026-08-16, same day, same machine:

| Source | Words | Difference from the shipped file |
|---|---:|---|
| norvig.com/ngrams/enable1.txt | 172,820 | — (this is the shipped file) |
| github.com/dolph/dictionary `enable1.txt` | 172,823 | adds `knickknack`, `razzmatazz`, `razzmatazzes` |

That is why the SHA-256 above, not the name "ENABLE1", is what
`tests/structure-d9.js` asserts.

## Licence — public domain

ENABLE (**E**nhanced **N**orth **A**merican **B**enchmark **LE**xicon) was
researched and compiled by **M. Leo Cooper** and **Alan Beale** and released
into the public domain. The citable primary statement is Cooper's own YAWL
package (YAWL is a superset of ENABLE), retrieved 2026-08-16 from
<https://github.com/elasticdog/yawl> (`yawl-0.3.2.03.tar.gz`):

**The evidence is now shipped next to the list it licenses:** `YAWL-README.txt` in this directory, retrieved 2026-08-22 and sha256-pinned in `tests/structure-d9.js`. The hash lives in the test, not in this sentence — this file records exactly one SHA-256, the upstream edition's, and the suite asserts that; a hash restated in prose is a value that drifts from the thing it describes. Until then this page cited a document no reader could open and no test could notice changing. The suite asserts both load-bearing sentences — *"herewith and forever placed in the Public Domain"* and *"ENABLE, YAWL, and 2DICTS are not trademarks"* — so a re-pin of a rewritten upstream cannot silently drop them.

> Care has been taken to ensure that the YAWL word list (word.list) will
> for all time remain copyright free. It is based on the updated Public
> Domain ENABLE (Enhanced North American Benchmark Lexicon), researched and
> compiled by the author and his colleague, Alan Beale.
>
> — `yawl-0.3.2.03/README`

and, from the same package's `LICENSE`:

> The author decided to release the list into the Public Domain because
> it is based primarily on other Public Domain lists by the author and
> his colleague, Alan Beale [...] Note that "Public Domain" *means* Public
> Domain. Even if portions or the whole of this package are incorporated
> into a commercial or proprietary application, those portions of YAWL
> within it *remain* Public Domain.

The same README states, in its own words: **"ENABLE, YAWL, and 2DICTS are not
trademarks."** So there is no attribution obligation and no mark to respect —
credit is given on `/methodology/` because naming your dictionary is what makes
a word site checkable, not because a licence compels it.

## What is deliberately NOT here, permanently

The official tournament lists — **TWL/NWL** (NASPA) and **Collins** — are
proprietary compilations and **never enter this repository**, in any form,
including as a diff against ENABLE1. Thesis Gate 3
(`docs/2026-08-16-wordsieve-thesis.md`) makes that permanent, not a stage-1
simplification. A word site that shipped a tournament list would be
redistributing somebody's licensed database; ENABLE1 exists precisely so that
nobody has to.

Two consequences the site states on-page rather than hiding:

1. ENABLE1 is **a general English word list, not the word list of any
   particular game**. Results will differ from any specific game's judge.
2. Mirror text that describes ENABLE1 in terms of a branded dictionary or a
   named game is **not repeated anywhere in `sites/`** — the honest description
   is "a public-domain English word list", and the trademark discipline in the
   thesis's Gate 3 governs every sentence that mentions a game by name.

## Derived files in this directory

`shard-02.txt` … `shard-15.txt` are **generated, never hand-edited**. Producer:
`node tools/wordsieve-index.js`; verify with `--check` (byte-for-byte against
disk) and `--verify` (drives the shipped `sieve.js` in jsdom against an
independent brute-force scan of this file). `tests/structure-d9.js` re-runs the
producer and pins the output, so a hand-edited shard fails the build.

## To update the edition

Replace `enable1.txt`, update **both** hashes and the word count above and in
`tests/structure-d9.js`, re-run `node tools/wordsieve-index.js --verify`, and
update the counts quoted in `/word-unscrambler/` and `/methodology/` — those are
recomputed against this file by `tests/structure-d9.js`, so a stale number on
the page fails the build rather than misinforming a visitor.


## Exclusions (2026-08-24)

The shipped file is the upstream ENABLE1 list **minus 39 entries**: a short list
of sensitive terms removed before publication.

- **Upstream ENABLE1, unmodified (no trailing newline):** 172,820 words,
  SHA-256 `61ba1392a5b6199dd161fae7b483cd262fb8a88c0d49bd2c9ecb6753e755697f`.
  That is the source, recorded so the identity of the dictionary this site
  derives from stays checkable. The hash of the file shipped before this change is
  recoverable from git history and is deliberately not repeated here: this
  record pins the CURRENT pair, and a third hash would make the gate that reads
  it ambiguous.
- **Shipped:** 172,781 words, SHA-256 above (the filtered list plus one
  trailing newline).
- **CHECKED, not asserted:** `tests/structure-d9.js` re-merges the excluded
  terms into the shipped list, sorts, and requires the result to hash to the
  upstream SHA above. That turns "39 terms were removed and nothing else
  changed" from a sentence into arithmetic — a filter that quietly dropped or
  altered anything more fails the build.
- **The list itself lives in `tools/wordsieve-exclusions.txt`, which is NOT
  deployed.** Keeping it outside the site directory is the point: a filter file
  shipped alongside the thing it filters would publish exactly what it removed.
- **The exclusion is deliberately narrow.** Ordinary words that merely have an
  offensive sense are KEPT. This is a named word-game dictionary, and removing
  legitimate play words would make the site answer a different question than the
  one it claims to answer — which is the failure this whole file exists to catch.
- **Reproducible:** filter `enable1.txt` against the exclusion list, then run
  `node tools/wordsieve-index.js` to rebuild every shard. Every figure the site
  quotes is recomputed from the shipped files by `tests/structure-d9.js`.
