Version-Bump von Release entkoppeln: laufender Kandidat mit Eskalation, Pre-Release-Beta-Semantik #42
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Befund
Heute bekommt jeder
wikitool version bumpsofort eine fixierte, dauerhafte Versionsnummer, unabhängig davon, ob je ein Release dazu erscheint. Fünf Minor-Bumps hintereinander ohne Release ergeben fünf verschiedene Nummern, von denen die älteren vier nie ausgeliefert wurden — Nummern werden verbraucht, ohne dass ein Release sie eingelöst hätte. Messbar: 66 Einträge inCHANGES.md,4.3.3nach vier Tagen; allein die Sitzung vom 2026-09-03 hat zwei Releases für zwei Prosa-Änderungen erzeugt.Verschärft wird das durch das Version-Gate in
ci.yml: jeder Push, der Stack-Pfade berührt, mussVERSIONbewegen. Nummern werden damit in Commit-Granularität verbraucht, nicht in Release-Granularität.Entscheidungen
Betreiber, 2026-09-02 — das Modell:
-beta.n.Betreiber, 2026-09-03 — die vier offenen Mechanikfragen:
VERSIONträgt den Suffix selbst (4.4.0-beta.3). Kein neues Zustandsfile. Der letzte Release ist der neueste suffixfreie##-Eintrag inCHANGES.md; die Eskalationsstufe ist die Differenz zwischen Kandidatenbasis und letztem Release, also abgeleitet statt gespeichert. Damit behält CIs Version-Gate seinen Anker („VERSION hat sich bewegt") undversion showsagt weiter, was tatsächlich installiert ist.bump-Aufruf. Der Aufrufer deklariert weiterhin--patch/--minor/--majorals Urteil;version-parts.mdbleibt die Autorität dafür. Der Kandidat nimmt das Maximum gegen den letzten Release. Keine Klassifikation aus Commits oder Diff —version.pyverwirft das im Modul-Docstring bereits mit dem richtigen Grund:publishschreibt Content-Commits in dasselbe Repo, jeder Ingest würde als Release gelesen.release.ymlfeuert nur bei suffixfreierVERSION. Folge, die die Versionsstelle dieser Änderung trägt: eine ausgelieferte Instanz sieht nie ein Beta, also trifft ihr Parser nie eineVERSION-Form, die er nicht kennt.## X.Y.Z-beta.n - <datum> - <titel>; jeder Bump aktualisiert Version und Datum und hängt seinen--titlean eine maschinenverwaltete Liste am Kopf des Eintrags. Die Prosa darunter bleibt Autorenarbeit.version notesdruckt damit genau einen Eintrag pro Release.Betreiber, 2026-09-03 (Nachtrag) — Menschendoku: der Release-Vorgang bekommt eine
DEVELOPMENT.mdim Repo-Root. Heute gibt es für die Erzeuger-Seite keine Menschendoku:INSTALL.mdbeschreibt nur, wie man ein Release konsumiert,README.mderwähnt Releases mit keinem Wort, und der Ablauf ist nur aus einem Agenten-Skill plus einer Workflow-Datei zusammenzulesen. Die Doku fährt in diesem Issue mit statt vorher, weil sich der Ablauf hier ändert — vorher geschrieben würde sie einen Prozess beschreiben, den es nach dieser Umsetzung nicht mehr gibt.Die Mechanik konkret
VERSIONhält entweder eine Release-VersionX.Y.Z(direkt nach einem Release) oder einen KandidatenX.Y.Z-beta.n.version bump --patch|--minor|--major --title "…":R(neuester suffixfreier Changelog-Eintrag) und den aktuellenVERSION-Stand.s= die Stelle, um die die Kandidatenbasis überRhinausgeht; keine, wennVERSION == R.max(s, angeforderte Stufe)in der Ordnung patch < minor < major.R.bumped(neue Stufe).n= altesn+ 1, bzw. 1 bei einem frisch eröffneten Kandidaten.VERSION, aktualisiert Heading und Titelliste des offenen Eintrags — oder legt den Eintrag an.Randfall ohne letzten Release: eine frische Distribution hat einen Changelog ohne versionierten Eintrag (
top_changes_versionliefert dort heute schonNone, und das ist ein gültiger Zustand). Dann gibt es keinR; die Kandidatenbasis istVERSION.bumped(angeforderte Stufe)und die Eskalation startet bei dieser Stufe. Nicht als Fehler behandeln.Die Eskalation ist monoton: nie automatisch zurück. Ein zurückgenommener Umfang senkt den Kandidaten nicht (siehe „Nicht in diesem Issue").
version release [--title "…"] [--dry-run]fixiert: streicht den Suffix ausVERSIONund setzt das Heading auf## X.Y.Z - <heute> - <titel>. Woher der Titel kommt: ohne--titlebleibt der Titel stehen, den der letzte Bump gesetzt hat; mit--titlewird er ersetzt. Das ist der Normalfall und kein Luxus — ein Kandidat hat mehrere Bumps mit je eigenem Titel gesammelt, und der Release will eine zusammenfassende Überschrift statt der zufällig letzten. Committet nicht und pusht nicht (Invariante 5) — der anschließendepublishbewegtVERSIONaufmainund löstrelease.ymlaus. Der nächstebumperöffnet dann einen neuen Eintrag, weil der oberste suffixfrei ist; dafür ist kein weiterer Zustand nötig.Was das an bestehendem Code bricht
Vier Stellen, die das neue Modell still beschädigen würde. Sie sind der eigentliche Umfang dieses Issues, nicht die Suffix-Arithmetik.
.gitea/workflows/release.ymlpaths: [VERSION]aufmain. Unter dem neuen Modell feuert das bei jedem Bump und veröffentlicht Betas.VERSIONeinen Suffix, endet der Job sauber (Skip, kein Fail). Die Reihenfolge ist nicht kosmetisch — die bestehendereleases/tags/-Abfrage würde sonst für jeden Beta-Bump eine Runde gegen die API drehen.docs_verify.check_breaking_change_for_boundary/check_migration_for_boundarycompat_keydes obersten mit dem des zweitobersten Eintrags. Zwischen4.4.0-beta.2und4.4.0-beta.1liegt keine Grenze — der Breaking-Change-Zwang wäre faktisch abgeschaltet.kb_state.chain()/next_link()4.4.0-beta.1 < 4.4.0, also fällt eine Migration mit Ziel4.4.0aus dem Intervall(kb_version, stack_version]. Die Instanz hat die Maschinerie und bekommt die Migration nicht angesagt.read_kb_version()verweigert einen Prerelease: eine Inhaltsform hat kein Beta.version_cmd.bump_command,--breaking/--no-migrationversion-parts.mdSchritt 4 (Gespräch mit dem Betreiber vor einem Grenzübertritt) gilt ab jetzt an genau diesem Punkt.Nicht betroffen, geprüft: das Version-Gate in
ci.ymlbleibt gültig, weilVERSIONbei jedem Bump durchn+1weiterhin wandert. Das ist beabsichtigt und soll so bleiben. Auchversion releasepassiert das Gate — es prüft nur „Stack-Pfad ohne VERSION-Bewegung", nicht die Gegenrichtung.Umsetzungsplan
Alle neun Schritte umgesetzt:
version.py(Datentyp/Ordnung, Kandidatenlogik),version_cmd.py(bumpumgestellt,releaseneu),docs_verify.py/kb_state.py/dist_cmd.py/doctor.py(alle vier Funde behoben),release.yml-Guard, Agenten-Doku (version-parts.mdmit neuem Abschnitt „The candidate model" und angepassten Schritten 4–8,tools/CONTRACT.md,CHANGES.md-Kopf,docs/version-model.md),DEVELOPMENT.mdneu, Version-Bump dieser Änderung selbst.Tests
Gilt
instructions/dev/testing-conventions.md. Alle Fälle aus der ursprünglichen Testliste (Ordnung inkl. numerischem Beta-Vergleich, max-wins-Eskalation, Randfall ohne letzten Release,--breaking-Persistenz über Folgebumps, beide Regressionen für Fund 2 und 3,version releasemit/ohne--title,version notesfür einen Kandidaten) haben einen Test intest_version_cmd.py,test_docs_verify.py,test_migrate_cmd.pyundtest_doctor.py. Derrelease.yml-Guard bleibt wie geplant ungetestet (Shell in CI).Akzeptanzkriterien
Versionversteht-beta.n: Parsing, totale Ordnung,base,compat_keyüber die Basis. Tests dafür.version bumpführt einen laufenden Kandidaten mit max-wins-Eskalation gegen den letzten Release;nzählt pro Bump. Tests dafür, inklusive Randfall ohne letzten Release.CHANGES.mdträgt genau einen offenen Eintrag pro Kandidat, mit maschinenverwalteter Titelliste in<!-- wikitool:bumps -->-Markern.version releasefixiert die Nummer, beendet die Pre-Release-Phase, committet nichts, und behandelt--titlewie oben beschrieben. Test dafür.release.ymlüberspringt eine Kandidaten-VERSIONsauber, vor der API-Abfrage.docs verifymessen gegen den letzten Release. Regressionstest.kb_versionrechnen gegen die Kandidatenbasis. Regressionstest.--breaking/--no-migrationgreifen am Eskalationsbump und bleiben über Folgebumps erhalten.tools/CONTRACT.md: Zeile fürversion releasein Kommandotabelle und Fehlerkontrakt.instructions/dev/version-parts.md,CHANGES.md-Kopf unddocs/version-model.mdbeschreiben die neue Semantik.DEVELOPMENT.mdexistiert, beschreibt den Release-Ablauf unter dem neuen Modell, ist bewusst nicht indist_cmd.ROOT_FILES(mit Begründung im Code), hat eine Zeile inAGENTS.md§ File naming und einen Zeiger ausREADME.md.4.3.3→4.4.0-beta.1→version release→4.4.0. Changelog-Eintrag geschrieben.docs verify,instructions verify,pytestgrün; CI grün inklusive dist-export-Replay.Umsetzung und Ausrollen (Stand 2026-09-03, abgeschlossen)
Vollständig umgesetzt, gepublisht, verifiziert. Publish freigegeben durch den Betreiber (Mass-Update Gate, 21 Dateien, Token
815a67d6a9fd), Commitd29d400auforigin/main. Verifiziert:ci.yml, Run #91,verify):success- volle Testsuite,docs verify,instructions verify,dist export-Replay gegen eine frische Instanz, alles grün gegen den gepushten Stand.release.yml, Run #92,release):success-VERSIONwar beim Push bereits release-fixiert (4.4.0, kein Suffix mehr), der Guard aus Fund 1 hat den Job also nicht übersprungen, sondern regulär durchlaufen lassen.Damit ist der komplette Ablauf einmal live durchlaufen: Bump → Prosa → Verify →
version release→ Publish (mit Gate-Freigabe) → CI → Release.Nachspiel, gleicher Tag: die gesamte Prosa dieser Umsetzung entstand ohne den Modellwechsel, den
stack-devSchritt 6 dafür vorsieht — der Break wurde übersprungen. Ein nachgeholter Durchgang (4.4.1-beta.1) hat darin einen echten Faktenfehler gefunden, der sowohl im Changelog als auch indocs/version-model.mdstand (siehe Nachtrag ganz oben), dazu eine veraltete2.x-Angabe inversion-parts.mdund eine überflüssige Kommandotabelle inDEVELOPMENT.md. Der Prozessfehler dahinter ist #47.Abhängigkeiten
#7 (
wikitool dist upgrade) warstatus/blockedauf dieses Issue. Die Kopplung ist nach Fund 3 enger als ursprünglich notiert: sowohl die Drei-Wege-Klassifikation in #7 als auch die Migrationskette hängen daran, dass ein Prerelease auf seine Basis zurückgeführt wird, bevor verglichen wird. Dieses Issue ist erledigt, #7 ist entsperrt.Nicht in diesem Issue
prio/waiting, Auslöser ist die PR-Einführung.Vorgeschichte
Modell entschieden in der Diskussion vom 2026-09-02, im Rahmen der Aufarbeitung von #38, #30, #28, #7, #27 als Fallouts des Entwicklungsprozesses. Siehe auch #41 (Issue-Management), das denselben Sitzungsblock eröffnet hat. Die vier Mechanikfragen und die vier Funde am bestehenden Code stammen vom 2026-09-03; die
DEVELOPMENT.md-Anforderung und die Bereitschaftsprüfung vom selben Tag, nach dem Landen von 4.3.2 und 4.3.3. Umsetzung, Publish und Release ebenfalls vom 2026-09-03, im direkten Anschluss.torben referenced this issue2026-09-02 21:07:39 +00:00
torben referenced this issue2026-09-03 04:33:45 +00:00
Update 2026-09-03: #39/#40 sind gelandet, ohne direkten Einfluss auf die hier offenen Mechanik-Fragen (Zustandsort, Eskalationsberechnung, Pre-Release-Vergleichslogik). Position in der Reihenfolge unverändert: nach #28/#38, vor #30/#7 - #7 hängt direkt an diesem Issue.
Changelog: Body von Befund+offenen Fragen auf einen umsetzbaren Plan umgeschrieben.
Neu: alle vier offenen Mechanikfragen entschieden (VERSION trägt den Suffix, max-wins pro Bump-Aufruf, Betas werden nie veröffentlicht, ein offener Changelog-Eintrag pro Kandidat), dazu die konkrete Bump-Arithmetik, ein achtstufiger Umsetzungsplan mit bindender Reihenfolge, eine Testliste und ein Abschnitt „Nicht in diesem Issue".
Vier Funde am bestehenden Code ergänzt, die vorher in keiner Anforderung standen:
release.ymlwürde unter dem neuen Modell bei jedem Bump feuern und Betas veröffentlichen; die beiden Grenzübertritts-Checks indocs verifyvergleichen den obersten mit dem zweitobersten Eintrag und wären zwischen zwei Betas faktisch abgeschaltet;kb_state.chain()lässt eine Migration mit Ziel4.4.0bei installiertem4.4.0-beta.1aus dem Intervall fallen;--breaking/--no-migrationhaben unter Eskalation keinen festen Zeitpunkt mehr. Fund 2 und 3 sind Regressionstests im Akzeptanzkriterienblock.Alte Abschnitte „Offene Punkte" und die Kurzform der Akzeptanzkriterien entfallen — ersetzt durch Entscheidungen, Plan und die neue, geschnittene Kriterienliste. Release-Drafter-Recherche ist kein Kriterium mehr, sondern explizit zurückgestellt (Trigger: PR-Einführung), noch ohne eigenes Issue.
kind/decision→kind/build: die offenen Entscheidungen sind getroffen, es fehlt nur noch Umsetzungszeit.prio/plannedundsize/Lunverändert.Changelog:
DEVELOPMENT.mdals Anforderung aufgenommen, Bereitschaftsprüfung durchgeführt, drei dabei gefundene Lücken geschlossen.Neu als Plan-Schritt 8 und Akzeptanzkriterium:
DEVELOPMENT.mdim Repo-Root für die Erzeuger-Seite des Release-Vorgangs — mit den vier Nebenbedingungen (bewusst nicht indist_cmd.ROOT_FILES, Begründung im Code; darf deshalb nachinstructions/dev/verlinken; Zeile inAGENTS.md§ File naming; Zeiger ausREADME.md). Alter Schritt 8 ist jetzt 9.Bei der Bereitschaftsprüfung aufgefallen und ergänzt:
<!-- wikitool:<name> -->ausblocks.py, mit der ausdrücklichen Auflage,blocks.BLOCKSnicht zu erweitern — dessen Namen speisenxref,citeund den Lint-Checkunbalanced_markers, undCHANGES.mdist keine Seite.version releasefehlte. Ein Kandidat sammelt mehrere Bump-Titel; welcher im Release-Heading landet, stand nirgends. Jetzt:--titleoptional, ohne ihn bleibt der letzte Bump-Titel stehen.Kleinere Präzisierungen: Guard in
release.ymlmuss vor die API-Abfrage (sonst dreht jeder Beta-Bump eine Runde gegen die API); Ordnungstestbeta.9 < beta.10ergänzt (numerisch, nicht lexikografisch);version releasepassiert das CI-Version-Gate, geprüft.Neuer Abschnitt „Bereitschaft": umsetzungsbereit, Body ist die vollständige Übergabe für eine frische Sitzung. Empfehlung zur Sitzungsführung ergänzt — Design ist erledigt, also direkt in der mechanischen Phase starten (Sonnet/high nach 4.3.3).
Changelog: Umsetzung abgeschlossen, alle Akzeptanzkriterien erfüllt und angehakt.
Umgesetzt wie geplant:
Versionmit-beta.n,escalate()(max-wins),version bump/version releaseauf dem neuen Modell, alle vier Funde am Bestand behoben (inkl. Regressionstests),release.yml-Guard,DEVELOPMENT.mdneu,docs/version-model.mdundinstructions/dev/version-parts.mderweitert,tools/CONTRACT.mdergänzt. Version-Bump dieser Änderung:4.3.3→4.4.0-beta.1→version release→4.4.0.Neuer Abschnitt „Umsetzung" ersetzt „Bereitschaft": Stand ist implementiert und lokal grün (pytest,
docs verify,instructions verify, ein manuellerdist export), aber noch nicht gepusht -publishbraucht die ausdrückliche Freigabe des Betreibers. Issue bleibt deshalb offen, bis das passiert ist und CI durchgelaufen ist.Changelog: Publish freigegeben und durchgelaufen, CI und Release grün, Issue schließt.
CI (
ci.ymlRun #91) und Release (release.ymlRun #92) beidesuccessgegen Commitd29d400. v4.4.0 ist veröffentlicht. Abschnitt „Bereitschaft"/„Umsetzung" durch „Umsetzung und Ausrollen" ersetzt, mit den Run-Links und dem Release-Nachweis. #7 als entsperrt vermerkt.