feat: wikitool upstream merge/verify - code procedure for taking a stack update (4.5.0-beta.1, #30)
CI / verify (push) Successful in 57s
Release / release (push) Successful in 35s

Files changed:
- AGENTS.md
- CHANGES.md
- VERSION
- instructions/gates.md
- instructions/private-instance.md
- tools/CONTRACT.md
- tools/README.md
- tools/chemenu/cli.py
- tools/chemenu/commands/dist_cmd.py
- tools/chemenu/commands/run_budget.py
- tools/chemenu/commands/upstream_cmd.py
- tools/chemenu/ownership.py
- tools/chemenu/tests/test_upstream_cmd.py
This commit is contained in:
2026-09-04 07:08:49 +02:00
parent abe5497cda
commit 686c08bb14
13 changed files with 880 additions and 80 deletions
+48 -1
View File
@@ -35,12 +35,13 @@ dev-checkout concern - readable here, never shipped as something to parse.
---
## 4.4.1-beta.1 - 2026-09-03 - Faktenkorrekturen in der 4.4.0-Prosa; DEVELOPMENT.md ohne zweite Kommandobeschreibung
## 4.5.0-beta.1 - 2026-09-04 - wikitool upstream merge/verify: code procedure for taking a stack update, ownership.py as the shared stack/instance boundary
**Author:** Torben Nehmer
<!-- wikitool:bumps -->
- Faktenkorrekturen in der 4.4.0-Prosa; DEVELOPMENT.md ohne zweite Kommandobeschreibung
- wikitool upstream merge/verify: code procedure for taking a stack update, ownership.py as the shared stack/instance boundary
<!-- /wikitool:bumps -->
Die Prosa zu 4.4.0 - Changelog-Eintrag, `docs/version-model.md`, `instructions/dev/version-parts.md`,
@@ -70,6 +71,52 @@ Kein Verhalten geändert, nur Prosa - und bewusst als laufender Kandidat gelasse
CIs Version-Gate verlangt die `VERSION`-Bewegung, ein Release verlangt sie nicht. Genau dafür gibt
es das Modell aus 4.4.0.
**Zweiter Bump auf demselben Kandidaten (#30):** `git merge upstream/main` behandelt einen
bewegten Korpus asymmetrisch - eine gelöschte, upstream-geänderte Seite meldet sich als Konflikt,
eine neu angelegte Seite wird still gestaged, nur eine beidseitig gelöschte Seite ist harmlos. Die
Prosa-Prozedur in `private-instance.md` § "Taking a stack update" hat das geschlossen, aber mit
vier eigenen Fehlern: der Pfadsatz stand dreifach (im Skript, im Kontroll-Grep, implizit in
`dist_cmd.py`); eine vom Upstream **gelöschte** Maschinerie-Datei wurde von `git checkout
MERGE_HEAD -- <pfad>` still ignoriert, weil das Skript kein `set -e` hatte; ein echter Konflikt in
`tools/`/`types/`/`instructions/` endete in einem von der Prosa nirgends erwähnten offenen Merge;
und ein *neuer* Maschinerie-Pfad unter einer Content-Stage hätte die Literal-Liste nie erreicht.
Die Eigentumsgrenze ist jetzt ein Prädikat statt einer Liste: `chemenu/ownership.py`,
`is_stack_owned(relative)`, wahr für `<stage>/CONTRACT.md` direkt unter einer Content-Stage
(`kb`, `raw`, `work`, `reports`) und für jeden Pfad, der dort auf `.template` endet - nicht
rekursiv, `kb/<collection>/COLLECTION.md` bleibt seit #39 instanzeigen. `dist_cmd.py` liest das
Modul jetzt statt einer eigenen `_CONTENT_ALLOWED_NAMES`-Liste zu pflegen, und
`CONTRACT_ONLY_STAGES` leitet sich aus `ownership.CONTENT_STAGES` ab statt die drei Stage-Pfade
ein zweites Mal aufzuschreiben - ein Test hält fest, dass beide Sichten nicht auseinanderlaufen
können.
Neu: `wikitool upstream merge [--remote upstream] [--branch main] [--no-fetch]` und `wikitool
upstream verify --since <rev> [--until HEAD]`. `merge` prüft Vorbedingungen (sauberer Baum, kein
laufendes Merge, Remote löst auf), warnt statt zu blockieren, wenn `.wikitool-remotes.json` fehlt,
hält den Merge offen (`--no-commit --no-ff`), zwingt jede Content-Stage auf die lokale Seite
zurück, holt dann über die Vereinigungsmenge der Bäume von `MERGE_HEAD` und `HEAD` genau die
stack-eigenen Pfade zurück - inklusive einer Löschung, falls der Upstream einen Maschinerie-Pfad
entfernt hat -, verweigert bei verbliebenen unaufgelösten Pfaden ohne zu committen, committet
sonst und verifiziert den entstandenen Commit mit derselben Logik wie `verify` - ein Fund dort
wird laut gemeldet und **nicht** automatisch zurückgerollt. Nicht idempotent (AGENTS.md § Tool
error contract), nicht budget-exempt; `verify` liest nur und ist wie `migrate verify` von der
Budget-Gate ausgenommen. Die Mass-Update-Gate greift bei einem Merge-Commit strukturell nicht -
das steht jetzt als eigener Absatz in `instructions/gates.md`, mit `upstream merge`s eigener
Nachkontrolle als der Sicherung, die hier tatsächlich trägt.
`private-instance.md` § "Taking a stack update" verweist jetzt auf den Befehl statt das Skript
auszuschreiben; die Pfadtabelle bleibt als Erklärung stehen, ist aber nicht mehr die operative
Liste. Vorschlag B (eigenes Demo-Repo) bleibt zurückgestellt, siehe #30.
18 neue Tests unter `test_upstream_cmd.py` (30 Fälle mit der parametrisierten
`is_stack_owned`-Tabelle) decken die Fälle aus der Spezifikation ab:
gelöschte vs. geänderte vs. neu angelegte Seiten, `kb/CONTRACT.md`- und Template-Änderungen,
`kb/entities/COLLECTION.md` bleibt lokal, eine gelöschte `raw/CONTRACT.md` landet, ein neuer
Template-Pfad landet, ein offener `work/`-Lauf landet nicht, ein echter `tools/`-Konflikt lässt
den Merge offen, ein schmutziger Baum wird unberührt abgewiesen, "bereits aktuell" ist ein No-op,
die Publish-Remote-Gate-Warnung, `verify` gegen einen von Hand verpfuschten Merge, und die
`dist_cmd`/`ownership`-Konsistenz.
---
## 4.4.0 - 2026-09-03 - Versionskandidat statt Bump-pro-Release: VERSION traegt -beta.N, version release fixiert