Files
chemenu/INSTALL.md
T
torben 7bc5da6e0d
CI / verify (push) Successful in 48s
docs: INSTALL.md nennt die Anwendungsgebiet-Frage aus dem Setup (Nachzug zu #68)
Files changed:
- INSTALL.md
2026-09-09 07:51:17 +02:00

358 lines
21 KiB
Markdown

# Installation
Dieses Dokument richtet sich an Menschen. Es gibt vier Wege: ein **Release herunterladen**
(der normale Weg zu einer neuen Instanz), eine Distribution **selbst exportieren**, **dieses
Repo klonen** (Testbett und Demo, samt Beispielkorpus), oder eine **private Instanz mit diesem
Repo als Upstream** aufsetzen. Der agent-seitige Ablauf steckt in `instructions/`; hier stehen
nur die menschlichen Teile - für die vollständige Kommandoreferenz siehe
[tools/CONTRACT.md](tools/CONTRACT.md).
Den optionalen **MCP-Leseserver** installiert und betreibt
[INSTALL-MCP.md](INSTALL-MCP.md): derselbe Korpus, lesend, für einen Konsumenten, der kein
Terminal auf dieser Maschine ist.
## Voraussetzungen
- Python 3.11 oder neuer
- git
- [ripgrep](https://github.com/BurntSushi/ripgrep) (`rg`) - wird von `search` und
`sources coverage` gebraucht
## Weg A: Release herunterladen
Der kürzeste Weg zu einer eigenen Instanz - kein Checkout dieses Repos nötig. Jedes Release
trägt genau einen `dist export`-Baum plus eine Prüfsumme. Das Repo ist öffentlich, der Download
braucht also weder Konto noch Token:
```bash
BASE=https://gitea.nehmer.net/torben/chemenu/releases/download/v<version>
curl -LO $BASE/chemenu-stack-<version>.tar.gz
curl -LO $BASE/chemenu-stack-<version>.tar.gz.sha256
sha256sum -c chemenu-stack-<version>.tar.gz.sha256
tar xzf chemenu-stack-<version>.tar.gz
cd chemenu-stack-<version>
```
Die Prüfsumme ist nicht Zierde: Sie ist das Einzige, was einen unterbrochenen Download von
einem vollständigen unterscheidet, und `sha256sum -c` muss `OK` sagen, bevor irgendetwas
entpackt wird.
Danach weiter mit Schritt 2 aus Weg B: den Agenten
[instructions/setup-instance.md](instructions/setup-instance.md) ausführen lassen. Der
entpackte Baum ist bereits eine Distribution - Schritt 1 (`dist export`) entfällt.
Die Liste der Releases: <https://gitea.nehmer.net/torben/chemenu/releases>.
## Weg B: Neue, leere Instanz selbst exportieren
Dasselbe Ergebnis aus einem Checkout dieses Repos - für einen Stand, der noch kein Release hat.
Zwei Schritte, von denen nur der erste rein menschlich ist:
1. **Zielverzeichnis wählen** und die Distribution dorthin exportieren, aus einem Checkout
dieses Repos:
```bash
tools/wikitool dist export /pfad/zur/neuen/instanz
```
Das Ziel muss leer sein oder noch nicht existieren. `dist export` kopiert die Maschinerie
(Werkzeuge, Typen, Instruktionen, die Collection-Contracts) ohne Wiki-Inhalt, ohne
Git-Historie und ohne `instructions/dev/` (Stack-Entwicklung selbst, inkl. der vendorten
`commonplace/`-Wissensbasis) - dauerhaft, ohne Restore-Weg.
2. **Den Agenten dort arbeiten lassen.** Öffne das Zielverzeichnis in deinem Agent-Harness
(Claude Code, GitHub Copilot, Codex CLI, Mistral Vibe) und lass es
`instructions/setup-instance.md` ausführen. Diese Anweisung fragt dich dabei explizit nach:
- **Autor-Identität** (Name + E-Mail für `git config`) - wird nie geraten oder aus einem
anderen Repo übernommen, und ist zugleich der Autorname jeder künftig angelegten
Wiki-Seite (`$WIKI_AUTHOR` überschreibt dies bei Bedarf).
- **Remote** (optional) - eine URL, wenn du das Repo auf einen Server pushen willst; sonst
bleibt die Instanz lokal, und jedes `publish` läuft mit `--no-push`.
- **Autorenkonventionen** - Sprache, Abschnittsnamen, Namensformen, Ton, Beziehungslabels
und Confidence-Rubrik stehen in `kb/CONVENTIONS.md`, dazu je Collection die Regeln in
`kb/<name>/COLLECTION.md`. Die Distribution bringt davon nur die `.template`-Dateien mit:
das sind Entscheidungen *dieser* Instanz, keine Eigenschaft des Musters, und nichts davon
liegt unter `tools/` oder `types/`. Fertige Profile - darunter ein vollständiges deutsches -
hält `instructions/kb-profiles.md` bereit; es ist eine Palette, kein Enum. Sag die Sprache
**vor dem ersten Ingest** - danach ist ein Wechsel der Abschnittsnamen eine Migration jeder
bereits angelegten Seite.
- **Anwendungsgebiet** - woraus dieses Wiki seine Quellen zieht. Daraus schlägt der Agent
eine `source_type`-Liste vor (bei einem Verein etwa Satzung, Protokoll, Spielbericht statt
Transkript, Analyse, Artikel) und setzt sie in `types/source.schema.yaml` und
`types/source.md` ein. Das ist ein **Startpunkt, keine Festlegung**: zu diesem Zeitpunkt hat
die Instanz null Quellen, die Taxonomie ist also geraten, bevor jemand Material gesehen hat.
Sie wird später an echtem Bestand korrigiert - `instructions/evolve-subtypes.md` beschreibt,
wie ein Wert dazukommt und wie das Auffangfach `unclassified` wieder leer wird. Nicht zur
Wahl stehen `fidelity` und `authority`: die beiden sind Stack-Vokabular und in jeder Domäne
dieselben.
- **Personalization** - wer diese Instanz bedient (`USER.md`) und wie sie klingt
(`SOUL.md`). Die Distribution bringt nur `USER.md.template` und `SOUL.md.template` mit:
persönlicher Inhalt gehört nicht in jede exportierte Kopie, aber beide Dateien werden in
jeder Session gelesen, sind also Betriebsvoraussetzung. Der Agent interviewt dich entlang
der Template-Abschnitte und schreibt deine Antworten **wörtlich** mit - inklusive der
beiden Fragen, die er nicht raten darf: der **Persona-Name** und die **Themen, die
bewusst draußen bleiben**.
Danach ist die Instanz initialisiert, verifiziert und committet.
Was von der Sprachwahl unberührt bleibt: die Trennung zwischen Prosa und Identifiern.
Seitentitel, Wikilink-Ziele, Zitat-IDs, Schema-Werte, Tags, Befehle und Pfade folgen keiner
KB-Sprache, sondern dem etablierten Namen der Sache - `Act Runner` heißt in jeder Instanz
`Act Runner`.
## Weg C: Dieses Repo klonen
Für die Arbeit am Stack selbst, oder um sich den mitgelieferten Korpus als begehbares Beispiel
anzusehen. Was hier liegt, ist ein **Testbett und eine Demo**, keine produktive Wissensbasis:
rund 170 Seiten, die den Stack selbst dokumentieren - Gates, Lint, Versionierung, Suche, das
Wiki-Muster. Wer eigenes Wissen sammeln will, nimmt Weg A oder B und fängt mit einem leeren
`kb/` an.
```bash
git clone https://gitea.nehmer.net/torben/chemenu.git
cd chemenu
```
Danach den Agenten `instructions/bootstrap.md` ausführen lassen (Werkzeugumgebung + Skills
publizieren). Git-Repo, Autor-Identität und Inhalt existieren hier bereits.
Ein Clone, der älter ist als die Personalization-Dateien, hat kein `USER.md`/`SOUL.md` -
`doctor` meldet dafür `personalization: FAIL`. Das ist einmalig nachzuholen: nur **Schritt 6
(Personalization)** aus `instructions/setup-instance.md`, nicht der ganze Ablauf. `bootstrap.md`
verweist an derselben Stelle darauf.
`ENVIRONMENT.md` fehlt nach einem Clone immer - die Datei ist gitignored, weil sie *einen
Checkout* beschreibt und nicht das Repo. Sie ist optional; wer sie anlegt, spart jeder
folgenden Session die Fragen nach Harness, MCP-Servern und Remote. Vorlage:
`ENVIRONMENT.md.template`, Ablauf: Schritt 5 in `instructions/bootstrap.md`.
## Weg D: Private Instanz mit diesem Repo als Upstream
Die Kombination aus A und C: eine eigene, nicht öffentliche Instanz, die weiterhin
Stack-Updates von hier zieht - per `git merge` statt per Tarball, also mit echtem
Drei-Wege-Merge statt `cp -r`.
Das ist der Weg mit dem höchsten Einsatz, weil ein Checkout dann zwei Remotes hat und git beim
Push nicht unterscheidet, welcher welcher ist. Ein falsches `--remote` legt privaten Inhalt auf
ein öffentliches Repo, und ein Force-Push holt das nicht zurück - die Objekte bleiben per SHA
abrufbar, bis auf dem Server die Reflogs verfallen.
Dagegen gibt es das **Publish-Remote-Gate**, und die Anleitung setzt es an die Stelle, an der
es wirkt: *vor* dem ersten `publish`. Vollständiges Vorgehen:
[instructions/private-instance.md](instructions/private-instance.md).
## Version und Updates
Jede Instanz trägt die Version des **Stacks** (Werkzeuge, Typen, Instruktionen, Contracts) -
nicht die ihres Inhalts. Sie steht in `VERSION`, und eine per Release oder `dist export`
erzeugte Instanz trägt zusätzlich `.wikitool-release.json` mit Herkunft und Exportdatum.
```bash
tools/wikitool version # was läuft hier, und woher kommt es
tools/wikitool version check # gibt es ein neueres Release?
```
`version check` ist der einzige Befehl, der ins Netz geht. Er fragt den Release-Feed der
Ursprungs-Instanz (`$WIKITOOL_UPDATE_URL` überschreibt; sonst der Wert aus dem Stamp). Ein
nicht erreichbarer Feed wird als Fehler gemeldet - **nie** als „aktuell".
**Was die Versionsnummer aussagt:** kompatibel ist, was in der *linkesten von Null
verschiedenen Stelle* übereinstimmt. `0.1.3 → 0.1.4` ist ein sicheres Update, `0.1.3 → 0.2.0`
nicht, und ab `1.0.0` liest sich dieselbe Regel als das gewohnte „MAJOR bricht". `version check`
sagt das direkt (`state: update` vs. `state: migration`).
Was diese Stelle beantwortet, ist **ob die neue Version ein Drop-in-Ersatz ist** - ob sich die
Maschinerie einfach darüberkopieren lässt und ob die alte danach noch zurückkann. Ob *Inhalt*
migriert werden muss, ist eine **zweite, unabhängige Frage**. Ein MAJOR-Sprung kann eine leere
Migrationskette haben und trotzdem Handarbeit verlangen: umbenannter Release-Feed, umbenanntes
Artefakt, umbenannter Import- oder Kommandoname, geänderte Envvar - `kb/` bleibt dabei
unangetastet, das Update ist trotzdem keins zum Drüberkopieren. Der Abschnitt „Sonderfall:
Update von 1.x auf 2.0.0" unten ist genau dieser Fall.
Deshalb stehen in den Release-Notes eines MAJOR zwei getrennte Zeilen, und beide sind vor dem
Update zu lesen: **Breaking Change:** sagt, was aufhört zu funktionieren und was diese Instanz
dagegen tun muss; **Migration:** sagt, ob und wie der Korpus umgeschrieben wird (`none required`,
wenn nicht). `tools/wikitool version notes` druckt den Eintrag.
### Eine Instanz aktualisieren
Zwei Wege, je nachdem, wie diese Instanz entstanden ist. Ein **Clone mit gemeinsamer
Git-History** (`upstream`-Remote auf das Ursprungs-Repo, siehe
[instructions/private-instance.md](instructions/private-instance.md)) nimmt Stack-Updates per
echtem Drei-Wege-Merge: `tools/wikitool upstream merge`. Alles Folgende gilt für eine **Instanz
aus einem Tarball**, ohne gemeinsame History - der Weg unten unter „Eine Instanz aktualisieren"
nutzt sie.
Das Anwenden eines Updates schreibt in eine Instanz, die bereits Inhalt hat. Der Inhalt hat dabei
eine **eigene Version**: `.wikitool-kb.json` sagt, in welcher Form die Seiten vorliegen,
unabhängig davon, welche Maschinerie danebensteht. Genau dieser Unterschied ist der Zustand, in
dem sich jede Instanz mitten im Upgrade befindet.
1. **Vor dem Tausch** prüfen, was ansteht - solange `VERSION` noch die alte ist:
```bash
tools/wikitool migrate status
```
Steht hier etwas aus, erst diese Migrationskette abschließen (Schritt 5 unten) - `dist upgrade`
verweigert den Tausch sonst von selbst.
2. Release-Tarball herunterladen und die Release-Notes lesen (Weg A oben).
3. **Maschinerie tauschen:**
```bash
tools/wikitool dist upgrade <tarball-oder-verzeichnis> --dry-run
```
**Beim ersten Sprung auf `4.5.0` oder höher gibt es dieses Kommando in der Instanz noch
nicht** - es kam erst mit `4.5.0`. Dann das Werkzeug aus dem entpackten *neuen* Tarball
verwenden, gegen die alte Instanz gerichtet:
```bash
tar -xzf chemenu-stack-<version>.tar.gz
CHEMENU_ROOT="$PWD" chemenu-stack-<version>/tools/wikitool \
dist upgrade chemenu-stack-<version>.tar.gz --dry-run
```
`CHEMENU_ROOT` sagt dem Paket, auf welchen Korpus es zeigen soll (siehe § Konfiguration);
ohne die Variable würde es den entpackten Tarball selbst für die Instanz halten. Ab dem
zweiten Upgrade trägt die Instanz das Kommando selbst und die kurze Form oben genügt.
Klassifiziert jede Datei aus dem `files`-Block der neuen `.wikitool-release.json`:
unverändert seit der Installation, lokal verändert oder gelöscht, neu im Release, oder aus dem
Release entfallen - und druckt die Migrationskette, die nach dem Tausch aussteht, ohne sie
auszuführen. Ohne `--dry-run` schreibt der Befehl; eine lokal veränderte oder gelöschte Datei
wird dabei **nie** stillschweigend überschrieben - der Lauf bricht mit der vollständigen Liste
ab, es sei denn `--keep-local` ist gesetzt (dann bleibt jede davon unangetastet, erneut
gemeldet). `--prune` entfernt zusätzlich Dateien, die der neue Release nicht mehr ausliefert
und die seit der Installation unverändert sind. Voraussetzungen: ein sauberer Arbeitsbaum
(kein Git-Repo ist ein WARN, keine Sperre), eine lokale `.wikitool-release.json` mit
`files`-Block (fehlt sie, siehe „Fallstricke" unten), und `.wikitool-kb.json` vorhanden.
Committet und pusht nichts (Invariante 5). Vollständiger Fehlerkontrakt:
[tools/CONTRACT.md](tools/CONTRACT.md).
Eine lokal veränderte Stack-Datei ist damit sichtbar, statt von Hand gegen die sha256-Summen
im `files`-Block geprüft werden zu müssen - genau der Schritt, der vor `4.5.0` hier stand.
4. Bei einer Kompatibilitätsgrenze (`dist upgrade` meldet sie laut) die Release-Notes vor dem
nächsten Schritt lesen: **Breaking Change:** und **Migration:** im Eintrag von
`tools/wikitool version notes` sagen, was aufhört zu funktionieren und ob der Korpus
umgeschrieben werden muss.
5. **Die Migrationskette abarbeiten.** `tools/wikitool migrate status` listet jetzt alle
offenen Migrationen in der Reihenfolge, in der sie laufen müssen - bei einem Sprung über
mehrere Versionen sind das mehrere. Für jede: das genannte Dokument unter
`instructions/migrations/` ausführen lassen (die Prozedur dazu ist
`instructions/migrate-corpus.md`), dann
```bash
tools/wikitool migrate done <version>
```
`done` verweigert jede Version, die nicht das nächste Glied ist - eine übersprungene
Migration hinterlässt einen Korpus in einer Form, die keine Version beschreibt. Ein
abgebrochenes Upgrade wird durch erneutes `migrate status` fortgesetzt.
6. Prüfen: `tools/wikitool migrate verify --from <commit vor dem Tausch>`, dann `doctor`,
`docs verify`, `instructions verify` und `lint`. Zum Schluss
`tools/wikitool instructions sync` (die Skills sind Kopien) und die Agent-Session neu
starten. `dist upgrade` nennt diese Reihenfolge im eigenen Abschlussbericht, führt aber keinen
der Schritte selbst aus.
`doctor` warnt, solange `kb_version` hinter `VERSION` zurückliegt und noch Migrationen offen
sind. Einer Instanz, die älter ist als `.wikitool-kb.json`, fehlt die Datei ganz - dann einmalig
`tools/wikitool migrate baseline <version>` aufrufen; geraten wird nichts.
**Fallstricke.** Eine Instanz ohne lokale `.wikitool-release.json` (oder eine ohne `files`-Block,
aus der Zeit vor `4.5.0`) hat für `dist upgrade` keine Basis, gegen die es eine lokale Änderung
erkennen könnte, und verweigert den Tausch - dafür gibt es heute keine Reparatur (siehe Gitea #7).
Der Befehl lädt selbst nichts herunter: `<tarball-oder-verzeichnis>` muss vorher aus Weg A
geholt werden, und ein Tarball muss genau ein Top-Level-Verzeichnis enthalten - die Form, in der
`.gitea/workflows/release.yml` es baut.
Vor `4.5.0` stand hier ein rein manueller Ablauf (Maschinerie von Hand kopieren, `kb/CONTRACT.md`
eingeschlossen, sha256-Vergleich von Hand). `dist upgrade` ersetzt genau diesen Teil; wer ihn
dennoch von Hand nachvollziehen will oder muss (ein Werkzeug, das `wikitool` selbst nicht
ausführen kann), findet die Dateiliste im `files`-Block der `.wikitool-release.json` und die
Ausnahmen (`kb/CONVENTIONS.md`, `kb/*/COLLECTION.md`, `.wikitool-kb.json`) in
[tools/CONTRACT.md](tools/CONTRACT.md)s `dist upgrade`-Zeile.
## Konfiguration
| Variable | Zweck | Fallback |
|----------|-------|----------|
| `WIKI_AUTHOR` | Override für den Autornamen neuer Source-Seiten | `git config user.name` - fehlt beides, bricht `new` mit `ERROR` ab |
| `WIKITOOL_SESSION_ID` | Scopt das Iteration-Budget-Gate auf eine Aufgabe statt auf ein Terminal | Parent-Process-ID (siehe [instructions/session-setup.md](instructions/session-setup.md)) |
| `WIKITOOL_UPDATE_URL` | Release-Feed, den `version check` abfragt | Wert aus `.wikitool-release.json`, sonst der Feed der Ursprungs-Instanz |
| `WIKITOOL_UPDATE_TOKEN` | Gitea-Token für den Release-Feed | keiner - gegen `torben/chemenu` nicht nötig, nur für einen privaten Fork (siehe unten) |
| `CHEMENU_ROOT` | Auf welchen Korpus das Paket zeigt - für einen Aufrufer, der nicht im Checkout selbst liegt | der Checkout, in dem das Paket liegt (`tools/wikitool` verhält sich ohne die Variable unverändert) |
| `WIKI_TRACE` / `WIKI_TRACE_DIR` | Telemetrie abschalten bzw. aus dem Arbeitsbaum heraus umlenken | an, nach `reports/telemetry/` - der MCP-Server verweigert damit den Start, siehe [INSTALL-MCP.md](INSTALL-MCP.md) |
**Gegen das Ursprungs-Repo braucht es kein Token.** `torben/chemenu` ist öffentlich lesbar;
`version check` und der Download in Weg A funktionieren ohne Konfiguration.
**Für einen privaten Fork schon.** Wer den Stack in ein eigenes, nicht öffentliches Repo legt
und `WIKITOOL_UPDATE_URL` auf dessen Feed zeigen lässt, stößt auf eine Eigenheit, die man
kennen sollte: Gitea antwortet anonymen Aufrufern für ein unsichtbares Repo mit demselben
`404` wie für ein gar nicht existierendes. Ein fehlendes Release und ein fehlender Zugriff
sehen dann identisch aus - „kein Update gefunden" wäre in dem Fall schlicht gelogen. Dagegen
hilft ein Gitea-Token mit Lesezugriff:
```bash
export WIKITOOL_UPDATE_TOKEN="<gitea-token>"
tools/wikitool version check
```
## Verifikation
```bash
tools/wikitool doctor
```
Prüft in einem Aufruf: Abhängigkeiten, Autor-Auflösung, Git-Identität/Branch/Remote,
publizierte Skills, Struktur (Collection-Contracts, generierte Dateien), Personalization
(`USER.md`/`SOUL.md` vorhanden **und** ausgefüllt), die optionale Umgebungsnotiz
(`ENVIRONMENT.md`) und die Session-ID.
`OK`/`WARN` sind unbedenklich (ein fehlender Remote z. B. ist ein gültiger Endzustand); nur ein
`FAIL` bricht mit exit 1 ab, und jede Zeile nennt ihr eigenes Fix-Kommando.
Danach zusätzlich:
```bash
tools/wikitool docs verify
tools/wikitool instructions verify
```
## Troubleshooting
- **`wikitool: venv not found`** - Schritt "Werkzeugumgebung anlegen" aus
[instructions/bootstrap.md](instructions/bootstrap.md) bzw.
[instructions/setup-instance.md](instructions/setup-instance.md) wurde noch nicht ausgeführt.
- **Der Agent bietet keine Skills an (`wiki-ingest`, `wiki-query`, ...)** - `.agents/skills/`
und `.claude/skills/` sind generiert und nicht committet. `tools/wikitool instructions sync`
ausführen, dann die Agent-Session neu starten (Harnesses lesen Skills nur beim Start).
- **`doctor` meldet `personalization: FAIL`** - `USER.md`/`SOUL.md` fehlen, oder sie tragen
noch die Sentinel-Zeile aus dem Template (ein umbenanntes Template ist kein ausgefülltes).
Den Personalization-Schritt (6) aus `instructions/setup-instance.md` ausführen lassen; bei
einer Instanz nach Weg C ist das der einzige nachzuholende Schritt.
- **`doctor` meldet `environment: WARN`** - `ENVIRONMENT.md` existiert, trägt aber noch die
Sentinel-Zeile aus dem Template. Ausfüllen (Vorlage: `ENVIRONMENT.md.template`) und die Zeile
entfernen, oder die Datei löschen - sie ist optional, und `absent` ist ein gültiger
Endzustand.
- **`new` bricht mit "No author configured" ab** - weder `$WIKI_AUTHOR` noch
`git config user.name` sind gesetzt. `git config user.name "<Name>"` ausführen, oder
`WIKI_AUTHOR` exportieren.
- **`publish` endet mit Exit-Code 42 (Mass-Update-Gate)** - erwartetes Verhalten bei ≥10
gezählten Dateien (z. B. beim allerersten Commit einer neuen Instanz). Das ist kein Fehler,
sondern die Aufforderung, die Ausgabe einem Menschen zu zeigen: sie enthält die vollständige
Dateiliste und die exakte `--confirm <token>`-Zeile, die nach Freigabe veröffentlicht.
Details: [instructions/gates.md](instructions/gates.md).
- **`publish` endet mit Exit-Code 42 (Publish-Remote-Gate)** - dieser Checkout hat eine
`.wikitool-remotes.json`, und das angesteuerte Remote steht nicht darin. Ebenfalls kein
Fehler: Die Ausgabe nennt die Push-URL, an die geschrieben würde, und die erlaubten. Anders
als beim Mass-Update-Gate gibt es hier **keinen Token und keine Flagge** - stimmt das Ziel
wirklich, trägt der Mensch dessen URL selbst in die Datei ein. Ein Agent, der die Datei
anfasst, um an der Verweigerung vorbeizukommen, öffnet ein Gate aus eigenem Antrieb.
- **Ich will am Tool-Stack selbst weiterarbeiten (nicht nur Wiki-Inhalt betreiben)** - eine neue
Instanz hat dafür keinen Weg: `dist export` lässt `instructions/dev/` (Stack-Entwicklung,
inkl. der vendorten `commonplace/`-Wissensbasis) bewusst und dauerhaft weg, ohne
Restore-Mechanismus. Für Stack-Entwicklung im Ursprungs-Repo arbeiten (oder eine neue
Dev-Instanz daraus exportieren) statt in dieser Instanz nachzurüsten.