Befunde aus der Analyse in #140, gültig auf jeder Plattform. Umgesetzt im 8.0.0-Kandidaten (Bump auf 8.0.0-beta.10, Commit eadc052, README-Nachzug 61130ce; Nachprüfung beim Abschluss: 8.0.0-beta.11, Commit 03743eb). Entschieden wurde Teil 3 (D25, Betreiber, 2026-09-28; erweitert um Entscheidung A, Betreiber, 2026-09-30): publish ohne --no-push bricht vor dem Commit ab, wenn das Remote nicht erreichbar oder gar nicht konfiguriert ist.
Befund 1 – das Gate zählte einen Pfad doppelt (behoben)
collect_changes (tools/chemenu/commands/git_publish.py) las git status --porcelain -z -uall. Ein Pfad, der als gelöscht vorgemerkt ist und zugleich wieder im Arbeitsbaum liegt (git rm -r raw, danach git restore --source=HEAD -- raw/CONTRACT.md ohne --staged), steht dort zweimal (D und ??). Das Gate zählte beide; git add -A hebt sie gegeneinander auf, der Commit enthielt keinen. Die Liste zur Freigabe nannte also eine Löschung und eine Neuanlage, die nie committet wurden.
Umsetzung:collect_changes staged in einem temporären Index (Kopie des echten, oder leer, wenn keiner existiert; GIT_INDEX_FILE) und liest git diff --cached --no-renames daraus (--raw --no-abbrev -z für Status und Blob-ID, --numstat -z für die Zeilenzahlen, beides auf --paths eingeschränkt). Das temporäre Verzeichnis wird in finally entfernt.
Digest im --confirm-Token ist die Blob-ID des gestagten Inhalts; bei einer Löschung bleibt er leer.
Eine Umbenennung erscheint als alter Pfad (deleted) plus neuer Pfad (added); renamed entfällt im Scale-Line.
Entfernt: _numstat, _untracked_stat, _changed_files, parse_porcelain_entries, parse_porcelain_z samt Tests. describe_status liest jetzt den Status-Buchstaben von --raw.
Die Dateiliste der Commit-Message stammt aus derselben Liste und stimmt damit ebenfalls.
Invariante, die hält (getestet): ein abgelehnter publish hinterlässt echten Index und Arbeitsbaum byte-identisch, auch auf einem ungeborenen Branch ohne Index-Datei und auch, wenn die Berechnung mittendrin scheitert (dann ist auch die Temp-Kopie weg). git add schreibt Blobs in den Objektspeicher; das ist erlaubt.
Befund 2 – eine Meldung für drei Zustände (behoben)
reconcile liefert bei gescheitertem Fetch jetzt genau einen von drei Status, bestimmt nur nach dem Fehlschlag:
Status
Erkennung
sync
publish ohne --no-push
no-remote
git remote get-url <remote> scheitert
Exit 0
Exit 1, vor dem Commit
remote-lacks-branch
git ls-remote --exit-code → 2
Exit 0
weiter wie bisher (erster Push)
unreachable
sonst
Exit 0
Exit 1, vor dem Commit
Jeder Status hat seine eigene Meldung; die von unreachable nennt die URL.
Teil 3 – vor dem Commit abbrechen (umgesetzt)
publish_command ruft nach dem Reconcile publish_stop_message auf und endet bei unreachable/no-remote mit fail() (Exit 1) – vor collect_changes, also vor Gate, git add und Commit, und auch bei sauberem Baum (früher: „Nothing to commit“). Beide Meldungen nennen --no-push; die von unreachable sagt, dass der nächste publish mit erreichbarem Remote den lokalen Commit mitnimmt, die von no-remote verweist auf setup-instance.md Schritt 4. Das Publish-Remote-Gate (Exit 42, wenn .wikitool-remotes.json existiert) greift weiterhin vorher; der Retry nach einem abgelehnten Push bleibt unverändert und meldet bei inzwischen unerreichbarem Remote den ursprünglichen Push-Fehler.
Akzeptanzkriterien (alle erfüllt, je ein Test in tools/chemenu/tests/test_git_publish.py)
Im nachgestellten Fall zählt das Gate genau eine Datei (raw/a.md, gelöscht), kein raw/CONTRACT.md.
Die Pfadliste von collect_changes stimmt mit der des Commits nach dem publish überein (inkl. Umbenennung).
Nach Gate-Ablehnung (Exit 42) sind echter Index (Bytes) und Arbeitsbaum identisch mit vorher; ebenso ohne Index-Datei und nach scheiterndem git add.
Erster publish einer frischen Instanz committet und pusht weiterhin.
no-remote, remote-lacks-branch, unreachable: drei verschiedene Meldungen; sync endet in allen dreien mit Exit 0.
Nicht erreichbares Remote ohne --no-push: Exit 1, kein Commit, Index und Arbeitsbaum unverändert, auch bei sauberem Baum.
Ohne Remote und ohne --no-push dasselbe; die Meldung verweist auf --no-push.
Mit --no-push wird in beiden Fällen lokal committet; der liegengebliebene Commit geht mit dem nächsten erreichbaren publish hinaus.
publish- und sync-Record, tools/CONTRACT.md (regeneriert), instructions/publish-cycle.md, instructions/setup-instance.md Schritte 4 und 15, instructions/gates.md, INSTALL.md und die README-Zeile zu publish beschreiben die Ablehnung und die drei Meldungen.
Version
Major-Bump im laufenden 8.0.0-Kandidaten (8.0.0-beta.10), --breaking: „publish without --no-push now exits 1 before committing when the remote is unreachable or not configured, where it used to commit locally and fail at the push - an offline session or a local-only instance must pass --no-push“. **Migration:** bleibt „none required“, am Inhalt ändert sich nichts. Der Nachzug beim Abschluss lief als Patch (8.0.0-beta.11).
Verifikation
pytest in tools/: 1763 passed, 3 skipped (Umsetzung); 235 passed in test_git_publish.py, test_docs_verify.py, test_instructions*.py (Nachzug).
tools/wikitool docs verify, tools/wikitool instructions verify, docs toc: grün bzw. aktuell, jeweils vor beiden Publishes.
Abschlussprüfung auf Opus gegen den Code: Changelog-Aussagen zum alten Verhalten (alte Meldung „No remote configured, or origin could not be reached“, „Nothing to commit“ bei sauberem Baum), sync-Exit 0 und Retry-Pfad am Code von 08dde00 bzw. HEAD bestätigt.
Nicht angefasst
kb/concepts/workflows/Mass-Update Gate.md beschreibt das Gate noch mit „git status --porcelain nach dem Staging“. Das ist Korpusinhalt und läuft über den normalen Quellen-/Provenance-Weg, nicht über dieses Paket.
Verwandt: #53 (Gate-Schwelle), #149 (Trailer der Commit-Message).
Befunde aus der Analyse in #140, gültig auf jeder Plattform. Umgesetzt im 8.0.0-Kandidaten (Bump auf 8.0.0-beta.10, Commit eadc052, README-Nachzug 61130ce; Nachprüfung beim Abschluss: 8.0.0-beta.11, Commit 03743eb). Entschieden wurde Teil 3 (D25, Betreiber, 2026-09-28; erweitert um Entscheidung A, Betreiber, 2026-09-30): `publish` ohne `--no-push` bricht vor dem Commit ab, wenn das Remote nicht erreichbar oder gar nicht konfiguriert ist.
## Befund 1 – das Gate zählte einen Pfad doppelt (behoben)
`collect_changes` (`tools/chemenu/commands/git_publish.py`) las `git status --porcelain -z -uall`. Ein Pfad, der als gelöscht vorgemerkt ist und zugleich wieder im Arbeitsbaum liegt (`git rm -r raw`, danach `git restore --source=HEAD -- raw/CONTRACT.md` ohne `--staged`), steht dort zweimal (`D ` und `??`). Das Gate zählte beide; `git add -A` hebt sie gegeneinander auf, der Commit enthielt keinen. Die Liste zur Freigabe nannte also eine Löschung und eine Neuanlage, die nie committet wurden.
**Umsetzung:** `collect_changes` staged in einem temporären Index (Kopie des echten, oder leer, wenn keiner existiert; `GIT_INDEX_FILE`) und liest `git diff --cached --no-renames` daraus (`--raw --no-abbrev -z` für Status und Blob-ID, `--numstat -z` für die Zeilenzahlen, beides auf `--paths` eingeschränkt). Das temporäre Verzeichnis wird in `finally` entfernt.
- Digest im `--confirm`-Token ist die Blob-ID des gestagten Inhalts; bei einer Löschung bleibt er leer.
- Eine Umbenennung erscheint als alter Pfad (deleted) plus neuer Pfad (added); `renamed` entfällt im Scale-Line.
- Entfernt: `_numstat`, `_untracked_stat`, `_changed_files`, `parse_porcelain_entries`, `parse_porcelain_z` samt Tests. `describe_status` liest jetzt den Status-Buchstaben von `--raw`.
- Die Dateiliste der Commit-Message stammt aus derselben Liste und stimmt damit ebenfalls.
- **Invariante, die hält (getestet):** ein abgelehnter `publish` hinterlässt echten Index und Arbeitsbaum byte-identisch, auch auf einem ungeborenen Branch ohne Index-Datei und auch, wenn die Berechnung mittendrin scheitert (dann ist auch die Temp-Kopie weg). `git add` schreibt Blobs in den Objektspeicher; das ist erlaubt.
## Befund 2 – eine Meldung für drei Zustände (behoben)
`reconcile` liefert bei gescheitertem Fetch jetzt genau einen von drei Status, bestimmt nur nach dem Fehlschlag:
| Status | Erkennung | `sync` | `publish` ohne `--no-push` |
|---|---|---|---|
| `no-remote` | `git remote get-url <remote>` scheitert | Exit 0 | Exit 1, vor dem Commit |
| `remote-lacks-branch` | `git ls-remote --exit-code` → 2 | Exit 0 | weiter wie bisher (erster Push) |
| `unreachable` | sonst | Exit 0 | Exit 1, vor dem Commit |
Jeder Status hat seine eigene Meldung; die von `unreachable` nennt die URL.
## Teil 3 – vor dem Commit abbrechen (umgesetzt)
`publish_command` ruft nach dem Reconcile `publish_stop_message` auf und endet bei `unreachable`/`no-remote` mit `fail()` (Exit 1) – vor `collect_changes`, also vor Gate, `git add` und Commit, und auch bei sauberem Baum (früher: „Nothing to commit“). Beide Meldungen nennen `--no-push`; die von `unreachable` sagt, dass der nächste `publish` mit erreichbarem Remote den lokalen Commit mitnimmt, die von `no-remote` verweist auf `setup-instance.md` Schritt 4. Das Publish-Remote-Gate (Exit 42, wenn `.wikitool-remotes.json` existiert) greift weiterhin vorher; der Retry nach einem abgelehnten Push bleibt unverändert und meldet bei inzwischen unerreichbarem Remote den ursprünglichen Push-Fehler.
## Akzeptanzkriterien (alle erfüllt, je ein Test in `tools/chemenu/tests/test_git_publish.py`)
- [x] Im nachgestellten Fall zählt das Gate genau eine Datei (`raw/a.md`, gelöscht), kein `raw/CONTRACT.md`.
- [x] Die Pfadliste von `collect_changes` stimmt mit der des Commits nach dem `publish` überein (inkl. Umbenennung).
- [x] Nach Gate-Ablehnung (Exit 42) sind echter Index (Bytes) und Arbeitsbaum identisch mit vorher; ebenso ohne Index-Datei und nach scheiterndem `git add`.
- [x] Erster `publish` einer frischen Instanz committet und pusht weiterhin.
- [x] `no-remote`, `remote-lacks-branch`, `unreachable`: drei verschiedene Meldungen; `sync` endet in allen dreien mit Exit 0.
- [x] Nicht erreichbares Remote ohne `--no-push`: Exit 1, kein Commit, Index und Arbeitsbaum unverändert, auch bei sauberem Baum.
- [x] Ohne Remote und ohne `--no-push` dasselbe; die Meldung verweist auf `--no-push`.
- [x] Mit `--no-push` wird in beiden Fällen lokal committet; der liegengebliebene Commit geht mit dem nächsten erreichbaren `publish` hinaus.
- [x] `publish`- und `sync`-Record, `tools/CONTRACT.md` (regeneriert), `instructions/publish-cycle.md`, `instructions/setup-instance.md` Schritte 4 und 15, `instructions/gates.md`, `INSTALL.md` und die README-Zeile zu `publish` beschreiben die Ablehnung und die drei Meldungen.
## Version
Major-Bump im laufenden 8.0.0-Kandidaten (`8.0.0-beta.10`), `--breaking`: „publish without --no-push now exits 1 before committing when the remote is unreachable or not configured, where it used to commit locally and fail at the push - an offline session or a local-only instance must pass --no-push“. `**Migration:**` bleibt „none required“, am Inhalt ändert sich nichts. Der Nachzug beim Abschluss lief als Patch (`8.0.0-beta.11`).
## Verifikation
- `pytest` in `tools/`: 1763 passed, 3 skipped (Umsetzung); 235 passed in `test_git_publish.py`, `test_docs_verify.py`, `test_instructions*.py` (Nachzug).
- `tools/wikitool docs verify`, `tools/wikitool instructions verify`, `docs toc`: grün bzw. aktuell, jeweils vor beiden Publishes.
- CI: Runs 459 und 460 (eadc052), 461 (61130ce), 462 und 463 (03743eb), alle `success`.
- Abschlussprüfung auf Opus gegen den Code: Changelog-Aussagen zum alten Verhalten (alte Meldung „No remote configured, or origin could not be reached“, „Nothing to commit“ bei sauberem Baum), `sync`-Exit 0 und Retry-Pfad am Code von 08dde00 bzw. HEAD bestätigt.
## Nicht angefasst
`kb/concepts/workflows/Mass-Update Gate.md` beschreibt das Gate noch mit „`git status --porcelain` nach dem Staging“. Das ist Korpusinhalt und läuft über den normalen Quellen-/Provenance-Weg, nicht über dieses Paket.
Verwandt: #53 (Gate-Schwelle), #149 (Trailer der Commit-Message).
Entschieden (Betreiber, 2026-09-28): D25. Teil 3 gehört damit fest zu diesem Paket: publish bricht bei unerreichbarem, konfiguriertem Remote vor dem Commit ab.
Version: im 8.0.0-Kandidaten, im --breaking-Text erwähnt.
Neu: Akzeptanzkriterium zur Doku (publish-Record, publish-cycle.md).
**Changelog:**
- **Entschieden (Betreiber, 2026-09-28):** D25. Teil 3 gehört damit fest zu diesem Paket: `publish` bricht bei unerreichbarem, konfiguriertem Remote vor dem Commit ab.
- **Version:** im 8.0.0-Kandidaten, im `--breaking`-Text erwähnt.
- **Neu:** Akzeptanzkriterium zur Doku (`publish`-Record, `publish-cycle.md`).
torben
added size/M and removed size/S labels 2026-09-30 18:30:22 +00:00
Changelog: Für die Entwicklung vorbereitet (2026-09-30), Body gegen den Baum geprüft.
Neu: Entwurf je Teil. Befund 1: Temp-Index + diff --cached --no-renames, Digest = Blob-ID, _numstat/_untracked_stat/_changed_files/parse_porcelain_* entfallen. Befund 2: drei Status no-remote/remote-lacks-branch/unreachable. Teil 3: fail() vor collect_changes, auch bei sauberem Baum (Session-Entscheidung, begründet). Dazu eine Dateiliste und die Index-Invariante für den Temp-Index.
Neu: Offene Frage A (kein Remote + Push → auch vor dem Commit abbrechen?), mit Empfehlung „ja“.
Korrigiert: Der Body sagte, D25 stehe schon im --breaking-Text des Kandidaten. Das stimmt nicht; der fertige version bump-Aufruf steht jetzt unter „Version“.
Akzeptanzkriterien: nachgeschärft (Index-Invariante, erster Publish, sync Exit 0, --no-push-Pfad).
Relabel:size/S → size/M: Drei Teile, zwei Records, eine Instruction und ein eigener Testaufwand sind mehr als „ein klarer Schnitt“.
**Changelog:** Für die Entwicklung vorbereitet (2026-09-30), Body gegen den Baum geprüft.
- **Neu:** Entwurf je Teil. Befund 1: Temp-Index + `diff --cached --no-renames`, Digest = Blob-ID, `_numstat`/`_untracked_stat`/`_changed_files`/`parse_porcelain_*` entfallen. Befund 2: drei Status `no-remote`/`remote-lacks-branch`/`unreachable`. Teil 3: `fail()` vor `collect_changes`, auch bei sauberem Baum (Session-Entscheidung, begründet). Dazu eine Dateiliste und die Index-Invariante für den Temp-Index.
- **Neu:** Offene Frage A (kein Remote + Push → auch vor dem Commit abbrechen?), mit Empfehlung „ja“.
- **Korrigiert:** Der Body sagte, D25 stehe schon im `--breaking`-Text des Kandidaten. Das stimmt nicht; der fertige `version bump`-Aufruf steht jetzt unter „Version“.
- **Akzeptanzkriterien:** nachgeschärft (Index-Invariante, erster Publish, `sync` Exit 0, `--no-push`-Pfad).
- **Relabel:** `size/S` → `size/M`: Drei Teile, zwei Records, eine Instruction und ein eigener Testaufwand sind mehr als „ein klarer Schnitt“.
Changelog: Frage A entschieden (Betreiber, 2026-09-30): Auch no-remote bricht ohne --no-push vor dem Commit ab; die Session-Entscheidung zum sauberen Baum ist bestätigt.
„Offene Frage“ entfällt. Teil 3 deckt jetzt unreachable und no-remote ab, der Befund-2-Tabelle ist eine Spalte für das Verhalten von sync/publish hinzugefügt.
Neu: Hinweis, dass das Publish-Remote-Gate bei vorhandener .wikitool-remotes.json vorher greift. setup-instance.md Schritt 4 und INSTALL.md stehen in der Dateiliste, außerdem die Prüfung bestehender Tests, die ohne Remote publizieren.
Neu: Akzeptanzkriterium für no-remote ohne --no-push; das --no-push-Kriterium deckt jetzt beide Fälle ab.
Geändert: Titel und --breaking-Text des version bump-Aufrufs um „or not configured“ bzw. „local-only instance“ erweitert.
**Changelog:** Frage A entschieden (Betreiber, 2026-09-30): Auch `no-remote` bricht ohne `--no-push` vor dem Commit ab; die Session-Entscheidung zum sauberen Baum ist bestätigt.
- „Offene Frage“ entfällt. Teil 3 deckt jetzt `unreachable` und `no-remote` ab, der Befund-2-Tabelle ist eine Spalte für das Verhalten von `sync`/`publish` hinzugefügt.
- **Neu:** Hinweis, dass das Publish-Remote-Gate bei vorhandener `.wikitool-remotes.json` vorher greift. `setup-instance.md` Schritt 4 und `INSTALL.md` stehen in der Dateiliste, außerdem die Prüfung bestehender Tests, die ohne Remote publizieren.
- **Neu:** Akzeptanzkriterium für `no-remote` ohne `--no-push`; das `--no-push`-Kriterium deckt jetzt beide Fälle ab.
- **Geändert:** Titel und `--breaking`-Text des `version bump`-Aufrufs um „or not configured“ bzw. „local-only instance“ erweitert.
Umgesetzt in 8.0.0-beta.10 (eadc052, README-Nachzug 61130ce), CI-Runs 459, 460, 461 grün. Body auf den Endstand gebracht: Kriterien abgehakt, Design als Entscheidung formuliert, Verifikation benannt. Offen bleibt nur die Korpusseite kb/concepts/workflows/Mass-Update Gate.md (beschreibt noch das alte Porcelain-Zählen), bewusst nicht Teil dieses Pakets.
Umgesetzt in 8.0.0-beta.10 (eadc052, README-Nachzug 61130ce), CI-Runs 459, 460, 461 grün. Body auf den Endstand gebracht: Kriterien abgehakt, Design als Entscheidung formuliert, Verifikation benannt. Offen bleibt nur die Korpusseite `kb/concepts/workflows/Mass-Update Gate.md` (beschreibt noch das alte Porcelain-Zählen), bewusst nicht Teil dieses Pakets.
Nachprüfung auf Opus (8.0.0-beta.11, 03743eb, CI-Runs 462/463 grün): setup-instance.md Schritt 15 zeigte den ersten publish ohne --no-push und kündigte Exit 42 an. Eine lokale Instanz bekommt dort jetzt Exit 1, deshalb nennt der Schritt das Flag. Außerdem nachgezogen: ein Satz in gates.md (das Gate zählte angeblich „working-tree changes before publish stages them“) und der _reconcile_summary-Docstring. Body entsprechend ergänzt.
Nachprüfung auf Opus (8.0.0-beta.11, 03743eb, CI-Runs 462/463 grün): `setup-instance.md` Schritt 15 zeigte den ersten `publish` ohne `--no-push` und kündigte Exit 42 an. Eine lokale Instanz bekommt dort jetzt Exit 1, deshalb nennt der Schritt das Flag. Außerdem nachgezogen: ein Satz in `gates.md` (das Gate zählte angeblich „working-tree changes before publish stages them“) und der `_reconcile_summary`-Docstring. Body entsprechend ergänzt.
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.
Befunde aus der Analyse in #140, gültig auf jeder Plattform. Umgesetzt im 8.0.0-Kandidaten (Bump auf 8.0.0-beta.10, Commit
eadc052, README-Nachzug 61130ce; Nachprüfung beim Abschluss: 8.0.0-beta.11, Commit03743eb). Entschieden wurde Teil 3 (D25, Betreiber, 2026-09-28; erweitert um Entscheidung A, Betreiber, 2026-09-30):publishohne--no-pushbricht vor dem Commit ab, wenn das Remote nicht erreichbar oder gar nicht konfiguriert ist.Befund 1 – das Gate zählte einen Pfad doppelt (behoben)
collect_changes(tools/chemenu/commands/git_publish.py) lasgit status --porcelain -z -uall. Ein Pfad, der als gelöscht vorgemerkt ist und zugleich wieder im Arbeitsbaum liegt (git rm -r raw, danachgit restore --source=HEAD -- raw/CONTRACT.mdohne--staged), steht dort zweimal (Dund??). Das Gate zählte beide;git add -Ahebt sie gegeneinander auf, der Commit enthielt keinen. Die Liste zur Freigabe nannte also eine Löschung und eine Neuanlage, die nie committet wurden.Umsetzung:
collect_changesstaged in einem temporären Index (Kopie des echten, oder leer, wenn keiner existiert;GIT_INDEX_FILE) und liestgit diff --cached --no-renamesdaraus (--raw --no-abbrev -zfür Status und Blob-ID,--numstat -zfür die Zeilenzahlen, beides auf--pathseingeschränkt). Das temporäre Verzeichnis wird infinallyentfernt.--confirm-Token ist die Blob-ID des gestagten Inhalts; bei einer Löschung bleibt er leer.renamedentfällt im Scale-Line._numstat,_untracked_stat,_changed_files,parse_porcelain_entries,parse_porcelain_zsamt Tests.describe_statusliest jetzt den Status-Buchstaben von--raw.publishhinterlässt echten Index und Arbeitsbaum byte-identisch, auch auf einem ungeborenen Branch ohne Index-Datei und auch, wenn die Berechnung mittendrin scheitert (dann ist auch die Temp-Kopie weg).git addschreibt Blobs in den Objektspeicher; das ist erlaubt.Befund 2 – eine Meldung für drei Zustände (behoben)
reconcileliefert bei gescheitertem Fetch jetzt genau einen von drei Status, bestimmt nur nach dem Fehlschlag:syncpublishohne--no-pushno-remotegit remote get-url <remote>scheitertremote-lacks-branchgit ls-remote --exit-code→ 2unreachableJeder Status hat seine eigene Meldung; die von
unreachablenennt die URL.Teil 3 – vor dem Commit abbrechen (umgesetzt)
publish_commandruft nach dem Reconcilepublish_stop_messageauf und endet beiunreachable/no-remotemitfail()(Exit 1) – vorcollect_changes, also vor Gate,git addund Commit, und auch bei sauberem Baum (früher: „Nothing to commit“). Beide Meldungen nennen--no-push; die vonunreachablesagt, dass der nächstepublishmit erreichbarem Remote den lokalen Commit mitnimmt, die vonno-remoteverweist aufsetup-instance.mdSchritt 4. Das Publish-Remote-Gate (Exit 42, wenn.wikitool-remotes.jsonexistiert) greift weiterhin vorher; der Retry nach einem abgelehnten Push bleibt unverändert und meldet bei inzwischen unerreichbarem Remote den ursprünglichen Push-Fehler.Akzeptanzkriterien (alle erfüllt, je ein Test in
tools/chemenu/tests/test_git_publish.py)raw/a.md, gelöscht), keinraw/CONTRACT.md.collect_changesstimmt mit der des Commits nach dempublishüberein (inkl. Umbenennung).git add.publisheiner frischen Instanz committet und pusht weiterhin.no-remote,remote-lacks-branch,unreachable: drei verschiedene Meldungen;syncendet in allen dreien mit Exit 0.--no-push: Exit 1, kein Commit, Index und Arbeitsbaum unverändert, auch bei sauberem Baum.--no-pushdasselbe; die Meldung verweist auf--no-push.--no-pushwird in beiden Fällen lokal committet; der liegengebliebene Commit geht mit dem nächsten erreichbarenpublishhinaus.publish- undsync-Record,tools/CONTRACT.md(regeneriert),instructions/publish-cycle.md,instructions/setup-instance.mdSchritte 4 und 15,instructions/gates.md,INSTALL.mdund die README-Zeile zupublishbeschreiben die Ablehnung und die drei Meldungen.Version
Major-Bump im laufenden 8.0.0-Kandidaten (
8.0.0-beta.10),--breaking: „publish without --no-push now exits 1 before committing when the remote is unreachable or not configured, where it used to commit locally and fail at the push - an offline session or a local-only instance must pass --no-push“.**Migration:**bleibt „none required“, am Inhalt ändert sich nichts. Der Nachzug beim Abschluss lief als Patch (8.0.0-beta.11).Verifikation
pytestintools/: 1763 passed, 3 skipped (Umsetzung); 235 passed intest_git_publish.py,test_docs_verify.py,test_instructions*.py(Nachzug).tools/wikitool docs verify,tools/wikitool instructions verify,docs toc: grün bzw. aktuell, jeweils vor beiden Publishes.eadc052), 461 (61130ce), 462 und 463 (03743eb), allesuccess.sync-Exit 0 und Retry-Pfad am Code von08dde00bzw. HEAD bestätigt.Nicht angefasst
kb/concepts/workflows/Mass-Update Gate.mdbeschreibt das Gate noch mit „git status --porcelainnach dem Staging“. Das ist Korpusinhalt und läuft über den normalen Quellen-/Provenance-Weg, nicht über dieses Paket.Verwandt: #53 (Gate-Schwelle), #149 (Trailer der Commit-Message).
Changelog:
publishbricht bei unerreichbarem, konfiguriertem Remote vor dem Commit ab.--breaking-Text erwähnt.publish-Record,publish-cycle.md).Changelog: Für die Entwicklung vorbereitet (2026-09-30), Body gegen den Baum geprüft.
diff --cached --no-renames, Digest = Blob-ID,_numstat/_untracked_stat/_changed_files/parse_porcelain_*entfallen. Befund 2: drei Statusno-remote/remote-lacks-branch/unreachable. Teil 3:fail()vorcollect_changes, auch bei sauberem Baum (Session-Entscheidung, begründet). Dazu eine Dateiliste und die Index-Invariante für den Temp-Index.--breaking-Text des Kandidaten. Das stimmt nicht; der fertigeversion bump-Aufruf steht jetzt unter „Version“.syncExit 0,--no-push-Pfad).size/S→size/M: Drei Teile, zwei Records, eine Instruction und ein eigener Testaufwand sind mehr als „ein klarer Schnitt“.Changelog: Frage A entschieden (Betreiber, 2026-09-30): Auch
no-remotebricht ohne--no-pushvor dem Commit ab; die Session-Entscheidung zum sauberen Baum ist bestätigt.unreachableundno-remoteab, der Befund-2-Tabelle ist eine Spalte für das Verhalten vonsync/publishhinzugefügt..wikitool-remotes.jsonvorher greift.setup-instance.mdSchritt 4 undINSTALL.mdstehen in der Dateiliste, außerdem die Prüfung bestehender Tests, die ohne Remote publizieren.no-remoteohne--no-push; das--no-push-Kriterium deckt jetzt beide Fälle ab.--breaking-Text desversion bump-Aufrufs um „or not configured“ bzw. „local-only instance“ erweitert.Umgesetzt in 8.0.0-beta.10 (
eadc052, README-Nachzug61130ce), CI-Runs 459, 460, 461 grün. Body auf den Endstand gebracht: Kriterien abgehakt, Design als Entscheidung formuliert, Verifikation benannt. Offen bleibt nur die Korpusseitekb/concepts/workflows/Mass-Update Gate.md(beschreibt noch das alte Porcelain-Zählen), bewusst nicht Teil dieses Pakets.Nachprüfung auf Opus (8.0.0-beta.11,
03743eb, CI-Runs 462/463 grün):setup-instance.mdSchritt 15 zeigte den erstenpublishohne--no-pushund kündigte Exit 42 an. Eine lokale Instanz bekommt dort jetzt Exit 1, deshalb nennt der Schritt das Flag. Außerdem nachgezogen: ein Satz ingates.md(das Gate zählte angeblich „working-tree changes before publish stages them“) und der_reconcile_summary-Docstring. Body entsprechend ergänzt.