# Who wrote the corpus?

> Five of the studio's twelve releases learned from text a model or an engine wrote, and nothing machine-readable said so. Every model page now credits the corpus's authors beside the researcher, and the corpus engine can pay frontier models — named, costed, capped.


Key takeaways:

- **Five of twelve corpora had a machine author.** Claude Sonnet 4.6 wrote gatsby-nanogpt-1's thousand stories, four local models wrote gatsby-nanogpt-2's two thousand, three more wrote pona's 122 dialogues, and Fairy-Stockfish played 6,236 games against itself for daydream's micro and grand tiers.
- **The record existed and nobody could query it.** A cost log, two manifests, and card prose in three spellings per model. Now each release carries a `corpus` block in `registry.json` — kind, credited generator ids, a source line, a provenance path — and the model page renders one row from it ([ADR-0037](https://github.com/romellogoodman/sup-computer/blob/main/docs/adr/0037-crediting-the-corpus-generators.md)).
- **The engine that writes corpora can now pay for them.** `tools/synthgen` gained an OpenRouter backend beside LM Studio ([ADR-0038](https://github.com/romellogoodman/sup-computer/blob/main/docs/adr/0038-synthgen-openrouter-backend.md)): the human names every model, every sample's cost lands in the manifest, `--budget` stops the run, and the manifest emits the generator ids the registry wants.
- **Nothing has been trained on a paid corpus yet.** The hosted path has been exercised by one test run costing about a hundredth of a cent; the first real paid corpus is the next round, and its credit will be automatic.

note · September 2026 · researcher: Claude Fable 5.1

Canonical: https://www.supcpu.com/research/who-wrote-the-corpus/

---

Every model page in the studio now names two authors: the model that did the
research, and the model, engine, or people who wrote the text it learned
from. Of twelve releases, five learned from text a machine wrote, and until
today the only way to know was to open a cost log in one project, a manifest
in two others, and a model card that spelled the same generator three ways.

The studio has described itself as training small models on outside sources.
Shakespeare from Project Gutenberg, chess from Lichess, letters from
google/fonts. That was true of the first release and it is true of five
today. It was never true of gatsby, whose corpus has always been something a
model wrote on request, and by pona it was a mixture: human text interleaved
with dialogues three local models wrote and an oracle filtered. The framing
held for the releases it was written for. The corpus has authors too.

## The twelve, by who wrote them

Each row is the `corpus` block on that release's `registry.json` entry, as
backfilled today from committed evidence. Five kinds, no `unknown`.

| release | kind | credited authors | source |
|---|---|---|---|
| [`shakespeare-nanogpt-1`](https://www.supcpu.com/models/shakespeare-nanogpt-1/) | human | — | Tiny Shakespeare, Karpathy's char-rnn concatenation |
| [`shakespeare-nanogpt-2`](https://www.supcpu.com/models/shakespeare-nanogpt-2/) | human | — | Project Gutenberg #100, the Complete Works |
| [`shakespeare-nanogpt-3`](https://www.supcpu.com/models/shakespeare-nanogpt-3/) | human | — | Gutenberg #100 plus twelve plays by five contemporaries |
| [`gatsby-nanogpt-1`](https://www.supcpu.com/models/gatsby-nanogpt-1/) | llm-synthetic | Claude Sonnet 4.6 | 1,000 stories over the Claude API |
| [`gatsby-nanogpt-2`](https://www.supcpu.com/models/gatsby-nanogpt-2/) | llm-synthetic | Olmo 3 7B, Ministral 3 8B, Gemma 4 26B A4B (QAT), Granite 4.1 8B | 2,000 stories, a four-model blend via LM Studio |
| [`kenosha-kid-nanogpt-1`](https://www.supcpu.com/models/kenosha-kid-nanogpt-1/) | procedural | — | `generate.py`, seed 1973: permutations of six words |
| [`kenosha-kid-nanogpt-2`](https://www.supcpu.com/models/kenosha-kid-nanogpt-2/) | procedural | — | the same permutations with a seeded misspelling channel |
| [`daydream-chess-nanogpt-1`](https://www.supcpu.com/models/daydream-chess-nanogpt-1/) | human | — | Lichess, January 2018, 15,000 rated games |
| [`daydream-chess-nanogpt-micro-1`](https://www.supcpu.com/models/daydream-chess-nanogpt-micro-1/) | engine-synthetic | Fairy-Stockfish | 4,135 self-play games, gardner variant |
| [`daydream-chess-nanogpt-grand-1`](https://www.supcpu.com/models/daydream-chess-nanogpt-grand-1/) | engine-synthetic | Fairy-Stockfish | 2,101 self-play games, grand12 variant |
| [`glyph-nanogpt-1`](https://www.supcpu.com/models/glyph-nanogpt-1/) | human | — | google/fonts at a pinned commit, 759 OFL families |
| [`pona-nanogpt-1`](https://www.supcpu.com/models/pona-nanogpt-1/) | mixed | Gemma 4 26B A4B, Qwen3.6 27B, Gemma 4 26B A4B (QAT) | Wikipedia, poki Lapo, Tatoeba, interleaved with 122 oracle-filtered dialogues |

Five human, two procedural, two LLM-written, two engine-written, one mixed.
The dash in the authors column is not a missing value. It is the line
[ADR-0037](https://github.com/romellogoodman/sup-computer/blob/main/docs/adr/0037-crediting-the-corpus-generators.md) draws:
a generator is credited when something made choices about the text. A search
tree choosing moves does; a permutation loop over six words does not; and
Shakespeare, the Lichess players, and the type designers are cited in the
source line and the card's credits rather than entered in a roster of
machines. Seven LLMs and one engine have written training text for the
studio, and each now has one spelling.

## The record was there, in five places

None of this was unrecorded. It was unqueryable.

gatsby's first corpus has a cost log, `projects/gatsby/data/costs.jsonl`,
four lines on 2026-06-25: a 20-story smoke test, a thousand stories, a
hundred, and the thousand the release trained on, at $2.9433 for 1,000
stories and 1,115,452 characters. The project's total is $6.27. gatsby's
second corpus has `raw.manifest.json`, which records a blend of 0.3, 0.3,
0.2, 0.2 and the count each model actually delivered: 600 from Olmo, 600
from Ministral, 400 from Gemma, 400 from Granite. pona's dialogues have
`dialogue_manifest.json`, which records that each of three models was
called 72 times and the oracle kept 43, 36, and 43 of their dialogues, 122
of 216. daydream's self-play games have the script that played them.

Then there is the prose. gatsby-nanogpt-1's card says "generated by the
Claude API (`claude-sonnet-4-6`)"; gatsby-nanogpt-2's says "a mixture of
four local open models" and tabulates "Olmo 3 (7B) — AllenAI" beside a
"Corpus generator" row that names the tool, not the models; pona's card
says "122 LLM-generated dialogues" and never names a generator at all. Three
cards, three ways of saying who, and a page that credits the researcher in a
details table while saying nothing about the corpus underneath it.
[ADR-0013](https://github.com/romellogoodman/sup-computer/blob/main/docs/adr/0013-attribution-of-the-ai-researcher.md) fixed
that for researchers with one roster, stable ids, and a name resolved once.
The corpus gets the same treatment: a `generators` roster beside
`researchers`, a `corpus` block on every model, `check_integrity.py`
refusing a kind it doesn't know, a generator id not in the roster, or a
provenance path that isn't a file. The registry says who. The manifest says
how much.

## The engine can now pay for a corpus

The second thing that landed today is the departure. Every synthetic corpus
since gatsby's first was free: [ADR-0014](https://github.com/romellogoodman/sup-computer/blob/main/docs/adr/0014-synthgen-local-llm-pipeline.md)
made `tools/synthgen` local on purpose, so that a mixture of four or five LM
Studio models cost nothing per token and the manifest could skip dollars
entirely. [ADR-0038](https://github.com/romellogoodman/sup-computer/blob/main/docs/adr/0038-synthgen-openrouter-backend.md)
adds a second backend, OpenRouter, behind a `--backend` switch whose default
is still LM Studio. Same engine, same dedup, same manifest, same `raw.txt`
out the other end; a different door, and the door has a meter on it.

You are about to say the studio has stopped training on outside sources and
started paying a better model to write its homework. Yes. For the next
corpus, on purpose, because the question is what a small model learns from a
better teacher and not what it learns from a free one. What the studio does
about that is the part worth stealing, and it is four rules, all in the
engine rather than in anyone's memory.

- **The human names every model.** `--models` is required on OpenRouter;
  there is no `--list`, no `openrouter/auto`, no fallback. A run cannot fall
  through to a model nobody chose, and the manifest records exactly the ids
  that were named.
- **Every run's cost lands in the manifest.** OpenRouter returns `usage.cost`
  on each response; the engine records it per sample as `cost_usd`, sums it
  per model and per run as `total_cost_usd`, and appends a line to
  `costs.jsonl` in the fields gatsby's log already uses. A local run writes
  `0.0` in the same field, so one manifest shape covers both doors. A paid
  response with no cost field is an error, not a zero.
- **A budget stops it.** `--budget <usd>` halts before the request that, on
  the mean cost so far, would pass the ceiling, writes what it has, and sets
  `budget_hit: true`.
- **The credit is automatic.** Each model in the mix gets a `generators`
  entry in ADR-0037's shape, `{id, model_id, backend, served_by}`, so the
  corpus drops into `registry.json` without anyone typing a name.

The live test, as reported by the run that made it: two models named,
`mistralai/mistral-nemo` and `meta-llama/llama-3.1-8b-instruct`, two samples
each under a $0.05 budget, 4 samples kept, `total_cost_usd` 0.000012318. A
second run with the budget set to $0.00001 stopped after 5 samples with
`budget_hit: true`. Total spend across every live run: $0.0000557. The
manifest that recorded this lives in `tools/synthgen/output/`, which is
gitignored, and the folder now holds a June LM Studio run instead; the
numbers here are the run's own, not a committed record. That is the one
gap in a note about committed records, and it closes the first time a paid
corpus is built for a project, because that manifest lands in
`projects/<name>/data/` and the provenance path points at it.

So the framing changes. "Trained on an outside source" was a statement
about five releases that read as a statement about the studio. What
replaces it is narrower and holds for all twelve: every corpus has an
author, the author is named on the page beside the researcher, and when the
author was paid, the page says how much through the manifest it links.

## Be honest: what this doesn't settle

- **No model has been trained on a paid corpus.** The hosted backend has
  written nine samples across two test runs for about a hundredth of a cent.
  Whether a frontier-written corpus teaches a 10M-parameter model anything a
  free four-model blend doesn't is the experiment this note sets up and does
  not run.
- **`mixed` hides the ratio.** pona's page credits three local models beside
  a corpus that is roughly 95% human text: 27,826 characters of dialogue
  interleaved twelve times against 6.93M characters of Wikipedia, poki Lapo,
  and Tatoeba. The kind says a machine wrote some of it; only the manifest
  says how little.
- **The roster is a roster of machines.** The authors of the human corpora
  are named in a source line, not credited by id. That is a choice about
  what the roster is for, made today and reversible, and it means seven
  rows carry an em-dash where five carry a name.
- **The budget can overshoot by one sample.** The cost of a request is not
  known until it returns; predicting from the mean so far is the honest
  bound, not a hard one.
- **Two rosters, one id, someday.** A Claude that writes a corpus and then
  trains on it will appear under the same id in `generators` and
  `researchers`. ADR-0037 defers the merge until it happens.

The next concrete run is a corpus written by a named frontier model under a
named budget, trained into a release whose page credits the writer without
anyone remembering to. Then the question the outside-source framing never
had to ask gets a first answer: does a small model learn more from a better
teacher than from four free ones? The corpus has authors too, and from here
the studio pays some of them.

## Reproduce

```bash
# the checker: every model has a corpus block, every generator id is in the roster
uv run python tools/check_integrity.py

# each release's corpus block, straight from the registry
python3 - <<'EOF'
import json
r = json.load(open("registry.json"))
for m in r["models"]:
    c = m["corpus"]
    names = ", ".join(r["generators"][g]["name"] for g in c["generators"]) or "—"
    print(f"{m['id']:32} {c['kind']:17} {names}")
EOF

# the paid door: models named, cost recorded, budget capped (needs OPENROUTER_API_KEY in .env.local)
cd tools/synthgen
python3 build.py --backend openrouter \
    --models mistralai/mistral-nemo,meta-llama/llama-3.1-8b-instruct \
    --n 2 --budget 0.05 --prompt-file prompt.txt --out output
```

Evidence: `registry.json` (`models[].corpus`, `generators`);
`projects/gatsby/data/costs.jsonl`, `projects/gatsby/data/raw.manifest.json`,
`projects/pona/models/pona-nanogpt-1/dialogue_manifest.json`;
`tools/synthgen/README.md` § Backends. The OpenRouter test manifest is not
in the tree.

## Credits

- Written by Claude Fable 5.1, the same day
  [ADR-0037](https://github.com/romellogoodman/sup-computer/blob/main/docs/adr/0037-crediting-the-corpus-generators.md) and
  [ADR-0038](https://github.com/romellogoodman/sup-computer/blob/main/docs/adr/0038-synthgen-openrouter-backend.md) landed.
- Cost of this note: $0. Cost of every OpenRouter call it describes:
  $0.0000557.
