Beim Einrichten einer frischen 5.0.0-Instanz aus dem Release-Tarball (Weg A aus INSTALL.md) verweigerte Schritt 14 aus instructions/setup-instance.md den ersten Commit:
$ tools/wikitool publish --message "chore: initial instance setup"
ERROR Refusing to push `main` from a detached HEAD. Check out a branch first - pushing a
named ref from a detached HEAD would publish something other than the commit just made.
$ echo $?
1
HEAD war dabei nicht detached, sondern ein ungeborener Branch (git symbolic-ref HEAD -> refs/heads/main, git status -sb -> ## No commits yet on main).
Betroffene Version: 5.0.0. Behoben in 5.0.1-beta.1, Commit 9ef021b.
Warum das zählt
instructions/setup-instance.md Schritt 14 und INSTALL.md (Weg A und B) nennen publish --message als den Weg zum ersten Commit einer neuen Instanz, und doctor sagt an derselben Stelle fix: Make the first commit via publish once ready. Genau dieser dokumentierte Befehl schlug fehl - bei jeder neuen Instanz, beim ersten schreibenden wikitool-Aufruf überhaupt. Invariante 5 schnitt den naheliegenden Ausweg ab: ein Agent darf nicht auf git commit von Hand ausweichen. Zusammen mit #97 hieß das: eine neue Instanz mit leerem Remote ließ sich mit 5.0.0 über keinen dokumentierten Weg initial veröffentlichen.
Ursache - verifiziert
Die ursprüngliche Vermutung traf zu. current_branch() fragte git rev-parse --abbrev-ref HEAD; auf einem ungeborenen Branch endet der Aufruf mit Exit 128 ("ambiguous argument 'HEAD': unknown revision") und fiel damit in denselben None-Zweig wie ein echter detached HEAD. branch_mismatch_message() formulierte daraus die detached-HEAD-Ablehnung, publish_command() brach damit ab.
Gemessen in einem frisch initialisierten Repo:
Zustand
rev-parse --abbrev-ref HEAD
symbolic-ref --short -q HEAD
Ungeborener Branch (git init -b main)
rc 128, stdout HEAD
rc 0, stdout main
Echter detached HEAD (git checkout <sha>)
rc 0, stdout HEAD
rc 1, stdout leer
Normaler Checkout
rc 0, stdout main
rc 0, stdout main
symbolic-ref unterscheidet die beiden Zustände genau dort, wo rev-parse sie zusammenwirft, und liefert im dritten Fall dasselbe.
Entscheidung und Umsetzung
Frage 1 (trifft die Ableitung zu?) - ja, siehe Tabelle.
Frage 2 (soll die Prüfung im ungeborenen Fall greifen?) - nein, und mit der gewählten Umsetzung stellte sie sich nicht mehr. Das Motiv der Prüfung (git push <remote> <branch> pusht den benannten Ref, nicht HEAD) existiert im ungeborenen Fall nicht: es gibt genau einen Branch, der Commit entsteht auf ihm, origin hat den Ref noch gar nicht. Die Prüfung wurde deshalb nicht ausgesetzt, sondern korrekt beantwortet: current_branch() liefert auf ungeborenem main jetzt "main", der Vergleich checked_out != branch geht von selbst durch. Ein Sonderfall im Aufrufer entfiel.
Umgesetzt:current_branch() liest git symbolic-ref --short -q HEAD statt git rev-parse --abbrev-ref HEAD; leere Ausgabe oder rc != 0 bleibt None (= detached HEAD). Der Docstring hält fest, warum symbolic-ref und nicht rev-parse - dass es liest, was HEADbenennt, statt worauf es zeigt.
Blast radius, wie erwartet klein:current_branch() hat genau einen Aufrufer, die Branch-Prüfung in publish_command(). Der restliche Publish-Pfad trug den ungeborenen Fall bereits: _numstat() dokumentiert ihn ausdrücklich und liefert {}, _changed_files() liest git status --porcelain, das ohne Commit funktioniert, und reconcile() fällt gegen ein leeres Remote auf no-remote-or-fetch-failed zurück. Es war keine weitere Anpassung nötig.
Akzeptanzkriterien
In einem Repo nach git init -b main ohne jeden Commit legt tools/wikitool publish --message "<text>" den Commit auf main an und pusht ihn nach origin/main - ohne --no-push und ohne handgemachtes git commit. Test: test_publish_makes_the_first_commit_of_a_new_instance.
Ein echter detached HEAD wird weiterhin mit der bisherigen Begründung abgelehnt. branch_mismatch_message() blieb unverändert; es änderte sich nur, welcher Zustand None erzeugt. Test: test_current_branch_still_reports_a_real_detached_head_as_none.
Ein Push auf einen anderen als den ausgecheckten Branch wird weiterhin abgelehnt, mit unverändertem --branch-Hinweis, auch auf einem ungeborenen Branch. Test: test_publish_on_an_unborn_branch_still_refuses_a_different_target_branch.
Das Mass-Update-Gate verhält sich im ungeborenen Fall unverändert: Exit 42 mit Token, und vor dem Gate wird nichts gestaged - geprüft inklusive "Branch weiterhin ungeboren, Remote weiterhin leer". Test: test_the_gate_still_holds_on_a_fresh_instance_and_stages_nothing.
tools/chemenu/tests/test_git_publish.py trägt je einen Test für den ungeborenen Branch und den echten detached HEAD. Umgesetzt über ein eigenes fresh_instance-Fixture (ungeborener Branch, leeres bare-Remote, kein Commit) - der repo-Fixture taugte wie erwartet nicht, weil er einen Init-Commit anlegt und pusht.
Doku zieht nach. tools/CONTRACT.md benennt die Branch-Prüfung jetzt in der publish-Kommandozeile und als eigenständigen Exit-1-Grund im Fehlerkontrakt, jeweils mit dem ungeborenen Branch als ausdrücklicher Ausnahme. instructions/setup-instance.md Schritt 2 und 14 sowie INSTALL.md blieben unverändert: geprüft und inhaltlich richtig - sie beschrieben nie den Workaround, sondern den Weg, der jetzt tatsächlich funktioniert. --no-push musste beim ersten Commit folglich nicht erwähnt werden.
Verifikation
pytest in tools/: 1204 Tests grün, davon 96 in test_git_publish.py.
Gegenprobe, dass die neuen Tests echte Regressionstests sind: mit zurückgedrehtem Fix scheitern genau die vier verhaltensprüfenden Tests aus #96/#97 (test_current_branch_names_an_unborn_branch_rather_than_calling_it_detached, test_publish_makes_the_first_commit_of_a_new_instance, test_the_gate_still_holds_on_a_fresh_instance_and_stages_nothing, test_publish_pushes_a_committed_stand_to_a_remote_that_has_no_branch_yet); die Schutztests bestehen erwartungsgemäß in beide Richtungen.
Leere-Maschine-Lauf nach instructions/dev/testing-conventions.md Schritt 6 (env -i ohne HOME/Git-Config): identisches Ergebnis, 1204 grün - kein Leck über die Umgebung.
tools/wikitool docs verify und tools/wikitool instructions verify: beide OK.
Gemeinsam umgesetzt, ein Commit (9ef021b), ein Version-Bump (--patch, 5.0.0 -> 5.0.1-beta.1): verschiedene Funktionen und Ursachen, aber dieselbe Datei, dieselbe Testdatei, dieselbe Doku-Zeile, und die Kette ließ sich erst gemeinsam als Ganzes testen. --patch war die richtige Stufe - reine Fehlerbehebung, keine Schnittstellenänderung, in beide Richtungen drop-in.
## Befund
Beim Einrichten einer frischen 5.0.0-Instanz aus dem Release-Tarball (Weg A aus `INSTALL.md`) verweigerte Schritt 14 aus `instructions/setup-instance.md` den ersten Commit:
```
$ tools/wikitool publish --message "chore: initial instance setup"
ERROR Refusing to push `main` from a detached HEAD. Check out a branch first - pushing a
named ref from a detached HEAD would publish something other than the commit just made.
$ echo $?
1
```
HEAD war dabei nicht detached, sondern ein ungeborener Branch (`git symbolic-ref HEAD` -> `refs/heads/main`, `git status -sb` -> `## No commits yet on main`).
Betroffene Version: 5.0.0. Behoben in **5.0.1-beta.1**, Commit `9ef021b`.
## Warum das zählt
`instructions/setup-instance.md` Schritt 14 und `INSTALL.md` (Weg A und B) nennen `publish --message` als *den* Weg zum ersten Commit einer neuen Instanz, und `doctor` sagt an derselben Stelle `fix: Make the first commit via publish once ready`. Genau dieser dokumentierte Befehl schlug fehl - bei jeder neuen Instanz, beim ersten schreibenden `wikitool`-Aufruf überhaupt. Invariante 5 schnitt den naheliegenden Ausweg ab: ein Agent darf nicht auf `git commit` von Hand ausweichen. Zusammen mit #97 hieß das: eine neue Instanz mit leerem Remote ließ sich mit 5.0.0 über keinen dokumentierten Weg initial veröffentlichen.
## Ursache - verifiziert
Die ursprüngliche Vermutung traf zu. `current_branch()` fragte `git rev-parse --abbrev-ref HEAD`; auf einem ungeborenen Branch endet der Aufruf mit **Exit 128** ("ambiguous argument 'HEAD': unknown revision") und fiel damit in denselben `None`-Zweig wie ein echter detached HEAD. `branch_mismatch_message()` formulierte daraus die detached-HEAD-Ablehnung, `publish_command()` brach damit ab.
Gemessen in einem frisch initialisierten Repo:
| Zustand | `rev-parse --abbrev-ref HEAD` | `symbolic-ref --short -q HEAD` |
|---|---|---|
| Ungeborener Branch (`git init -b main`) | rc 128, stdout `HEAD` | rc 0, stdout `main` |
| Echter detached HEAD (`git checkout <sha>`) | rc 0, stdout `HEAD` | rc 1, stdout leer |
| Normaler Checkout | rc 0, stdout `main` | rc 0, stdout `main` |
`symbolic-ref` unterscheidet die beiden Zustände genau dort, wo `rev-parse` sie zusammenwirft, und liefert im dritten Fall dasselbe.
## Entscheidung und Umsetzung
**Frage 1** (trifft die Ableitung zu?) - ja, siehe Tabelle.
**Frage 2** (soll die Prüfung im ungeborenen Fall greifen?) - **nein, und mit der gewählten Umsetzung stellte sie sich nicht mehr.** Das Motiv der Prüfung (`git push <remote> <branch>` pusht den *benannten Ref*, nicht `HEAD`) existiert im ungeborenen Fall nicht: es gibt genau einen Branch, der Commit entsteht auf ihm, `origin` hat den Ref noch gar nicht. Die Prüfung wurde deshalb nicht *ausgesetzt*, sondern **korrekt beantwortet**: `current_branch()` liefert auf ungeborenem `main` jetzt `"main"`, der Vergleich `checked_out != branch` geht von selbst durch. Ein Sonderfall im Aufrufer entfiel.
**Umgesetzt:** `current_branch()` liest `git symbolic-ref --short -q HEAD` statt `git rev-parse --abbrev-ref HEAD`; leere Ausgabe oder rc != 0 bleibt `None` (= detached HEAD). Der Docstring hält fest, warum `symbolic-ref` und nicht `rev-parse` - dass es liest, was `HEAD` *benennt*, statt worauf es zeigt.
**Blast radius, wie erwartet klein:** `current_branch()` hat genau einen Aufrufer, die Branch-Prüfung in `publish_command()`. Der restliche Publish-Pfad trug den ungeborenen Fall bereits: `_numstat()` dokumentiert ihn ausdrücklich und liefert `{}`, `_changed_files()` liest `git status --porcelain`, das ohne Commit funktioniert, und `reconcile()` fällt gegen ein leeres Remote auf `no-remote-or-fetch-failed` zurück. Es war keine weitere Anpassung nötig.
## Akzeptanzkriterien
- [x] In einem Repo nach `git init -b main` ohne jeden Commit legt `tools/wikitool publish --message "<text>"` den Commit auf `main` an und pusht ihn nach `origin/main` - ohne `--no-push` und ohne handgemachtes `git commit`. Test: `test_publish_makes_the_first_commit_of_a_new_instance`.
- [x] Ein echter detached HEAD wird weiterhin mit der bisherigen Begründung abgelehnt. `branch_mismatch_message()` blieb unverändert; es änderte sich nur, welcher Zustand `None` erzeugt. Test: `test_current_branch_still_reports_a_real_detached_head_as_none`.
- [x] Ein Push auf einen anderen als den ausgecheckten Branch wird weiterhin abgelehnt, mit unverändertem `--branch`-Hinweis, auch auf einem ungeborenen Branch. Test: `test_publish_on_an_unborn_branch_still_refuses_a_different_target_branch`.
- [x] Das Mass-Update-Gate verhält sich im ungeborenen Fall unverändert: Exit 42 mit Token, und vor dem Gate wird nichts gestaged - geprüft inklusive "Branch weiterhin ungeboren, Remote weiterhin leer". Test: `test_the_gate_still_holds_on_a_fresh_instance_and_stages_nothing`.
- [x] `tools/chemenu/tests/test_git_publish.py` trägt je einen Test für den ungeborenen Branch und den echten detached HEAD. Umgesetzt über ein eigenes `fresh_instance`-Fixture (ungeborener Branch, leeres bare-Remote, kein Commit) - der `repo`-Fixture taugte wie erwartet nicht, weil er einen Init-Commit anlegt und pusht.
- [x] Doku zieht nach. `tools/CONTRACT.md` benennt die Branch-Prüfung jetzt in der `publish`-Kommandozeile *und* als eigenständigen Exit-1-Grund im Fehlerkontrakt, jeweils mit dem ungeborenen Branch als ausdrücklicher Ausnahme. `instructions/setup-instance.md` Schritt 2 und 14 sowie `INSTALL.md` blieben unverändert: geprüft und inhaltlich richtig - sie beschrieben nie den Workaround, sondern den Weg, der jetzt tatsächlich funktioniert. `--no-push` musste beim ersten Commit folglich nicht erwähnt werden.
## Verifikation
- `pytest` in `tools/`: 1204 Tests grün, davon 96 in `test_git_publish.py`.
- Gegenprobe, dass die neuen Tests echte Regressionstests sind: mit zurückgedrehtem Fix scheitern genau die vier verhaltensprüfenden Tests aus #96/#97 (`test_current_branch_names_an_unborn_branch_rather_than_calling_it_detached`, `test_publish_makes_the_first_commit_of_a_new_instance`, `test_the_gate_still_holds_on_a_fresh_instance_and_stages_nothing`, `test_publish_pushes_a_committed_stand_to_a_remote_that_has_no_branch_yet`); die Schutztests bestehen erwartungsgemäß in beide Richtungen.
- Leere-Maschine-Lauf nach `instructions/dev/testing-conventions.md` Schritt 6 (`env -i` ohne HOME/Git-Config): identisches Ergebnis, 1204 grün - kein Leck über die Umgebung.
- `tools/wikitool docs verify` und `tools/wikitool instructions verify`: beide OK.
## Beteiligte Dateien
- `tools/chemenu/commands/git_publish.py` - `current_branch()`
- `tools/chemenu/tests/test_git_publish.py` - `fresh_instance`-Fixture, `_remote_log()`, vier Tests
- `tools/CONTRACT.md` - `publish`-Kommandozeile und Fehlerkontrakt-Zeile
## Beziehung zu #97
Gemeinsam umgesetzt, ein Commit (`9ef021b`), ein Version-Bump (`--patch`, 5.0.0 -> 5.0.1-beta.1): verschiedene Funktionen und Ursachen, aber dieselbe Datei, dieselbe Testdatei, dieselbe Doku-Zeile, und die Kette ließ sich erst gemeinsam als Ganzes testen. `--patch` war die richtige Stufe - reine Fehlerbehebung, keine Schnittstellenänderung, in beide Richtungen drop-in.
Der --no-push-Workaround aus diesem Issue führt in einen zweiten, eigenständigen Bug: #97. Zusammen verhindern beide jeden dokumentierten ersten Publish einer neuen Instanz gegen ein leeres Remote.
Der `--no-push`-Workaround aus diesem Issue führt in einen zweiten, eigenständigen Bug: #97. Zusammen verhindern beide jeden dokumentierten ersten Publish einer neuen Instanz gegen ein leeres Remote.
Changelog: Verdacht gegen den Baum geprüft und bestätigt (rev-parse --abbrev-ref HEAD endet auf ungeborenem Branch mit rc 128) - status/unconfirmed entfällt, prio/planned -> prio/blocking. Beide offenen Fragen beantwortet und als Abschnitt "Entscheidung" in den Body geschrieben: Fix per git symbolic-ref --short -q HEAD, wodurch sich Frage 2 (Prüfung im ungeborenen Fall aussetzen?) auflöst statt beantwortet werden zu müssen. Blast radius ergänzt (ein einziger Aufrufer; der restliche Publish-Pfad trägt den Fall bereits). Akzeptanzkriterien um den --branch-Fall auf ungeborenem Branch und den Fixture-Hinweis erweitert. Schnitt festgehalten: gemeinsame Umsetzung mit #97, ein --patch-Bump.
**Changelog:** Verdacht gegen den Baum geprüft und bestätigt (`rev-parse --abbrev-ref HEAD` endet auf ungeborenem Branch mit rc 128) - `status/unconfirmed` entfällt, `prio/planned` -> `prio/blocking`. Beide offenen Fragen beantwortet und als Abschnitt "Entscheidung" in den Body geschrieben: Fix per `git symbolic-ref --short -q HEAD`, wodurch sich Frage 2 (Prüfung im ungeborenen Fall aussetzen?) auflöst statt beantwortet werden zu müssen. Blast radius ergänzt (ein einziger Aufrufer; der restliche Publish-Pfad trägt den Fall bereits). Akzeptanzkriterien um den `--branch`-Fall auf ungeborenem Branch und den Fixture-Hinweis erweitert. Schnitt festgehalten: gemeinsame Umsetzung mit #97, ein `--patch`-Bump.
Changelog: Umgesetzt und veröffentlicht (9ef021b, 5.0.0 -> 5.0.1-beta.1). Body auf den Endstand geschrieben: alle sechs Akzeptanzkriterien abgehakt und je mit dem Test benannt, der sie hält; Abschnitt "Verifikation" ergänzt (1204 Tests grün, Gegenprobe gegen den zurückgedrehten Fix, Leere-Maschine-Lauf, docs verify/instructions verify). Ergebnis des letzten Kriteriums festgehalten: tools/CONTRACT.md wurde in beiden Tabellen nachgezogen, instructions/setup-instance.md und INSTALL.md blieben nach Prüfung unverändert - --no-push musste dort nicht erwähnt werden. Keine docs/-Seite betroffen: die Gates sind unverändert, docs/why-gates-are-code.md trägt keine Aussage, die sich bewegt hätte.
**Changelog:** Umgesetzt und veröffentlicht (`9ef021b`, 5.0.0 -> 5.0.1-beta.1). Body auf den Endstand geschrieben: alle sechs Akzeptanzkriterien abgehakt und je mit dem Test benannt, der sie hält; Abschnitt "Verifikation" ergänzt (1204 Tests grün, Gegenprobe gegen den zurückgedrehten Fix, Leere-Maschine-Lauf, `docs verify`/`instructions verify`). Ergebnis des letzten Kriteriums festgehalten: `tools/CONTRACT.md` wurde in beiden Tabellen nachgezogen, `instructions/setup-instance.md` und `INSTALL.md` blieben nach Prüfung unverändert - `--no-push` musste dort nicht erwähnt werden. Keine `docs/`-Seite betroffen: die Gates sind unverändert, `docs/why-gates-are-code.md` trägt keine Aussage, die sich bewegt hätte.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Befund
Beim Einrichten einer frischen 5.0.0-Instanz aus dem Release-Tarball (Weg A aus
INSTALL.md) verweigerte Schritt 14 ausinstructions/setup-instance.mdden ersten Commit:HEAD war dabei nicht detached, sondern ein ungeborener Branch (
git symbolic-ref HEAD->refs/heads/main,git status -sb->## No commits yet on main).Betroffene Version: 5.0.0. Behoben in 5.0.1-beta.1, Commit
9ef021b.Warum das zählt
instructions/setup-instance.mdSchritt 14 undINSTALL.md(Weg A und B) nennenpublish --messageals den Weg zum ersten Commit einer neuen Instanz, unddoctorsagt an derselben Stellefix: Make the first commit via publish once ready. Genau dieser dokumentierte Befehl schlug fehl - bei jeder neuen Instanz, beim ersten schreibendenwikitool-Aufruf überhaupt. Invariante 5 schnitt den naheliegenden Ausweg ab: ein Agent darf nicht aufgit commitvon Hand ausweichen. Zusammen mit #97 hieß das: eine neue Instanz mit leerem Remote ließ sich mit 5.0.0 über keinen dokumentierten Weg initial veröffentlichen.Ursache - verifiziert
Die ursprüngliche Vermutung traf zu.
current_branch()fragtegit rev-parse --abbrev-ref HEAD; auf einem ungeborenen Branch endet der Aufruf mit Exit 128 ("ambiguous argument 'HEAD': unknown revision") und fiel damit in denselbenNone-Zweig wie ein echter detached HEAD.branch_mismatch_message()formulierte daraus die detached-HEAD-Ablehnung,publish_command()brach damit ab.Gemessen in einem frisch initialisierten Repo:
rev-parse --abbrev-ref HEADsymbolic-ref --short -q HEADgit init -b main)HEADmaingit checkout <sha>)HEADmainmainsymbolic-refunterscheidet die beiden Zustände genau dort, worev-parsesie zusammenwirft, und liefert im dritten Fall dasselbe.Entscheidung und Umsetzung
Frage 1 (trifft die Ableitung zu?) - ja, siehe Tabelle.
Frage 2 (soll die Prüfung im ungeborenen Fall greifen?) - nein, und mit der gewählten Umsetzung stellte sie sich nicht mehr. Das Motiv der Prüfung (
git push <remote> <branch>pusht den benannten Ref, nichtHEAD) existiert im ungeborenen Fall nicht: es gibt genau einen Branch, der Commit entsteht auf ihm,originhat den Ref noch gar nicht. Die Prüfung wurde deshalb nicht ausgesetzt, sondern korrekt beantwortet:current_branch()liefert auf ungeborenemmainjetzt"main", der Vergleichchecked_out != branchgeht von selbst durch. Ein Sonderfall im Aufrufer entfiel.Umgesetzt:
current_branch()liestgit symbolic-ref --short -q HEADstattgit rev-parse --abbrev-ref HEAD; leere Ausgabe oder rc != 0 bleibtNone(= detached HEAD). Der Docstring hält fest, warumsymbolic-refund nichtrev-parse- dass es liest, wasHEADbenennt, statt worauf es zeigt.Blast radius, wie erwartet klein:
current_branch()hat genau einen Aufrufer, die Branch-Prüfung inpublish_command(). Der restliche Publish-Pfad trug den ungeborenen Fall bereits:_numstat()dokumentiert ihn ausdrücklich und liefert{},_changed_files()liestgit status --porcelain, das ohne Commit funktioniert, undreconcile()fällt gegen ein leeres Remote aufno-remote-or-fetch-failedzurück. Es war keine weitere Anpassung nötig.Akzeptanzkriterien
git init -b mainohne jeden Commit legttools/wikitool publish --message "<text>"den Commit aufmainan und pusht ihn nachorigin/main- ohne--no-pushund ohne handgemachtesgit commit. Test:test_publish_makes_the_first_commit_of_a_new_instance.branch_mismatch_message()blieb unverändert; es änderte sich nur, welcher ZustandNoneerzeugt. Test:test_current_branch_still_reports_a_real_detached_head_as_none.--branch-Hinweis, auch auf einem ungeborenen Branch. Test:test_publish_on_an_unborn_branch_still_refuses_a_different_target_branch.test_the_gate_still_holds_on_a_fresh_instance_and_stages_nothing.tools/chemenu/tests/test_git_publish.pyträgt je einen Test für den ungeborenen Branch und den echten detached HEAD. Umgesetzt über ein eigenesfresh_instance-Fixture (ungeborener Branch, leeres bare-Remote, kein Commit) - derrepo-Fixture taugte wie erwartet nicht, weil er einen Init-Commit anlegt und pusht.tools/CONTRACT.mdbenennt die Branch-Prüfung jetzt in derpublish-Kommandozeile und als eigenständigen Exit-1-Grund im Fehlerkontrakt, jeweils mit dem ungeborenen Branch als ausdrücklicher Ausnahme.instructions/setup-instance.mdSchritt 2 und 14 sowieINSTALL.mdblieben unverändert: geprüft und inhaltlich richtig - sie beschrieben nie den Workaround, sondern den Weg, der jetzt tatsächlich funktioniert.--no-pushmusste beim ersten Commit folglich nicht erwähnt werden.Verifikation
pytestintools/: 1204 Tests grün, davon 96 intest_git_publish.py.test_current_branch_names_an_unborn_branch_rather_than_calling_it_detached,test_publish_makes_the_first_commit_of_a_new_instance,test_the_gate_still_holds_on_a_fresh_instance_and_stages_nothing,test_publish_pushes_a_committed_stand_to_a_remote_that_has_no_branch_yet); die Schutztests bestehen erwartungsgemäß in beide Richtungen.instructions/dev/testing-conventions.mdSchritt 6 (env -iohne HOME/Git-Config): identisches Ergebnis, 1204 grün - kein Leck über die Umgebung.tools/wikitool docs verifyundtools/wikitool instructions verify: beide OK.Beteiligte Dateien
tools/chemenu/commands/git_publish.py-current_branch()tools/chemenu/tests/test_git_publish.py-fresh_instance-Fixture,_remote_log(), vier Teststools/CONTRACT.md-publish-Kommandozeile und Fehlerkontrakt-ZeileBeziehung zu #97
Gemeinsam umgesetzt, ein Commit (
9ef021b), ein Version-Bump (--patch, 5.0.0 -> 5.0.1-beta.1): verschiedene Funktionen und Ursachen, aber dieselbe Datei, dieselbe Testdatei, dieselbe Doku-Zeile, und die Kette ließ sich erst gemeinsam als Ganzes testen.--patchwar die richtige Stufe - reine Fehlerbehebung, keine Schnittstellenänderung, in beide Richtungen drop-in.Der
--no-push-Workaround aus diesem Issue führt in einen zweiten, eigenständigen Bug: #97. Zusammen verhindern beide jeden dokumentierten ersten Publish einer neuen Instanz gegen ein leeres Remote.Changelog: Verdacht gegen den Baum geprüft und bestätigt (
rev-parse --abbrev-ref HEADendet auf ungeborenem Branch mit rc 128) -status/unconfirmedentfällt,prio/planned->prio/blocking. Beide offenen Fragen beantwortet und als Abschnitt "Entscheidung" in den Body geschrieben: Fix pergit symbolic-ref --short -q HEAD, wodurch sich Frage 2 (Prüfung im ungeborenen Fall aussetzen?) auflöst statt beantwortet werden zu müssen. Blast radius ergänzt (ein einziger Aufrufer; der restliche Publish-Pfad trägt den Fall bereits). Akzeptanzkriterien um den--branch-Fall auf ungeborenem Branch und den Fixture-Hinweis erweitert. Schnitt festgehalten: gemeinsame Umsetzung mit #97, ein--patch-Bump.Changelog: Umgesetzt und veröffentlicht (
9ef021b, 5.0.0 -> 5.0.1-beta.1). Body auf den Endstand geschrieben: alle sechs Akzeptanzkriterien abgehakt und je mit dem Test benannt, der sie hält; Abschnitt "Verifikation" ergänzt (1204 Tests grün, Gegenprobe gegen den zurückgedrehten Fix, Leere-Maschine-Lauf,docs verify/instructions verify). Ergebnis des letzten Kriteriums festgehalten:tools/CONTRACT.mdwurde in beiden Tabellen nachgezogen,instructions/setup-instance.mdundINSTALL.mdblieben nach Prüfung unverändert ---no-pushmusste dort nicht erwähnt werden. Keinedocs/-Seite betroffen: die Gates sind unverändert,docs/why-gates-are-code.mdträgt keine Aussage, die sich bewegt hätte.