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
10 KiB
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.
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.
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.
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.
- Eine Demo-Persona in
USER.md/SOUL.md.doctormeldet beide als ausgefüllt. Sie beschreiben den Demo-Betrieb, nicht dich. - Telemetrie an. Ohne
.wikitool-release.jsonist der Klon die Messstation, mit der der Stack sich selbst bewertet (EVALS.md § „Whether it runs at all“). instructions/dev/,commonplace/,.gitea/und diese Datei.dist exportliefert 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 <leeres Verzeichnis> 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 <tarball> 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 und docs/version-model.md. Hier nur der Ablauf, in der Reihenfolge, in der eine Sitzung ihn tatsächlich durchläuft:
-
Bump eröffnet oder eskaliert den Kandidaten, gewichtet mit
--impact.tools/wikitool version bump --minor --title "Was sich geändert hat" --impact mediumSchreibt
VERSIONalsX.Y.Z-beta.Nund öffnet (oder aktualisiert) den passendenCHANGES.md-Eintrag. Mehrere Bumps für dieselbe Änderung sind normal - jeder aktualisiert denselben Eintrag, statt einen neuen zu eröffnen.--impact high|medium|low(Defaultmedium) gruppiert den Eintrag;tools/wikitool version regradekorrigiert eine Note später, wenn der Gesamteindruck des Kandidaten den Blick auf einen früheren Bump ändert. -
Der Eintrag bekommt seine Prosa - zweigeteilt.
bumpschreibt 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### <Bump-Titel>-Changeset-Absatz. Details dazu in instructions/dev/version-parts.md § The candidate model. -
Verify laufen lassen, bevor irgendetwas gepublished wird:
cd tools && .venv/bin/python -m pytest -q tools/wikitool docs verify tools/wikitool instructions verify -
version releasefixiert den Kandidaten, sobald er ausgeliefert werden soll:tools/wikitool version release --title "Zusammenfassender Titel"Streicht den
-beta.N-Suffix ausVERSIONund schließt den Changelog-Eintrag.--titleist 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). -
Publish bewegt
VERSIONaufmain.tools/wikitool publish --message "..."Das Mass-Update-Gate und das Publish-Remote-Gate gelten wie bei jedem anderen Publish - siehe instructions/gates.md.
-
CI übernimmt den Rest.
.gitea/workflows/release.ymlreagiert auf jeden Push, derVERSIONbewegt: Eine suffixbehafteteVERSION(ein Kandidat) lässt den Job sauber überspringen, bevor er die Releases-API überhaupt anfragt - Betas werden nie veröffentlicht. Eine suffixfreieVERSIONbaut die Distribution (dist export), erzeugt Tag und Release und lädt Tarball und Prüfsumme hoch, dazu die beiden Preflight-Skripte und die Anleitungensetup-instance.mdundpreflight.md, auf die der Installationssatz inINSTALL.mdzeigt. 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 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.
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.
Stack-Entwicklung als eigener Sitzungstyp
Der stack-dev-Skill (instructions/dev/, nur in diesem Ursprungs-Repo vorhanden) fasst die
Regeln für eine Sitzung, die den Stack selbst statt Wiki-Inhalt bearbeitet: wann
Quellenbindung nicht gilt, wo Design endet und die mechanische Phase beginnt (mit dem
Modellwechsel-Hinweis), und endet mit dem Publish. Die Schlussphase - Issue-Body als Rewrite
statt Kommentar, docs/-Veralterung, die Modell-Handover-Zeile über die ganze Sitzung - liegt
seit 4.6.0 in einem eigenen Folge-Skill, stack-close, den stack-dev an dieser Stelle
übergibt statt sie als weiteren eigenen Schritt zu führen. Siehe
instructions/dev/issue-tracking.md für den
Issue-Tracker selbst.