fix: private-instance - Demo-Korpus wandert beim Merge mit, Prozedur korrigiert (2.2.1)
CI / verify (push) Successful in 43s
Release / release (push) Successful in 38s

Files changed:
- CHANGES.md
- VERSION
- instructions/private-instance.md
This commit is contained in:
2026-09-01 19:03:23 +02:00
parent 29063f511b
commit b2f7dec122
3 changed files with 98 additions and 8 deletions
+44
View File
@@ -20,6 +20,50 @@ their date-only headings.
--- ---
## 2.2.1 - 2026-09-01 - private-instance: der Demo-Korpus wandert beim Merge doch mit - Prozedur korrigiert
**Author:** Torben Nehmer
`instructions/private-instance.md` behauptete in 2.2.0, ein `git merge upstream/main` löse
Änderungen am Demo-Korpus stillschweigend auf, weil die private Instanz ihn einmal gelöscht hat:
*deleted-in-ours, unmodified-in-theirs*. Das war **nicht gemessen, sondern angenommen** — und es
ist falsch. Ein Nachbau mit einem Upstream, der seinen Korpus bewegt, zeigt drei verschiedene
Verhalten:
| Upstream tut | `git merge upstream/main` tut |
|---|---|
| ändert eine Seite, die du gelöscht hast | `CONFLICT (modify/delete)` — und **lässt die Upstream-Fassung im Arbeitsbaum liegen**. Ein `git add -A` beim Auflösen holt die Demo-Seite zurück. |
| legt eine neue Seite an | staged sie **stillschweigend**. Kein Konflikt, keine Meldung. |
| löscht eine Seite, die du auch gelöscht hast | nichts. Der einzige harmlose Fall. |
Die mittlere Zeile ist die gefährliche, weil nichts sie ankündigt. Ein Upstream, der einen
Demo-Korpus ausliefert **und** ihn als Testbett benutzt, legt Seiten an — und jede einzelne
landet in der privaten Instanz und taucht dort in `lint`, `index`, `search` und
`confidence decay` auf. Genau diese Doppelnutzung beschreibt Issue #28.
**Korrigiert:** Die Update-Prozedur hält den Merge mit `--no-commit` offen, zwingt `kb/` und
`raw/` danach auf den eigenen Stand zurück (`git rm --cached`, `rm -rf`, `git checkout HEAD --`)
und schließt ihn erst dann. Solange der Merge offen ist, zeigt `HEAD` noch auf den Commit davor,
und genau das macht den Schritt sauber. Anschließend eine Kontrolle, die man nicht überlesen
kann:
```bash
git diff --name-only $BEFORE HEAD -- kb raw # muss leer sein
```
Das Rezept ist wörtlich so nachgespielt worden, wie es jetzt in der Datei steht — mit einem
Upstream, der gleichzeitig eine Seite ändert, eine anlegt, eine löscht und dasselbe unter
`raw/` tut. Ergebnis: Stack aktualisiert, nur eigener Inhalt übrig, Kontrolle leer,
Arbeitsbaum sauber.
**Auch die Decision Points korrigiert.** „Konflikt in `kb/` per Hand als *keep deleted*
auflösen" stand vorher da und ist der Rat, der in die Falle führt: `git add -A` committet die
Fassung, die git im Arbeitsbaum liegen gelassen hat.
**Dateien:** `instructions/private-instance.md`.
---
## 2.2.0 - 2026-09-01 - Publish-Remote Gate: publish schreibt nur an erklaerte Ziele ## 2.2.0 - 2026-09-01 - Publish-Remote Gate: publish schreibt nur an erklaerte Ziele
**Author:** Torben Nehmer **Author:** Torben Nehmer
+1 -1
View File
@@ -1 +1 @@
2.2.0 2.2.1
+53 -7
View File
@@ -25,9 +25,24 @@ merge, so it cannot notice that the receiving instance changed a file, and it ha
surface, so nobody learns when upstream and local both touched the same one. It overwrites surface, so nobody learns when upstream and local both touched the same one. It overwrites
silently. silently.
A clone gets all of that from git. The private `main` deletes the upstream's demo corpus once; A clone gets all of that from git. Stack changes land as real merges, with real conflicts where
every later `git merge upstream/main` sees *deleted-in-ours, unmodified-in-theirs* and resolves they conflict.
without asking. Stack changes land as real merges, with real conflicts where they conflict.
**What a plain `git merge` does *not* give you is protection from the upstream's content.** The
private `main` deletes the demo corpus once, but that deletion does not make later upstream
changes to those paths go away. Measured, not assumed:
| Upstream does | `git merge upstream/main` does |
|---|---|
| modifies a page you deleted | `CONFLICT (modify/delete)` - and **leaves the upstream version in your working tree**. Resolve it with `git add -A` and the demo page is back. |
| adds a new page | stages it **silently**. No conflict, no prompt, no mention. |
| deletes a page you also deleted | nothing. The only harmless case. |
The middle row is the one that matters, because nothing announces it. An upstream that ships a
demo corpus *and* uses it as a test bed will add pages, and each one arrives in your instance
and starts showing up in your `lint`, your `index`, your `search` and your `confidence decay`.
So the merge has to be scoped. That is the procedure below, and it is not optional.
## Steps ## Steps
@@ -87,15 +102,43 @@ without asking. Stack changes land as real merges, with real conflicts where the
## Taking a stack update ## Taking a stack update
Take the machinery, never the content. The merge is held open, the content stages are forced
back to your own state, and only then does it close:
```bash ```bash
BEFORE=$(git rev-parse HEAD)
git fetch upstream git fetch upstream
git merge upstream/main
# --no-commit holds the merge open; it may report conflicts under kb/ or raw/,
# which the next three lines are about to make irrelevant.
git merge --no-commit --no-ff upstream/main || true
# Whatever the merge did to the content stages, undo it. HEAD is still your
# pre-merge commit while the merge is open, so this restores exactly your side.
git rm -rq --cached --ignore-unmatch kb raw
rm -rf kb raw
git checkout HEAD -- kb raw
git commit --no-edit
``` ```
Then **check that it worked**, rather than trusting that it did:
```bash
git diff --name-only $BEFORE HEAD -- kb raw # must print nothing
```
An empty result is the proof that the update touched machinery only. A non-empty one means a
path slipped through - inspect it before going further.
Then, as after any stack change: `doctor`, `docs verify`, `instructions verify`, `migrate status`, Then, as after any stack change: `doctor`, `docs verify`, `instructions verify`, `migrate status`,
`lint`. A `migrate status` with outstanding links means the update crossed a compatibility `lint`. A `migrate status` with outstanding links means the update crossed a compatibility
boundary - follow [migrate-corpus.md](migrate-corpus.md) before doing anything else. boundary - follow [migrate-corpus.md](migrate-corpus.md) before doing anything else.
**Why not just `git merge upstream/main`?** Because of the table above: a page the upstream
*adds* arrives with no conflict and no message. You would find out when `lint` starts reporting
pages you never wrote - if you noticed at all.
## Where stack development happens ## Where stack development happens
**In the public repo, not here.** That is not a preference; the stack is built that way. The **In the public repo, not here.** That is not a preference; the stack is built that way. The
@@ -110,9 +153,12 @@ merge above. Nothing is lost by the detour: the fix has to pass that CI either w
## Decision points ## Decision points
- **Merge conflict in `kb/` or `raw/`?** Something changed the upstream's corpus after you cut - **Merge conflict in `kb/` or `raw/`?** Expected, and already handled: the update procedure
it. Resolve as "keep deleted" - your instance's content is yours, and the upstream's demo above overwrites those stages with your own afterwards, so the conflict resolves itself.
corpus has no business in it. Never resolve one by hand with `git add -A` - that is exactly how the upstream version, which
git left sitting in your working tree, gets committed into your instance.
- **`git diff` after the merge shows something under `kb/` or `raw/`?** Stop. The scoping step
did not take. Do not publish; find out which path came through and where from.
- **Conflict in `tools/`, `types/` or `instructions/`?** You changed the stack locally, which - **Conflict in `tools/`, `types/` or `instructions/`?** You changed the stack locally, which
step "Where stack development happens" says not to do. Take the upstream side and re-file the step "Where stack development happens" says not to do. Take the upstream side and re-file the
change as an issue there. change as an issue there.