Chemenu 2.1.0 - deterministischer Wissenskompiler
CI / verify (push) Failing after 32s
Release / release (push) Successful in 38s

Chemenu kompiliert Rohnotizen zu einem verlinkten, quellengebundenen Wiki:
raw/ -> types/ + tools/ -> kb/ -> reports/. Was mechanisch ist, macht
tools/wikitool; was Urteil braucht, macht ein Agent unter Contracts, deren
Grenzen in Code durchgesetzt sind statt im Prompt.

Dieser Commit ist der Startpunkt der oeffentlichen Historie. Die vorherige
Entwicklung fand in einer privaten Instanz statt und ist nicht Teil dieses
Repositorys; ihre Erzaehlung steht vollstaendig in CHANGES.md, das mit 44
Eintraegen von 0.1.0 bis 2.1.0 erhalten geblieben ist.

Der mitgelieferte Korpus ist ein Testbett und eine Demo: 170 Seiten ueber den
Stack selbst - Gates, Lint, Versionierung, Suche, das Wiki-Muster. Er
dokumentiert das Werkzeug mit den eigenen Mitteln des Werkzeugs.

Lizenz: AGPL-3.0 fuer den Stack (tools/, types/), CC-BY-4.0 fuer die Inhalte.
Die Grenze zwischen beiden ist der Dateiplan, den dist export berechnet -
siehe NOTICE.
This commit is contained in:
2026-09-01 16:24:34 +02:00
commit 18ae28f918
368 changed files with 50628 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
---
type: types/instruction.md
name: migrate-corpus
description: Change the shape of every kb/ page at once - a schema field, a vocabulary, a language - in planned units, with a mechanical check per unit and a recorded KB version at the end.
---
# Migrate the corpus
A change that touches the *shape* of pages rather than their content: a new required
frontmatter field, a renamed enum value, a section heading vocabulary, a language. It is not an
ingest and not a lint fix - nothing new is learned, the same knowledge is restated in a new
form. The failure mode is therefore specific and quiet: **something present before is missing
afterwards**, and the corpus is still internally consistent, so `lint` reports nothing.
Every rule below was paid for once already. The German translation of 248 pages found four
defects this way - a dropped citation that silently unsourced a claim, a dropped wikilink, an
invented one, and a translated H1 - and three of the four had unchanged link *sets* and only
changed counts.
## When to run
A change that would otherwise be applied to more than a handful of pages by hand, or any change
declared by a migration document under `instructions/migrations/`. A single page is
`wiki-manage`; a raw tree is [ingest-large-tree.md](ingest-large-tree.md).
## Steps
1. **Open a workshop.** `tools/wikitool work new --key <slug>` - not `ingest-`, which is
reserved for keys derived from a `raw/` path. `plan.md` cuts the corpus into units and says
why each cut falls where it does; `README.md` carries the closing condition and the
decisions made so far. See [work/CONTRACT.md](../work/CONTRACT.md).
2. **Size the units by the iteration budget, not by feel.** One unit costs roughly
`N × touch` + `index rebuild` + `log append` + `publish` (twice - the Mass-Update Gate
refuses once and publishes on the confirm), plus `sources rebuild-index` if it contains
source pages. Against the 60-call ceiling that puts the ceiling near 55 pages; aim for 48 or
fewer.
**Units and publishes are not the same boundary.** The budget is per session id; the gate is
per publish. Several units may run back to back, each with its own
`WIKITOOL_SESSION_ID="<slug>/u<N>"`, and publish once together - which is what the written
unit boundaries in `plan.md` make legitimate rather than a way around a gate refusal (see
[gates.md](gates.md)).
3. **Rewrite the unit's pages.** Bodies only. Frontmatter is written with `touch`, never by
hand, and never by a subagent.
4. **Check mechanically, before anything else:**
```bash
tools/wikitool migrate verify --from HEAD --path kb/<area> --fail-on-error
```
This is the step the whole procedure exists for. It compares wikilink and citation
**counts**, footnote definitions, H1 and structural frontmatter against the last commit.
Run it before the summaries, before `lint`, before anything - it is the cheapest place to
catch a subagent that helpfully translated a link target.
5. **Write the summaries yourself** with `touch --summary`, from the original. Never paste a
subagent's proposal unread: they embellish, and a summary is a claim about the page.
6. **`index rebuild`, then `lint` - and read the whole report**, not only the sections this
unit could plausibly have touched. The translation's first unit had a frontmatter
round-trip bug that surfaced as a schema error on a field nobody had edited.
7. **`log append`, then publish** through [publish-cycle.md](publish-cycle.md). Expect exit 42
on a corpus-sized change; reproduce the breakdown for the user and wait.
8. **Carry the vocabulary between units.** Terminology settled in unit 5 and re-decided in unit
9 is the failure a glossary file in the workshop exists to prevent. Add to it *before*
dispatching the next unit.
9. **Record the migration** once the last unit is published:
```bash
tools/wikitool migrate done <version> --pages <N>
```
This advances `kb_version` in `.wikitool-kb.json`. It refuses any version that is not the
next link in the chain, so a multi-step upgrade cannot silently skip one.
10. **Close the workshop** per [work/CONTRACT.md](../work/CONTRACT.md), after promoting whatever
outlives the run. The translation's glossary became
[german-terminology.md](german-terminology.md); its checklist and unit plan died with the
directory, correctly.
## Decision points
- **Can the change be made backwards-compatible instead?** Prefer it. A vocabulary migration
does not need a flag day: `tools/chemenu/sections.py` gives each heading one canonical name
and any number of aliases, so a page is found under the old name and takes the new one only
when it is rewritten. Removing an alias afterwards is a second breaking change, not a cleanup.
- **Mechanical or assisted?** A rename with a fixed rule is `mechanical` and wants a script; a
change needing a judgment call per page is `assisted` and wants this procedure. There is no
`migrate run` today - `migration_kind` describes the work, it does not perform it.
- **The check finds something mid-unit.** Fix it in that unit and re-run `verify`. Never carry
a finding into the next unit "to fix later": the next unit's diff baseline is this unit's
commit, so an uncorrected drop becomes invisible.
- **Contradiction with an existing page.** Never overwrite. Record both, ask the user, and pull
the confidence down with `touch --confidence-base` if it stays unresolved.
## Writing the migration document
A migration that a distributed instance must also run is a `manual: true` instruction under
`instructions/migrations/<version>-<slug>.md`, carrying `migrates_to:` and `migration_kind:`.
`tools/wikitool migrate status` builds the outstanding chain from those files, and `version
bump` refuses a compatibility-breaking release that has none.
Write it for a reader who has the new machinery and the old content, and who is not you: what
changed, which pages are affected, how to tell a migrated page from an unmigrated one, and what
`migrate verify` should report when it is done.
**Baseline: 1.0.0.** Migrations that predate it - the type-system move, the `confidence_base`
backfill, the German section headings, the translation itself - have no documents and will not
get any. An instance older than that is re-exported, not migrated.
## Scope
For `kb/` content. A single page is `wiki-manage`; a `raw/` tree is
[ingest-large-tree.md](ingest-large-tree.md). Changing the machinery that *causes* a migration
is a different job with its own rules, and in a distributed instance it is not done at all -
the stack is developed in the origin repo.