# Entwicklung dieses Stacks Dieses Dokument richtet sich an Menschen, die an `tools/wikitool`, dem Type-Schema oder der Instruction-/Skill-Schicht selbst arbeiten - nicht an den Konsumenten einer Instanz. Für die Gegenseite (eine Instanz installieren, aktualisieren, betreiben) siehe [INSTALL.md](INSTALL.md). **Diese Datei wird nicht ausgeliefert.** Sie ist das menschliche Gegenstück zu `instructions/dev/`, das `tools/wikitool dist export` vollständig ausschließt: eine ausgelieferte Instanz hat keinen Release-Workflow, keine CI und kein Issue-Board, also braucht sie auch keine Anleitung dafür. `dist_cmd.ROOT_FILES` listet sie deshalb bewusst nicht - der Grund steht dort als Kommentar, damit eine spätere Sitzung die vermeintliche Lücke nicht "repariert". Und weil sie nicht ausgeliefert wird, darf sie - anders als `README.md`, `INSTALL.md` oder `EVALS.md`, die `instructions verify` auf genau diesen Punkt prüft - nach `instructions/dev/` verlinken. ## Entwicklungsumgebung Am Stack wird in einem Klon dieses Repos gearbeitet. Ein solcher Klon ist **keine Instanz** und wird nie eine. Instanzen entstehen ausschließlich aus Releases, siehe [INSTALL.md](INSTALL.md). ```bash git clone https://gitea.nehmer.net/torben/chemenu.git cd chemenu ``` Danach den Agenten `instructions/bootstrap.md` ausführen lassen: Preflight, dann `tools/wikitool instructions sync`. Die Agenten-Seite dazu - was hier anders ist als in einer Instanz und wie `dist export` als Testwerkzeug läuft - steht in [instructions/dev/dev-setup.md](instructions/dev/dev-setup.md). Was ein Klon mitbringt und eine Instanz nicht: - **Den Demo-Korpus.** Rund 170 Seiten, die den Stack selbst dokumentieren: Gates, Lint, Versionierung, Suche, das Wiki-Muster. Er ist Testbett und begehbares Beispiel, keine produktive Wissensbasis. Was an ihm geändert werden darf, regelt [instructions/dev/corpus-policy.md](instructions/dev/corpus-policy.md). - **Eine Demo-Persona** in `USER.md`/`SOUL.md`. `doctor` meldet beide als ausgefüllt. Sie beschreiben den Demo-Betrieb, nicht dich. - **Telemetrie an.** Ohne `.wikitool-release.json` ist der Klon die Messstation, mit der der Stack sich selbst bewertet ([EVALS.md](EVALS.md) § „Whether it runs at all“). - **`instructions/dev/`, `commonplace/`, `.gitea/` und diese Datei.** `dist export` liefert davon nichts aus. `ENVIRONMENT.md` fehlt nach jedem Klon, weil die Datei gitignored ist: Sie beschreibt einen Checkout, nicht das Repo. Wer sie anlegt (Vorlage `ENVIRONMENT.md.template`, Schritt 5 in `instructions/bootstrap.md`), erspart jeder Stack-Sitzung die Fragen nach Harness, `gitea-mcp` und Remote. ### `dist export` als Build- und Testwerkzeug `tools/wikitool dist export ` schreibt genau den Baum, den ein Release ausliefert: Maschinerie ohne Wiki-Inhalt, ohne Git-Historie, ohne `instructions/dev/`. Damit prüft man vor einem Release, was ausgeliefert würde (`--dry-run` listet es nur). Und man spielt den Installationsweg nach, ohne auf ein Release zu warten: Tarball daraus bauen wie `.gitea/workflows/release.yml`, dann das Preflight-Skript in einem leeren Verzeichnis mit `--archive ` starten. Der CI-Schritt „The distribution works as a fresh instance“ in `.gitea/workflows/ci.yml` macht genau das. Für eine echte Instanz ist ein solcher Export kein Weg. Ihm fehlen die Release-Herkunft im Stamp, und `dist upgrade --latest` vergleicht später gegen einen Stand, den es nie als Release gab. ### Ein Release-Feed in einem nicht öffentlichen Repo Wer den Stack in einem eigenen, nicht öffentlichen Repo betreibt und Instanzen von dort aktualisiert, lässt `WIKITOOL_UPDATE_URL` auf dessen Feed zeigen. Dabei gibt es eine Eigenheit: 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 falsch. Dagegen hilft ein Gitea-Token mit Lesezugriff in `WIKITOOL_UPDATE_TOKEN`. Es geht nur an Downloads auf demselben Host wie der Feed. ## Der Release-Ablauf Zwischen zwei Releases führt der Stack **einen** laufenden Versionskandidaten statt einer neuen Nummer pro Bump. Das volle Modell - Zustandsort, Eskalationslogik, warum eine Nummer erst durch ein Release verbraucht wird - steht in [instructions/dev/version-parts.md](instructions/dev/version-parts.md) und [docs/version-model.md](docs/version-model.md). Hier nur der Ablauf, in der Reihenfolge, in der eine Sitzung ihn tatsächlich durchläuft: 1. **Bump eröffnet oder eskaliert den Kandidaten, gewichtet mit `--impact`.** ```bash tools/wikitool version bump --minor --title "Was sich geändert hat" --impact medium ``` Schreibt `VERSION` als `X.Y.Z-beta.N` und öffnet (oder aktualisiert) den passenden `CHANGES.md`-Eintrag. Mehrere Bumps für dieselbe Änderung sind normal - jeder aktualisiert denselben Eintrag, statt einen neuen zu eröffnen. `--impact high|medium|low` (Default `medium`) gruppiert den Eintrag; `tools/wikitool version regrade` korrigiert eine Note später, wenn der Gesamteindruck des Kandidaten den Blick auf einen früheren Bump ändert. 2. **Der Eintrag bekommt seine Prosa - zweigeteilt.** `bump` schreibt nur das Skelett (Heading, Datum, Autor, die maschinenverwaltete, gruppierte Bump-Titel-Liste, ggf. Breaking-/Migration-Zeile). Darunter kommen zwei Autorenanteile: eine kurze Zusammenfassung (ein paar Sätze, worum es in diesem Release geht) direkt unter der Liste, und darunter je Bump ein eigener `### `-Changeset-Absatz. Details dazu in [instructions/dev/version-parts.md](instructions/dev/version-parts.md) § The candidate model. 3. **Verify laufen lassen, bevor irgendetwas gepublished wird:** ```bash cd tools && .venv/bin/python -m pytest -q tools/wikitool docs verify tools/wikitool instructions verify ``` 4. **`version release` fixiert den Kandidaten**, sobald er ausgeliefert werden soll: ```bash tools/wikitool version release --title "Zusammenfassender Titel" ``` Streicht den `-beta.N`-Suffix aus `VERSION` und schließt den Changelog-Eintrag. `--title` ist optional - ohne ihn bleibt der Titel des letzten Bumps stehen; mit ihm bekommt ein Kandidat, der mehrere Bump-Titel gesammelt hat, eine zusammenfassende Überschrift. Verweigert, wenn der Kandidat zwei oder mehr Bumps gesammelt hat und die Zusammenfassung aus Schritt 2 noch fehlt - ein Kandidat mit genau einem Bump ist davon ausgenommen. Committet und pusht nichts (Invariante 5 in [AGENTS.md](AGENTS.md)). 5. **Publish bewegt `VERSION` auf `main`.** ```bash tools/wikitool publish --message "..." ``` Das Mass-Update-Gate und das Publish-Remote-Gate gelten wie bei jedem anderen Publish - siehe [instructions/gates.md](instructions/gates.md). 6. **CI übernimmt den Rest.** `.gitea/workflows/release.yml` reagiert auf jeden Push, der `VERSION` bewegt: Eine suffixbehaftete `VERSION` (ein Kandidat) lässt den Job sauber überspringen, bevor er die Releases-API überhaupt anfragt - Betas werden nie veröffentlicht. Eine suffixfreie `VERSION` baut die Distribution (`dist export`), erzeugt Tag und Release und lädt Tarball und Prüfsumme hoch, dazu die beiden Preflight-Skripte und die Anleitungen `setup-instance.md` und `preflight.md`, auf die der Installationssatz in `INSTALL.md` zeigt. **CI setzt den Tag, nie eine Sitzung** - das hält Invariante 5 intakt. Die drei Verify-Befehle stehen oben in Schritt 3; was jeder von ihnen prüft, steht in [tools/CONTRACT.md](tools/CONTRACT.md) und wird dort von `docs verify` gegen die tatsächliche CLI gehalten. Hier steht es bewusst **nicht** noch einmal: eine zweite Beschreibung derselben Befehle ist genau die Kopie, die driftet (AGENTS.md Invariante 8), und dieses Dokument liegt außerhalb der Dateien, die der Kommando-Datensatz-Check von `docs verify` abdeckt - hier fällt eine Drift also niemandem auf. Was `pytest` an dieser Stelle vom Entwickler erwartet, steht in [instructions/dev/testing-conventions.md](instructions/dev/testing-conventions.md). ## Die CI-Hälfte `.gitea/workflows/ci.yml` läuft auf jeden Push/PR gegen `main` (Content-Pfade ausgenommen) und führt Testsuite, `docs verify`, `instructions verify` sowie einen vollständigen `setup-instance.md`-Replay aus: ein lokal gebauter Release-Tarball, das Preflight-Skript mit `--archive` in einem leeren Verzeichnis, dann die Schritte der Anleitung - derselbe Pfad, den ein neuer Nutzer tatsächlich geht, nur ohne Download. `.gitea/workflows/nightly.yml` ist der Drift-Check gegen die Zeit statt gegen einen Commit. `.gitea/workflows/release.yml` ist Schritt 6 oben. Drei weitere Workflows tragen die Live-Tests der Tracker-Adapter (Super Productivity, CalDAV): `ci.yml` führt in einem eigenen Schritt die CalDAV-Hälfte gegen ein Radicale als Prozess aus, `tracker-live.yml` läuft nachts und deckt beide Anbieter ab, und `sp-live-image.yml` baut täglich (bei neuer Version) und monatlich (immer) das Image `chemenu-sp-live` mit der jeweils aktuellen Super-Productivity-Version. Das Image folgt dem Update-Kanal der Desktop-Clients, nicht einer festen Version. Einmalig nach dem allerersten Push muss das Paket von Hand dem Repo `torben/chemenu` zugeordnet werden. Was die Suite schreibt, wie man sie gegen einen eigenen Tracker laufen lässt und was ein roter Lauf bedeutet, steht in [instructions/dev/tracker-testing.md](instructions/dev/tracker-testing.md). ## Stack-Entwicklung als eigener Sitzungstyp Drei Skills (`instructions/dev/`, nur in diesem Ursprungs-Repo vorhanden) führen eine Sitzung, die den Stack selbst statt Wiki-Inhalt bearbeitet, durch drei Phasen: `stack-dev` arbeitet das Issue aus, bis sein Body „ready“ ist, `stack-build` baut, publiziert und wartet auf einen grünen CI-Lauf, `stack-close` prüft den Endzustand des Bodys und veraltete `docs/`- und Contract-Prosa und schließt das Issue. Übergeben wird über den Zustand im Tracker, nicht über den Kontext einer Sitzung: Jeder Phasenwechsel geht in derselben Sitzung oder nach `/clear`. `stack-dev` greift automatisch; `stack-build` und `stack-close` startet nur der Betreiber per Slash-Kommando (`/stack-build #N`, `/stack-close`) - an genau dieser Stelle fällt die Wahl, ob es in derselben Sitzung weitergeht oder in einer neuen, auf welchem Modell. Einen Modellwechsel mitten in der Sitzung bietet keiner der drei an. Regeln und Phasentabelle stehen in [instructions/dev/stack-mode.md](instructions/dev/stack-mode.md), der Issue-Tracker selbst in [instructions/dev/issue-tracking.md](instructions/dev/issue-tracking.md).