-
v2.2.0 Stable
released this
2026-09-01 16:09:37 +00:00 | 105 commits to main since this release2.2.0 - 2026-09-01 - Publish-Remote Gate: publish schreibt nur an erklaerte Ziele
Author: Torben Nehmer
Der Stack bekommt sein drittes Gate. Die beiden bestehenden fragen, ob eine Änderung zu groß
ist und ob ein Rebase gefährlich ist. Dieses fragt, was darunter liegt: ob das überhaupt das
richtige Repository ist.Das Problem entsteht erst durch die private Instanz. Ein Checkout mit eigenem Inhalt hat
typischerweise zwei Remotes — sein eigenes und das öffentliche Upstream, von dem er
Stack-Updates zieht. Git unterscheidet die beim Push nicht, also legt ein falsches--remote
einen privaten Korpus auf ein öffentliches Repository. Das ist nicht billig rückholbar, und
zwar nachweislich: Beim Veröffentlichen dieses Repos blieb die gesamte alte History nach dem
Force-Push per SHA abrufbar, bis auf dem Server die Reflogs verfielen undgit gc --prune=now
lief. Ein Force-Push bewegt den Branch, nicht die Objekte..wikitool-remotes.jsonnennt die erlaubten Push-URLs. Nicht die Remote-Namen: Eine
Namensliste ließe einpublishdurch, dessenoriginumgebogen wurde, und genau das ist der
Fall, den das Gate fangen soll. Gelesen wird diepushurl, wenn der Remote eine setzt, denn
dorthin schreibtgit pushtatsächlich.Pro Checkout und gitignored, aus demselben Grund wie
ENVIRONMENT.md: Zwei Klone pushen an
zwei verschiedene Orte, eine committete Kopie würde einem privaten Klon also mitteilen, das
öffentliche Upstream sei ein legitimes Ziel für seinen eigenen Inhalt. Fehlt die Datei, gilt
keine Beschränkung — ein Checkout mit einem Remote und ohne Privates hat nichts zu schützen,
und eine Pflichtdatei würde aus einer Sicherung Papierkram machen. Eine kaputte Datei ist
dagegen ein Fehler und kein „keine Beschränkung": Eine beschädigte Sicherung darf sich nicht
wie eine abgeschaltete verhalten.Kein Token, keine Flagge. Die anderen beiden Gates lösen sich mit einem
--confirm <token>,
weil ihre Frage („ist diese Änderung richtig?") für genau ein Changeset beantwortbar ist. Dieses
fragt „gehört dieser Inhalt in jenes Repository?", und das ist eine stehende Eigenschaft des
Checkouts, kein Einzelfallurteil. Der Weg daran vorbei ist ein bewusster Edit des Nutzers.
Ein Agent, der die Datei anfasst, um an einer Verweigerung vorbeizukommen, öffnet ein Gate aus
eigenem Antrieb — Invariante 6.doctormeldet den Zustand statt ihn zu erzwingen: OK mit Anzahl der Ziele, OK bei
Abwesenheit mit einem Remote, und WARN bei mehr als einem Remote ohne Allowlist — also genau in
der Form, die eine private Instanz annimmt, sobald sie das Upstream hinzufügt.Und die Prozedur, für die das Gate gebaut wurde.
instructions/private-instance.md(neu)
beschreibt die dritte Instanz-Form neben „frisch aufsetzen" und „Repo klonen": eine private
Arbeitsinstanz, die Stack-Updates von einem öffentlichen Upstream pergit mergezieht und
deren eigener Inhalt nie zurückwandert. Der Grund, warum das dem Tarball-Weg vorzuziehen ist,
steht dort ausformuliert —cp -rhat keinen Drei-Wege-Merge und keine Konflikterkennung.
Schritt 4 der Anleitung ist das Gate, und zwar ausdrücklich vor dem erstenpublish:
später hinzugefügt schützt es das Fenster nicht, das es schließen soll.Dateien:
config.PUBLISH_REMOTES_FILENAME,git_publish.read_allowed_push_urls(),
push_url_for(),publish_remote_refusal()und die Prüfung vor dem Reconcile-Schritt,
doctor.check_publish_remotes(),.gitignore,instructions/gates.md,
instructions/private-instance.md(neu),AGENTS.md(Gate-Liste und Bootstrap-Routing),
12 neue Tests intest_git_publish.py.Downloads