publish baute die Commit-Message als f"{message}\n\nFiles changed:\n{file_list}" (tools/chemenu/commands/git_publish.py, publish_command). Endete --message mit einem Trailer-Block – etwa Co-Authored-By: … / Claude-Session: …, wie ihn eine Agent-Session anhängt –, stand die Dateiliste danach. Git liest Trailer nur im letzten Absatz der Message, und das war „Files changed:“ samt Liste.
Belegt an 8f61209 (Abschluss von #146) und c77bda2 (#154): git log -1 --format='%(trailers)' und git interpret-trailers --parse waren leer, obwohl die Message beide Zeilen trug. Keiner der 15 Commits vor dem Fix hatte einen lesbaren Co-Authored-By-Trailer. Damit fehlte die Mitautorschaft überall, wo Trailer ausgewertet werden (Gitea- und GitHub-Anzeige, git shortlog --group=trailer:co-authored-by), und zwar bei jedem Publish mit Attribution.
Umsetzung
Keine eigene Trailer-Regex. Die neue Funktion commit_message(message, changed_files) in git_publish.py lässt git urteilen:
git interpret-trailers --parse --no-divider auf --message. Leer → die bisherige Message, byte-identisch.
Sonst wird die Message am letzten Leerzeilen-Absatz geteilt, und der Kandidat ist Kopf + "Files changed:"-Absatz + letzter Absatz.
Der Kandidat gilt nur, wenn interpret-trailers auf ihm dieselben Trailer liest wie auf --message, sonst bleibt die bisherige Message. Damit entscheidet git über jeden Randfall: Fortsetzungszeilen, (cherry picked from …), die 25-%-Regel, die Titelzeile, Kommentarzeilen.
--no-divider, weil git log --format=%(trailers) eine ----Zeile nicht als Ende der Message liest; geprüft mit git 2.54. interpret-trailers läuft in config.ROOT und sieht dieselbe trailer.*-Konfiguration wie git log. _run nimmt dafür ein optionales input= (stdin).
Gate-Tokens unberührt: changeset_token hasht Pfade, Blob-Digests, Threshold, Remote, Branch und --path, rebase_review_token Remote, Branch, die beiden SHAs und die Overlap-Liste. --message geht in keinen der beiden ein.
Akzeptanzkriterien
Nach publish --message "<Betreff>\n\n<Text>\n\nCo-Authored-By: A <a@x>\nClaude-Session: https://…" liefert git log -1 --format='%(trailers:key=Co-Authored-By,valueonly)' genau A <a@x>, und die Message enthält „Files changed:“ samt vollständiger Dateiliste – test_publish_commits_trailers_git_log_can_read. Am echten Repo bestätigt: 80488be selbst ist mit Attribution publiziert, und %(trailers:key=Co-Authored-By,valueonly) liefert Claude Opus 5.5 <noreply@anthropic.com>.
Ohne Trailer-Block ist die Message byte-identisch zur bisherigen – test_a_message_without_a_trailer_block_is_byte_identical_to_before (fünf Fälle) und test_publish_without_trailers_commits_the_same_message_as_before (echter Commit).
Ein Absatz, der nur aussieht wie ein Trailer, wird nicht verschoben. Geprüft sind ein Prosa-Absatz mit Doppelpunkt, ein Trailer als Titelzeile und Trailer, auf die noch ein Absatz folgt. In allen drei Fällen ist interpret-trailers leer, und die Message bleibt unverändert. Die Gegenseite (Fortsetzungszeile, (cherry picked from …) + Signed-off-by neben Freitext, --- im Text, Leerraum am Ende) prüft test_git_reads_the_same_trailers_after_the_file_list_is_added.
Die Umstellung ändert nichts an den Gate-Tokens: --message geht in keinen Token ein. test_a_mass_update_token_does_not_depend_on_the_message zeigt das. Ein Token aus einer Verweigerung mit schlichter Message gibt dasselbe Changeset mit Trailer-Block frei, und die Trailer bleiben lesbar.
Der publish-Datensatz nennt in NOTES, wo die Dateiliste steht, dass ein abschließender Trailer-Block ihr folgt und dass --message in keinen Token eingeht. tools/CONTRACT.md ist per docs contract --apply regeneriert.
docs verify, instructions verify und pytest lokal grün (2057 passed, 3 skipped). CI-Run 497 grün (verify und pwsh), Release-Run 498 grün. Version-Bump --patch auf 8.0.0-beta.23 mit CHANGES.md-Abschnitt.
Nicht im Umfang
Die schon ausgelieferten Commits (8f61209, c77bda2 und alle bis c65d559) bleiben, wie sie sind – ein Umschreiben der Historie bräuchte einen Force-Push, und den schließt Invariante 5 aus.
Ob publish Attribution selbst anhängen sollte, statt sie aus --message zu übernehmen: nicht Teil dieses Befunds. Die Zeilen sind sitzungs- und harness-spezifisch und gehören zu dem, der die Message schreibt.
Kein docs/-Text, keine README, INSTALL.md und keine Instruction behauptet etwas über das Layout der Commit-Message (geprüft per grep). Außer dem publish-Datensatz war nichts nachzuziehen.
## Befund (behoben in 8.0.0-beta.23, `80488be`)
`publish` baute die Commit-Message als `f"{message}\n\nFiles changed:\n{file_list}"` (`tools/chemenu/commands/git_publish.py`, `publish_command`). Endete `--message` mit einem Trailer-Block – etwa `Co-Authored-By: …` / `Claude-Session: …`, wie ihn eine Agent-Session anhängt –, stand die Dateiliste danach. Git liest Trailer nur im **letzten** Absatz der Message, und das war „Files changed:“ samt Liste.
Belegt an `8f61209` (Abschluss von #146) und `c77bda2` (#154): `git log -1 --format='%(trailers)'` und `git interpret-trailers --parse` waren leer, obwohl die Message beide Zeilen trug. Keiner der 15 Commits vor dem Fix hatte einen lesbaren `Co-Authored-By`-Trailer. Damit fehlte die Mitautorschaft überall, wo Trailer ausgewertet werden (Gitea- und GitHub-Anzeige, `git shortlog --group=trailer:co-authored-by`), und zwar bei jedem Publish mit Attribution.
## Umsetzung
Keine eigene Trailer-Regex. Die neue Funktion `commit_message(message, changed_files)` in `git_publish.py` lässt git urteilen:
1. `git interpret-trailers --parse --no-divider` auf `--message`. Leer → die bisherige Message, byte-identisch.
2. Sonst wird die Message am letzten Leerzeilen-Absatz geteilt, und der Kandidat ist `Kopf + "Files changed:"-Absatz + letzter Absatz`.
3. Der Kandidat gilt nur, wenn `interpret-trailers` auf ihm **dieselben** Trailer liest wie auf `--message`, sonst bleibt die bisherige Message. Damit entscheidet git über jeden Randfall: Fortsetzungszeilen, `(cherry picked from …)`, die 25-%-Regel, die Titelzeile, Kommentarzeilen.
`--no-divider`, weil `git log --format=%(trailers)` eine `---`-Zeile nicht als Ende der Message liest; geprüft mit git 2.54. `interpret-trailers` läuft in `config.ROOT` und sieht dieselbe `trailer.*`-Konfiguration wie `git log`. `_run` nimmt dafür ein optionales `input=` (stdin).
Gate-Tokens unberührt: `changeset_token` hasht Pfade, Blob-Digests, Threshold, Remote, Branch und `--path`, `rebase_review_token` Remote, Branch, die beiden SHAs und die Overlap-Liste. `--message` geht in keinen der beiden ein.
## Akzeptanzkriterien
- [x] Nach `publish --message "<Betreff>\n\n<Text>\n\nCo-Authored-By: A <a@x>\nClaude-Session: https://…"` liefert `git log -1 --format='%(trailers:key=Co-Authored-By,valueonly)'` genau `A <a@x>`, und die Message enthält „Files changed:“ samt vollständiger Dateiliste – `test_publish_commits_trailers_git_log_can_read`. Am echten Repo bestätigt: `80488be` selbst ist mit Attribution publiziert, und `%(trailers:key=Co-Authored-By,valueonly)` liefert `Claude Opus 5.5 <noreply@anthropic.com>`.
- [x] Ohne Trailer-Block ist die Message byte-identisch zur bisherigen – `test_a_message_without_a_trailer_block_is_byte_identical_to_before` (fünf Fälle) und `test_publish_without_trailers_commits_the_same_message_as_before` (echter Commit).
- [x] Ein Absatz, der nur *aussieht* wie ein Trailer, wird nicht verschoben. Geprüft sind ein Prosa-Absatz mit Doppelpunkt, ein Trailer als Titelzeile und Trailer, auf die noch ein Absatz folgt. In allen drei Fällen ist `interpret-trailers` leer, und die Message bleibt unverändert. Die Gegenseite (Fortsetzungszeile, `(cherry picked from …)` + `Signed-off-by` neben Freitext, `---` im Text, Leerraum am Ende) prüft `test_git_reads_the_same_trailers_after_the_file_list_is_added`.
- [x] Die Umstellung ändert nichts an den Gate-Tokens: `--message` geht in keinen Token ein. `test_a_mass_update_token_does_not_depend_on_the_message` zeigt das. Ein Token aus einer Verweigerung mit schlichter Message gibt dasselbe Changeset mit Trailer-Block frei, und die Trailer bleiben lesbar.
- [x] Der `publish`-Datensatz nennt in NOTES, wo die Dateiliste steht, dass ein abschließender Trailer-Block ihr folgt und dass `--message` in keinen Token eingeht. `tools/CONTRACT.md` ist per `docs contract --apply` regeneriert.
- [x] `docs verify`, `instructions verify` und `pytest` lokal grün (2057 passed, 3 skipped). CI-Run 497 grün (`verify` und `pwsh`), Release-Run 498 grün. Version-Bump `--patch` auf 8.0.0-beta.23 mit `CHANGES.md`-Abschnitt.
## Nicht im Umfang
- Die schon ausgelieferten Commits (`8f61209`, `c77bda2` und alle bis `c65d559`) bleiben, wie sie sind – ein Umschreiben der Historie bräuchte einen Force-Push, und den schließt Invariante 5 aus.
- Ob `publish` Attribution selbst anhängen sollte, statt sie aus `--message` zu übernehmen: nicht Teil dieses Befunds. Die Zeilen sind sitzungs- und harness-spezifisch und gehören zu dem, der die Message schreibt.
- Kein `docs/`-Text, keine README, `INSTALL.md` und keine Instruction behauptet etwas über das Layout der Commit-Message (geprüft per grep). Außer dem `publish`-Datensatz war nichts nachzuziehen.
Changelog (2026-10-02): Zweiter Beleg im Befund: c77bda2 (#154). %(trailers) und git interpret-trailers --parse sind leer, obwohl --message mit Co-Authored-By:/Claude-Session: endete. Keiner der letzten 15 Commits auf main hat einen lesbaren Trailer. Die Zeilenangabe zum Code ist auf Z. 1377 nachgezogen.
**Changelog (2026-10-02):** Zweiter Beleg im Befund: `c77bda2` (#154). `%(trailers)` und `git interpret-trailers --parse` sind leer, obwohl `--message` mit `Co-Authored-By:`/`Claude-Session:` endete. Keiner der letzten 15 Commits auf `main` hat einen lesbaren Trailer. Die Zeilenangabe zum Code ist auf Z. 1377 nachgezogen.
Changelog (2026-10-02): Umgesetzt in 80488be (8.0.0-beta.23). Body auf Endstand: Befund in der Vergangenheit, der „Entwurf“ heißt jetzt „Umsetzung“, alle Kriterien sind mit ihren Tests abgehakt, CI-Run 497 und Release-Run 498 sind grün, und der Publish-Commit selbst trägt einen lesbaren Co-Authored-By. Geschlossen.
**Changelog (2026-10-02):** Umgesetzt in `80488be` (8.0.0-beta.23). Body auf Endstand: Befund in der Vergangenheit, der „Entwurf“ heißt jetzt „Umsetzung“, alle Kriterien sind mit ihren Tests abgehakt, CI-Run 497 und Release-Run 498 sind grün, und der Publish-Commit selbst trägt einen lesbaren `Co-Authored-By`. Geschlossen.
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 (behoben in 8.0.0-beta.23,
80488be)publishbaute die Commit-Message alsf"{message}\n\nFiles changed:\n{file_list}"(tools/chemenu/commands/git_publish.py,publish_command). Endete--messagemit einem Trailer-Block – etwaCo-Authored-By: …/Claude-Session: …, wie ihn eine Agent-Session anhängt –, stand die Dateiliste danach. Git liest Trailer nur im letzten Absatz der Message, und das war „Files changed:“ samt Liste.Belegt an
8f61209(Abschluss von #146) undc77bda2(#154):git log -1 --format='%(trailers)'undgit interpret-trailers --parsewaren leer, obwohl die Message beide Zeilen trug. Keiner der 15 Commits vor dem Fix hatte einen lesbarenCo-Authored-By-Trailer. Damit fehlte die Mitautorschaft überall, wo Trailer ausgewertet werden (Gitea- und GitHub-Anzeige,git shortlog --group=trailer:co-authored-by), und zwar bei jedem Publish mit Attribution.Umsetzung
Keine eigene Trailer-Regex. Die neue Funktion
commit_message(message, changed_files)ingit_publish.pylässt git urteilen:git interpret-trailers --parse --no-dividerauf--message. Leer → die bisherige Message, byte-identisch.Kopf + "Files changed:"-Absatz + letzter Absatz.interpret-trailersauf ihm dieselben Trailer liest wie auf--message, sonst bleibt die bisherige Message. Damit entscheidet git über jeden Randfall: Fortsetzungszeilen,(cherry picked from …), die 25-%-Regel, die Titelzeile, Kommentarzeilen.--no-divider, weilgit log --format=%(trailers)eine----Zeile nicht als Ende der Message liest; geprüft mit git 2.54.interpret-trailersläuft inconfig.ROOTund sieht dieselbetrailer.*-Konfiguration wiegit log._runnimmt dafür ein optionalesinput=(stdin).Gate-Tokens unberührt:
changeset_tokenhasht Pfade, Blob-Digests, Threshold, Remote, Branch und--path,rebase_review_tokenRemote, Branch, die beiden SHAs und die Overlap-Liste.--messagegeht in keinen der beiden ein.Akzeptanzkriterien
publish --message "<Betreff>\n\n<Text>\n\nCo-Authored-By: A <a@x>\nClaude-Session: https://…"liefertgit log -1 --format='%(trailers:key=Co-Authored-By,valueonly)'genauA <a@x>, und die Message enthält „Files changed:“ samt vollständiger Dateiliste –test_publish_commits_trailers_git_log_can_read. Am echten Repo bestätigt:80488beselbst ist mit Attribution publiziert, und%(trailers:key=Co-Authored-By,valueonly)liefertClaude Opus 5.5 <noreply@anthropic.com>.test_a_message_without_a_trailer_block_is_byte_identical_to_before(fünf Fälle) undtest_publish_without_trailers_commits_the_same_message_as_before(echter Commit).interpret-trailersleer, und die Message bleibt unverändert. Die Gegenseite (Fortsetzungszeile,(cherry picked from …)+Signed-off-byneben Freitext,---im Text, Leerraum am Ende) prüfttest_git_reads_the_same_trailers_after_the_file_list_is_added.--messagegeht in keinen Token ein.test_a_mass_update_token_does_not_depend_on_the_messagezeigt das. Ein Token aus einer Verweigerung mit schlichter Message gibt dasselbe Changeset mit Trailer-Block frei, und die Trailer bleiben lesbar.publish-Datensatz nennt in NOTES, wo die Dateiliste steht, dass ein abschließender Trailer-Block ihr folgt und dass--messagein keinen Token eingeht.tools/CONTRACT.mdist perdocs contract --applyregeneriert.docs verify,instructions verifyundpytestlokal grün (2057 passed, 3 skipped). CI-Run 497 grün (verifyundpwsh), Release-Run 498 grün. Version-Bump--patchauf 8.0.0-beta.23 mitCHANGES.md-Abschnitt.Nicht im Umfang
8f61209,c77bda2und alle bisc65d559) bleiben, wie sie sind – ein Umschreiben der Historie bräuchte einen Force-Push, und den schließt Invariante 5 aus.publishAttribution selbst anhängen sollte, statt sie aus--messagezu übernehmen: nicht Teil dieses Befunds. Die Zeilen sind sitzungs- und harness-spezifisch und gehören zu dem, der die Message schreibt.docs/-Text, keine README,INSTALL.mdund keine Instruction behauptet etwas über das Layout der Commit-Message (geprüft per grep). Außer dempublish-Datensatz war nichts nachzuziehen.Changelog (2026-10-02): Zweiter Beleg im Befund:
c77bda2(#154).%(trailers)undgit interpret-trailers --parsesind leer, obwohl--messagemitCo-Authored-By:/Claude-Session:endete. Keiner der letzten 15 Commits aufmainhat einen lesbaren Trailer. Die Zeilenangabe zum Code ist auf Z. 1377 nachgezogen.Changelog (2026-10-02): Umgesetzt in
80488be(8.0.0-beta.23). Body auf Endstand: Befund in der Vergangenheit, der „Entwurf“ heißt jetzt „Umsetzung“, alle Kriterien sind mit ihren Tests abgehakt, CI-Run 497 und Release-Run 498 sind grün, und der Publish-Commit selbst trägt einen lesbarenCo-Authored-By. Geschlossen.