Files changed: - .gitea/workflows/ci.yml - .gitea/workflows/release.yml - AGENTS.md - CHANGES.md - DEVELOPMENT.md - EVALS.md - INSTALL.md - README.md - VERSION - docs/ownership-and-templates.md - instructions/CONTRACT.md - instructions/bootstrap.md - instructions/dev/dev-setup.md - instructions/dev/stack-dev/SKILL.md - instructions/gates.md - instructions/ingest-large-tree.md - instructions/kb-profiles.md - instructions/mcp-read-server.md - instructions/migrations/3.0.0-authoring-conventions.md - instructions/preflight.md - instructions/private-instance.md - instructions/session-setup.md - instructions/setup-instance.md - instructions/upgrade-instance.md - tools/CONTRACT.md - tools/README.md - tools/chemenu/cli.py - tools/chemenu/cli_contract.py - tools/chemenu/commands/dist_cmd.py - tools/chemenu/commands/docs_verify.py - tools/chemenu/commands/doctor.py - tools/chemenu/commands/git_publish.py - tools/chemenu/commands/upstream_cmd.py - tools/chemenu/commands/work_cmd.py - tools/chemenu/config.py - tools/chemenu/ownership.py - tools/chemenu/tests/test_cli.py - tools/chemenu/tests/test_dist_cmd.py - tools/chemenu/tests/test_instructions_shell.py - tools/chemenu/tests/test_preflight.py - tools/chemenu/tests/test_preflight_pwsh.py - tools/chemenu/tests/test_run_budget.py - tools/chemenu/tests/test_upstream_cmd.py - tools/chemenu/toc.py - tools/preflight.ps1 - tools/preflight.sh
487 lines
32 KiB
Markdown
487 lines
32 KiB
Markdown
# Installation
|
|
|
|
Dieses Dokument richtet sich an Menschen. Es gibt genau einen Weg zu einer Chemenu-Instanz: Ein
|
|
Agent installiert das **neueste Release** in ein leeres Verzeichnis, das du vorgibst. Die
|
|
Schritte führt der Agent aus, nach `instructions/setup-instance.md` aus demselben Release. Hier
|
|
steht, was du vorher bereitstellst, welchen Satz du ihm gibst, was er dich fragt und was zu tun
|
|
ist, wenn er anhält. Die vollständige Kommandoreferenz steht in
|
|
[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.
|
|
|
|
<!-- dist:strip-start -->
|
|
Wer am Stack selbst arbeiten will, klont dieses Repo. Das ist eine Entwicklungsumgebung mit
|
|
Demo-Korpus und keine Instanz; sie steht in [DEVELOPMENT.md](DEVELOPMENT.md).
|
|
<!-- dist:strip-end -->
|
|
|
|
## Was vorher da sein muss
|
|
|
|
- **Python 3.11 oder neuer, git und [ripgrep](https://github.com/BurntSushi/ripgrep) (`rg`).**
|
|
Die maßgebliche Liste steht in `tools/prerequisites.txt`; der Preflight prüft sie, bevor
|
|
irgendein `wikitool`-Befehl läuft. Installieren musst du selbst - der Agent tut es nie, auch
|
|
nicht mit deiner Zustimmung.
|
|
- **Ein Agent-Harness**: Claude Code, GitHub Copilot (in VS Code oder als CLI), Codex CLI oder
|
|
Mistral Vibe.
|
|
- **Ein leeres Verzeichnis**, in dem die Instanz liegen soll, und dein Harness darin geöffnet.
|
|
Leer heißt: nichts außer einem `.git`. Ein frisch geklontes, leeres Repo für deine Instanz ist
|
|
also genau richtig - liegt dein Repo `torben/nathan` etwa in `~/src/nathan`, installierst du
|
|
dorthin, und der Agent übernimmt dessen `origin` als Ziel für `publish`.
|
|
|
|
Unter Windows zusätzlich:
|
|
|
|
- **PowerShell 7** (`pwsh`), in VS Code als Standardterminal eingestellt. Windows PowerShell 5.1
|
|
reicht nicht, und WSL ist nicht vorgesehen.
|
|
- **Execution Policy `RemoteSigned`** - auf vielen Rechnern ab Werk gesetzt
|
|
(`Get-ExecutionPolicy -List` zeigt es).
|
|
- **Git for Windows.** Es bringt Git Bash mit, in dem Claude Code seine Befehle ausführt.
|
|
- **Ein Installationsverzeichnis mit höchstens 95 Zeichen**, zum Beispiel `C:\Chemenu`. Windows
|
|
erlaubt ohne eingeschaltete lange Pfade nur 259 Zeichen je Pfad, und die Dateien des Wikis
|
|
brauchen den Rest. Wer Administratorrechte hat, kann stattdessen lange Pfade einschalten
|
|
(`LongPathsEnabled`); verlangt wird das nicht.
|
|
|
|
## Der Satz für den Agenten
|
|
|
|
Öffne das leere Verzeichnis in deinem Harness und gib dem Agenten diesen Satz:
|
|
|
|
> Richte in diesem Verzeichnis eine neue Chemenu-Instanz ein. Hol dazu das neueste Release von
|
|
> `https://gitea.nehmer.net/api/v1/repos/torben/chemenu/releases/latest` und folge dessen Asset
|
|
> `setup-instance.md`. Lies vor dem Start des Preflights das Asset `preflight.md` aus demselben
|
|
> Release.
|
|
|
|
Damit liest der Agent die Beschreibung des neuesten Releases und daraus die beiden Anleitungen.
|
|
Dann lädt er das passende Preflight-Skript (`preflight.ps1` für PowerShell, `preflight.sh` für
|
|
eine POSIX-Shell) mit einem Befehl seiner Shell ins Verzeichnis - nicht über den Browser, damit
|
|
Windows die Datei nicht als „aus dem Internet“ markiert - und startet es. Das Skript lädt den
|
|
Tarball desselben Releases, prüft dessen sha256, entpackt ihn in das Verzeichnis, löscht sich
|
|
selbst und prüft dann im entpackten Baum, ob alles da ist.
|
|
|
|
Die Liste aller Releases: <https://gitea.nehmer.net/torben/chemenu/releases>. Das Repo ist
|
|
öffentlich; der Download braucht weder Konto noch Token.
|
|
|
|
## Was der Agent dich fragt
|
|
|
|
Raten darf der Agent keine dieser Antworten, und keine übernimmt er aus einem anderen Repo:
|
|
|
|
- **Autor-Identität** - Name und E-Mail für `git config`. Das ist zugleich der Autorname jeder
|
|
künftig angelegten Wiki-Seite (`$WIKI_AUTHOR` überschreibt ihn bei Bedarf).
|
|
- **Remote** - bei einem leeren Klon nur die Bestätigung, dass `origin` stimmt; sonst eine URL,
|
|
wenn du auf einen Server pushen willst. Ohne Remote bleibt die Instanz lokal, und jedes
|
|
`publish` läuft mit `--no-push`.
|
|
- **Sprache und Ton der Seiten** - sie landen in `kb/CONVENTIONS.md`, dazu je Collection
|
|
`kb/<name>/COLLECTION.md`. Fertige Profile, darunter ein vollständiges deutsches, hält
|
|
`instructions/kb-profiles.md` bereit. Entscheide das **vor dem ersten Ingest**: Danach ist ein
|
|
Wechsel der Abschnittsnamen eine Migration jeder bestehenden Seite. Titel, Wikilink-Ziele,
|
|
Zitat-IDs, Schema-Werte, Tags, Befehle und Pfade folgen keiner Sprache - `Act Runner` heißt in
|
|
jeder Instanz `Act Runner`.
|
|
- **Anwendungsgebiet** - woraus dieses Wiki seine Quellen zieht. Daraus schlägt der Agent eine
|
|
`source_type`-Liste vor (bei einem Verein etwa Satzung, Protokoll, Spielbericht). Das ist ein
|
|
Startpunkt, keine Festlegung: Später wird sie an echtem Bestand korrigiert
|
|
(`instructions/evolve-subtypes.md`).
|
|
- **Personalisierung** - wer diese Instanz bedient (`USER.md`) und wie sie klingt (`SOUL.md`).
|
|
Der Agent interviewt dich entlang der Vorlagen und schreibt deine Antworten wörtlich mit. Zwei
|
|
Fragen beantwortest nur du: den **Namen der Persona** und die **Themen, die bewusst draußen
|
|
bleiben**.
|
|
- **Umgebung** (optional) - Harness, MCP-Server, Remotes, damit spätere Sitzungen nicht erneut
|
|
fragen. „Weiß ich nicht“ ist eine gültige Antwort.
|
|
- **Telemetrie** - standardmäßig aus; der Agent fragt nur, ob du sie einschalten willst.
|
|
- **Aufgaben-Tracker** (optional) - siehe [Konfiguration](#konfiguration).
|
|
|
|
Am Ende legt der Agent den ersten Commit an. Dabei hält das Mass-Update-Gate an (Exit 42), weil
|
|
eine neue Instanz aus weit mehr als zehn Dateien besteht. Das ist erwartet: Der Agent zeigt dir
|
|
die Dateiliste und die `--confirm`-Zeile, und erst nach deiner Freigabe wird veröffentlicht.
|
|
Danach startest du die Agent-Sitzung im selben Verzeichnis neu, damit sie die Skills lädt.
|
|
|
|
## Wenn der Agent anhält
|
|
|
|
Der Preflight hält mit **Exit 42** an, wenn du etwas tun musst. Seine Ausgabe nennt in einem
|
|
nummerierten Block, was fehlt, warum, den Befehl, der es behebt, und wie es weitergeht. Der
|
|
Agent zeigt dir diesen Block unverändert, setzt eine Übersetzung höchstens darunter und wartet.
|
|
Sag ihm Bescheid, wenn du fertig bist; dann prüft er erneut. Ausweichen oder selbst installieren
|
|
darf er nicht.
|
|
|
|
**Beim Herunterladen und Entpacken** (das Skript aus dem Release, bevor es einen Baum gibt):
|
|
|
|
- **Werkzeuge zum Laden oder Entpacken fehlen** (Exit 42). Unter Linux und macOS braucht das
|
|
Skript `curl`, `tar` und `sha256sum` (oder `shasum`), unter Windows nur das `tar.exe` aus
|
|
Windows 10/11. Installiere, was die Ausgabe nennt; unter Windows liefert Git for Windows alles
|
|
für Git Bash mit.
|
|
- **Das Verzeichnis ist zu lang** (Exit 42, nur Windows ohne lange Pfade). Nimm ein kürzeres,
|
|
etwa `C:\Chemenu`, öffne es im Harness und gib den Satz dort noch einmal.
|
|
- **Das Verzeichnis ist nicht leer** (Exit 1). Es darf nichts enthalten außer dem Skript und
|
|
einem `.git`. Räume es selbst auf oder nimm ein anderes - der Agent löscht dort nichts.
|
|
- **Download fehlgeschlagen oder Prüfsumme falsch** (Exit 1). Es wurde nichts entpackt. Prüf die
|
|
Internetverbindung und lass es erneut versuchen; einen anderen Download-Weg sucht der Agent
|
|
nicht. Ohne direkten Download kannst du Tarball und `.sha256` von der Release-Seite selbst
|
|
nebeneinander ablegen; der Agent startet das Skript dann mit `--archive <tarball>`.
|
|
|
|
**Im entpackten Baum** (jeder weitere Lauf ist `tools/preflight.sh` bzw. unter PowerShell
|
|
`pwsh -NoProfile -ExecutionPolicy Bypass -File tools/preflight.ps1`):
|
|
|
|
- **Ein Werkzeug fehlt** - Python, git, ripgrep, unter Windows auch PowerShell 7. Die Ausgabe
|
|
nennt den Installationsbefehl für dein System. Ist es schon installiert, nur woanders, nenn dem
|
|
Agenten den Pfad; er reicht ihn mit `--set <werkzeug>=<pfad>` weiter.
|
|
- **Eine Version ist zu alt** - zum Beispiel Python unter 3.11. Neuere Version installieren oder
|
|
deren Pfad nennen.
|
|
- **Ein genannter Pfad funktioniert nicht** - der Pfad muss auf das Programm selbst zeigen, nicht
|
|
auf seinen Ordner.
|
|
- **Die Python-Umgebung (`tools/.venv`) oder ihre Bibliotheken ließen sich nicht einrichten.** Die
|
|
Ausgabe zeigt, was Python oder pip gemeldet haben. Meist blockiert ein Proxy oder ein
|
|
Sicherheitsprogramm den Download; das klärt, wer deinen Rechner betreut.
|
|
- **Skripte tragen die Markierung „aus dem Internet“** (nur Windows). Das passiert, wenn das
|
|
Release im Browser geladen und im Explorer entpackt wurde. Einmal im Verzeichnis, in
|
|
PowerShell 7: `Get-ChildItem -Recurse -File | Unblock-File`. `doctor` zeigt den Stand unter
|
|
`script-marks`.
|
|
- **Die Execution Policy verbietet Skripte** (`Restricted` oder `AllSigned`, nur Windows). Die
|
|
Ausgabe nennt die eine Zeile für ein PowerShell-7-Fenster
|
|
(`Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned`). Setzt eine
|
|
Gruppenrichtlinie sie, hilft nur die IT - oder du arbeitest aus Git Bash mit `tools/wikitool`.
|
|
`doctor` zeigt den Stand unter `execution-policy`.
|
|
- **Das Installationsverzeichnis ist zu lang** (nur Windows ohne lange Pfade). Die Instanz muss
|
|
in ein kürzeres Verzeichnis umziehen, etwa `C:\Chemenu`.
|
|
|
|
Hält der Agent an einer anderen Stelle an und ist die Ursache nicht offensichtlich, bietet er dir
|
|
einen Fehlerbericht an - siehe [Troubleshooting](#troubleshooting).
|
|
|
|
## Version und Updates
|
|
|
|
Jede Instanz trägt die Version des **Stacks** (Werkzeuge, Typen, Instruktionen, Contracts) -
|
|
nicht die ihres Inhalts. Sie steht in `VERSION`, daneben `.wikitool-release.json` mit Herkunft
|
|
und Exportdatum des Releases.
|
|
|
|
```bash
|
|
tools/wikitool version # was läuft hier, und woher kommt es
|
|
tools/wikitool version check # gibt es ein neueres Release?
|
|
```
|
|
|
|
`version check`, `version notes` und `dist upgrade --latest` sind die einzigen Befehle, die
|
|
ins Netz gehen, und alle drei fragen denselben Release-Feed der Ursprungs-Instanz
|
|
(`$WIKITOOL_UPDATE_URL` überschreibt; sonst der Wert aus dem Stamp). `version check` ist dafür da;
|
|
`version notes` greift nur dann darauf zurück, wenn die lokale `CHANGES.md` den Eintrag nicht
|
|
hat - auf einer Instanz also immer, siehe unten - und sagt vorher auf stderr, welche URL es
|
|
fragt; `dist upgrade` fragt den Feed nur, wenn `--latest` dasteht, und lädt dann auch das Release
|
|
herunter (siehe „Eine Instanz aktualisieren"). Ein nicht erreichbarer Feed wird als Fehler
|
|
gemeldet - **nie** als „aktuell" und nie als „keine Notes".
|
|
|
|
**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 beide Zeilen - im Ursprungs-Repo aus der dort
|
|
gefüllten `CHANGES.md`, auf einer ausgelieferten Instanz aus dem Release-Feed, weil die Instanz
|
|
die Datei nur als Stub bekommt und ein Update sie nie überschreibt. Der Befehl fragt dabei immer
|
|
das **neueste** Release: solange `VERSION` noch die alte Fassung nennt, antwortet er also mit
|
|
einer anderen Version als der eigenen und sagt das auf stderr dazu. Ist der Feed nicht
|
|
erreichbar, nennt die Fehlermeldung die Release-Seite, die `.wikitool-release.json` als
|
|
`release_url` führt; `--offline` verlangt diesen Weg von vornherein.
|
|
|
|
### Eine Instanz aktualisieren
|
|
|
|
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.
|
|
|
|
**Die Durchführung selbst steht in `instructions/upgrade-instance.md`** - die Reihenfolge, was
|
|
jeder Schritt entscheidet, wo die Agent-Sitzung neu gestartet werden muss, und die beiden Stellen,
|
|
an denen heute Handarbeit nötig ist. Sie steht dort und nicht hier, weil sie von einer
|
|
Agent-Sitzung ausgeführt wird; eine zweite Fassung derselben Schrittfolge an dieser Stelle wäre
|
|
genau die Kopie, die irgendwann auseinanderläuft. Wer den Lauf selbst fahren will, liest dieselbe
|
|
Datei.
|
|
|
|
Was dieses Dokument beiträgt, ist die Entscheidung *davor* - welches Release, ob überhaupt, und
|
|
wem die Instanz als Quelle vertraut - und zwei Sonderfälle, die die Instruktion nicht abdecken
|
|
kann, weil es sie dort noch nicht gibt.
|
|
|
|
**Das Release kommt mit einem Befehl.** `tools/wikitool dist upgrade --latest --expect <version>`
|
|
fragt den Release-Feed, lädt Tarball und `.sha256` in ein Arbeitsverzeichnis, prüft den Tarball
|
|
gegen die Summe und wendet ihn an; das Arbeitsverzeichnis verschwindet bei jedem Ausgang wieder,
|
|
auch bei `--dry-run`. `<version>` ist die, die `version notes` gedruckt hat: der Feed kennt nur
|
|
sein *neuestes* Release, und `--expect` verweigert den Lauf **vor** dem Download, wenn inzwischen
|
|
ein neueres erschienen ist, statt es ungelesen einzuspielen. Beides zusammen entscheidet vor dem
|
|
Download über „schon aktuell", Downgrade und Vor-Release (`-beta.N` braucht `--pre`); fehlt dem
|
|
Release der Tarball oder die Summe, bricht der Befehl vor dem ersten Download ab und nennt die
|
|
Release-Seite. Wer offline arbeitet oder einen Tarball vom Betreiber bekommen hat, gibt statt
|
|
`--latest` weiter die Datei an (`dist upgrade <tarball>`).
|
|
|
|
**Was die Prüfsumme leistet - und was nicht.** Die `.sha256` liegt beim selben Feed wie der
|
|
Tarball. Sie schützt vor einer beschädigten Übertragung, nicht vor einem Feed, der selbst
|
|
kompromittiert ist: die Echtheit eines Releases beruht auf dem Vertrauen in den Host, dessen
|
|
Feed die Instanz fragt (`update_url` im Stamp). Es gibt keinen https-Zwang; wer einen
|
|
`http://`-Feed konfiguriert, tut das bewusst. `$WIKITOOL_UPDATE_TOKEN` geht nur an Downloads
|
|
auf demselben Host wie der Feed.
|
|
|
|
**Beim ersten Sprung auf ein Release, das `--latest` kennt, gibt es die Option in der Instanz
|
|
noch nicht** - die Instruktion, die dort steht, gehört zum Release, das die Instanz verlässt.
|
|
Dann Tarball und `.sha256` einmal von der Release-Seite holen, nebeneinander ablegen und
|
|
`dist upgrade <tarball>` geben; ab dem Release danach trägt die Instanz `--latest` selbst.
|
|
|
|
**Beim ersten Sprung auf `4.5.0` oder höher gibt es `dist upgrade` 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 Kommando und Instruktion selbst, und der normale Weg greift.
|
|
|
|
Was `dist upgrade` dabei genau tut, klassifiziert und verweigert, steht in
|
|
[tools/CONTRACT.md](tools/CONTRACT.md) - einschließlich des vollständigen Fehlerkontrakts. 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.
|
|
|
|
`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.
|
|
Mit `<tarball-oder-verzeichnis>` lädt der Befehl selbst nichts herunter; die Datei muss vorher
|
|
von der Release-Seite geholt werden. Nur `--latest` lädt, und ein Tarball muss in beiden Fällen 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`-Datensatz (oder direkt:
|
|
`tools/wikitool dist upgrade -h`).
|
|
|
|
## 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 | Eine vom Harness selbst gesetzte Sitzungs-Variable, wo eine bekannt ist (z. B. `CLAUDE_CODE_SESSION_ID`), sonst die 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 gegen einen Feed in einem nicht öffentlichen Repo |
|
|
| `WIKITOOL_TASKS_CONFIG` | Pfad zu einer Tracker-Konfiguration, die `task`, `review` und `doctor` statt `.wikitool-tasks.json` lesen - um einen Checkout der Reihe nach gegen mehrere Tracker laufen zu lassen | die `.wikitool-tasks.json` im Repo-Root. Nennt die Variable eine Datei, die es nicht gibt, ist das ein Fehler und nie „kein Tracker konfiguriert" |
|
|
| `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 | Aus - siehe unten |
|
|
| `WIKI_TRACE_MAX_SESSION_BYTES` / `WIKI_TRACE_KEEP_SESSIONS` | Byte-Deckel je Session-Trace bzw. wie viele Session-Verzeichnisse die Retention behält | 5 MiB je Session, 250 Verzeichnisse |
|
|
|
|
**Gegen das Ursprungs-Repo braucht es kein Token.** `torben/chemenu` ist öffentlich lesbar;
|
|
`version check`, `dist upgrade --latest` und die Installation funktionieren ohne Konfiguration.
|
|
|
|
**Telemetrie ist in einer Instanz aus.** Jede Instanz trägt die `.wikitool-release.json` ihres
|
|
Releases, und daran erkennt `chemenu.telemetry.policy`, dass niemand Telemetrie bestellt hat.
|
|
Das gilt auch für jeden weiteren Klon der Instanz, weil die Datei mit dem ersten Commit ins Repo
|
|
kommt. Nur ein Klon des Ursprungs-Repos zur Entwicklung trägt keine; dort sind die Traces das
|
|
Messinstrument, mit dem der Stack sich selbst bewertet, und sie stehen auf **an**.
|
|
|
|
Wer den Default umdrehen will, legt `.wikitool-telemetry.json` im Repo-Root an (pro Checkout,
|
|
gitignored, kein `.template` - genau wie `.wikitool-remotes.json`):
|
|
|
|
```json
|
|
{ "enabled": true, "max_session_bytes": 5242880, "keep_sessions": 250 }
|
|
```
|
|
|
|
Alle drei Schlüssel sind optional. `WIKI_TRACE` überschreibt `enabled` weiterhin in beide
|
|
Richtungen und schlägt diese Datei. `wikitool doctor` meldet den aktuellen Zustand (an/aus,
|
|
warum, und die Menge gegen beide Deckel); mehr dazu in [EVALS.md](EVALS.md) § "Whether it
|
|
runs at all".
|
|
|
|
**Tool-Pfade - schreibt der Preflight, nicht der Mensch.** `.wikitool-tools.json` im Repo-Root
|
|
hält die absoluten Pfade von Python, git und ripgrep, so wie der Preflight sie auf diesem Rechner
|
|
gefunden hat; `wikitool` startet git und rg von dort statt über `PATH`. Pro Checkout und
|
|
gitignored - ein Pfad auf einem Rechner sagt über den nächsten nichts. Fehlt die Datei oder ist
|
|
sie unvollständig, startet `tools/wikitool` nicht (Exit 42) und nennt den Preflight. Liegt ein
|
|
Tool woanders, als der Preflight sucht, nennt man den Pfad mit
|
|
`tools/preflight.sh --set rg=<pfad>` (PowerShell: `pwsh -NoProfile -ExecutionPolicy Bypass -File tools/preflight.ps1 --set rg=<pfad>`); von Hand
|
|
bearbeitet wird die Datei nicht. `doctor` meldet
|
|
unter `tool-paths`, ob alle Pfade noch stimmen.
|
|
|
|
**Aufgaben-Tracker anbinden - optional.** Der Wochenrückblick (`tools/wikitool review`, Skill
|
|
`gtd-weekly-review`) gleicht die Projektseiten unter `kb/gtd/` gegen einen Aufgaben-Tracker ab. Welcher
|
|
das ist, steht in `.wikitool-tasks.json` im Repo-Root - der dritten Datei dieser Art neben
|
|
`.wikitool-telemetry.json` und `.wikitool-remotes.json`: pro Checkout, ohne `.template`, und
|
|
**gitignored, sobald ein Token darin liegt**. Fehlt sie, ist schlicht kein Tracker konfiguriert;
|
|
das ist ein gültiger Endzustand, kein Fehler. Kaputt ist sie dagegen ein `FAIL` - eine
|
|
unlesbare Konfiguration darf nicht als „kein Tracker" durchgehen.
|
|
|
|
```json
|
|
{
|
|
"schema": 1,
|
|
"provider": "superproductivity",
|
|
"thresholds": {
|
|
"stalled_waiting_days": 14,
|
|
"unpaged_project_weeks": 3,
|
|
"someday_stale_months": 5
|
|
},
|
|
"superproductivity": {
|
|
"access": "api",
|
|
"api_base_url": "http://127.0.0.1:3876",
|
|
"api_token": "<token aus den SP-Einstellungen>"
|
|
}
|
|
}
|
|
```
|
|
|
|
```json
|
|
"superproductivity": {
|
|
"access": "snapshot",
|
|
"backups_dir": "~/.config/superProductivity/backups"
|
|
}
|
|
```
|
|
|
|
`provider` wählt den Adapter - ausgeliefert werden `superproductivity` und `caldav`. Der
|
|
`thresholds`-Block trägt die drei Schwellwerte des Rückblicks (Konfiguration, nicht Schema): ab
|
|
wann ein Waiting-For überfällig ist, ab welchem Alter ein Tracker-Projekt ohne `kb/`-Seite
|
|
gemeldet wird, und ab wann ein Someday-Eintrag als verstaubt gilt. Ein Wert, den der Provider
|
|
gar nicht liefern kann - ein Waiting-Posten ohne Wiedervorlagedatum, ein Tracker-Projekt ohne
|
|
bestimmbares Anlagedatum - wird vom Rückblick nicht still übersprungen, sondern als eigene
|
|
Fundstelle gemeldet (`waiting_no_follow_up`/`project_age_unknown`).
|
|
|
|
Der gleichnamige Provider-Block trägt dessen Verbindungsangaben, und bei Super Productivity
|
|
entscheidet `access` **verpflichtend und ohne Rückfall**, welcher von zwei sich ausschließenden
|
|
Wegen das ist: eine headless bediente Instanz setzt `access: "snapshot"` und liest
|
|
ausschließlich den jüngsten Backup-Schnappschuss unter `backups_dir` (läuft auch ohne laufende
|
|
App, aber rein lesend - der Tracker ist von dort aus nicht schreibbar); eine Desktop-Instanz
|
|
setzt `access: "api"` und spricht ausschließlich die lokale REST-API an, die nur antwortet,
|
|
solange die App läuft, dafür aber auch den aktuellen Zustand liefert und den Schreibpfad trägt.
|
|
Der Block nennt nur die Felder seines eigenen Wegs - ein `backups_dir` neben `access: "api"` oder
|
|
ein `api_token` neben `access: "snapshot"` wird beim Lesen der Konfiguration abgelehnt, nicht
|
|
ignoriert. `api_token` ist bei `access: "api"` Pflicht, da jeder Endpunkt außer `GET /health`
|
|
`Authorization: Bearer <token>` verlangt.
|
|
|
|
`tools/wikitool new project` legt einen gleichnamigen Tracker-Eintrag nur auf einer
|
|
`access: "api"`-Instanz an (und auch dort nicht automatisch - siehe die Kommandotabelle). Auf
|
|
einer `access: "snapshot"`-Instanz verweigert das Kommando vollständig, exit 1: der Tracker ist
|
|
von dort aus nur lesbar. Dasselbe gilt für `tools/wikitool task new`, den zweiten Schreibweg:
|
|
es legt einen einzelnen Posten im Tracker an - ohne `kb/`-Seite - und existiert ebenfalls nur
|
|
auf einer `access: "api"`-Instanz. `tools/wikitool task close --id` ist der dritte und letzte
|
|
Schreibweg - er markiert einen Posten erledigt, löscht ihn nie - und verweigert auf
|
|
`access: "snapshot"` auf dieselbe Weise. `tools/wikitool task list --project` ist rein lesend
|
|
und beantwortet daher auf beiden Zugriffsarten.
|
|
|
|
**`caldav`** ist der standardbasierte zweite Adapter (RFC 4791/5545), gegen Nextcloud Tasks
|
|
verifiziert, mit iOS *Erinnerungen* als mobilem Client - gebaut nach dem Zuschnitt: auf dem
|
|
Telefon wird abgehakt, gepflegt wird am Schreibtisch. Anders als bei Super Productivity gibt es
|
|
nur einen Zugriffsweg - CalDAV ist immer ein Netzwerkzugriff, kein `access`-Feld nötig:
|
|
|
|
```json
|
|
"caldav": {
|
|
"url": "https://<host>/remote.php/dav/calendars/<user>/",
|
|
"username": "<login>",
|
|
"app_password": "<Nextcloud-App-Passwort>",
|
|
"inbox_list": "Inbox",
|
|
"someday_list": "Someday",
|
|
"exclude_lists": ["<vorhandene Liste, die kein Projekt ist>"]
|
|
}
|
|
```
|
|
|
|
`url` zeigt auf das CalDAV-Calendar-Home-Set des Kontos; sie darf ein Alias sein (Nextcloud
|
|
akzeptiert dort einen Kurznamen), da jede spätere Adresse ausschließlich aus den vom Server
|
|
gelieferten `href`s stammt, nie aus dieser URL und einem Namen zusammengesetzt wird. `username`
|
|
ist der Login-Name, der von der Benutzer-ID in der URL abweichen kann - ein
|
|
Nextcloud-App-Passwort wird empfohlen, nicht das Kontopasswort. `inbox_list`/`someday_list`
|
|
nennen die beiden festen Listen (je genau eine pro Instanz); `exclude_lists` nimmt vorhandene
|
|
reine Aufgabenlisten heraus, die keine Projekte sind - eine Liste mit `VEVENT`-Anteil zählt
|
|
ohnehin nie als Projekt.
|
|
|
|
Ein Projekt ist dort eine Liste, deren unterstützte Komponente ausschließlich `VTODO` ist; `tools/wikitool
|
|
new project` legt sie automatisch per `MKCALENDAR` an - anders als bei Super Productivity ohne
|
|
Rückfrage, weil CalDAV einen echten Anlage-Befehl für Listen kennt. Die Eindeutigkeitsprüfung
|
|
läuft gegen **jede** Liste im Konto, auch gegen ausgeschlossene, Inbox, Someday und gemischte
|
|
Kalender - kollidiert ein neuer Name mit einer davon, wird nichts angelegt und die Kollision
|
|
genannt; die vorhandene Liste in Nextcloud umzubenennen bleibt Handarbeit. `tools/wikitool task
|
|
new`/`task close` funktionieren auf einer `caldav`-Instanz uneingeschränkt - es gibt keinen
|
|
reinen Lesemodus wie `access: "snapshot"`. Beim Abhaken ändert `task close` ausschließlich
|
|
`STATUS`, `COMPLETED`, `PERCENT-COMPLETE`, `LAST-MODIFIED` und `DTSTAMP` an der bestehenden
|
|
`.ics`-Ressource; jede andere Eigenschaft - auch eine unbekannte `X-`-Eigenschaft oder ein Alarm
|
|
- bleibt unverändert erhalten, und eine seit dem Lesen veränderte Ressource (ETag-Konflikt)
|
|
schreibt nichts und bricht mit exit 1 ab. Gelöscht wird nie etwas.
|
|
|
|
Listen abgeschlossener Projekte bleiben nach dem Archivieren bestehen - der Adapter löscht nie
|
|
eine Liste; das übernimmt der Betreiber von Hand in Nextcloud, sobald gewünscht.
|
|
|
|
## 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`), den Aufgaben-Tracker (`.wikitool-tasks.json` - fehlt sie, ist das `OK`; ist
|
|
ein Provider konfiguriert, zusätzlich ob sein Lesepfad bereitsteht und seine API gerade
|
|
antwortet, beides nie ein `FAIL`) 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
|
|
|
|
- **`tools/wikitool` endet mit `STOP - this checkout is not set up yet` (Exit 42)** - der
|
|
Preflight ist in diesem Checkout noch nicht durchgelaufen, oder seit dem letzten Update nicht
|
|
mehr: `tools/preflight.sh` ausführen, siehe
|
|
[instructions/preflight.md](instructions/preflight.md). In PowerShell 7 unter Windows heißt der
|
|
Aufruf `pwsh -NoProfile -ExecutionPolicy Bypass -File tools/preflight.ps1`; das
|
|
`-ExecutionPolicy Bypass` gilt nur für diesen einen Prozess und ändert keine Einstellung. Was
|
|
seine Ausgabe dann bedeuten kann, steht unter [Wenn der Agent anhält](#wenn-der-agent-anhält).
|
|
- **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 Personalisierungs-Schritt aus `instructions/setup-instance.md` ausführen lassen; bei einem
|
|
weiteren Klon einer älteren Instanz 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.
|
|
- **Setup oder Update schlägt fehl und ich will es melden** - den Agenten
|
|
[instructions/bug-report.md](instructions/bug-report.md) ausführen lassen, oder direkt
|
|
`python3 tools/bugreport.py`. Das Skript braucht nur Python 3.8 oder neuer, läuft auch ohne
|
|
funktionierendes `wikitool` und schreibt ein Bündel nach `reports/bugreport-<Zeitstempel>/`
|
|
samt Zip. Geheimnisse werden entfernt, und aus allem, was das Skript selbst erzeugt, bleiben
|
|
Seitentitel draußen (`--titles` nimmt sie mit). Der Sitzungs-Trace ist standardmäßig dabei
|
|
(`--no-trace` lässt ihn weg) und kann wie Chronologie und Transkripte Seiteninhalt und Titel
|
|
enthalten; das Bündel enthält außerdem Maschinen-, Benutzer- und Pfadnamen. Mit `--pseudonymise`
|
|
ersetzt das Skript Benutzer-, Host-, Pfad-, Git- und Remote-Namen durch Platzhalter, die Länge,
|
|
Leerzeichen, Bindestriche und Pfadtiefe erhalten; der Agent kann danach weitere Namen
|
|
(Personen, Firmen, Kunden, Projekte) mit `--bundle … --candidates …` nachtragen. Das ist das
|
|
Urteil eines Modells und lässt einen Rest übrig - lies das Bündel vor dem Teilen. Die
|
|
Zuordnung, die Prüfliste und die Kandidatendatei enthalten Originale und liegen neben, nie im
|
|
Bündel. Es wird nirgends hochgeladen - den Kanal wählst du selbst.
|