ingest: Public Release, Corpus Purge and History Squash Session 2026-09-01

Files changed:
- kb/concepts/Delete Rather Than Anonymize.md
- kb/concepts/Dual Licensing by File Plan.md
- kb/concepts/INDEX.md
- kb/entities/projects/Chemenu.md
- kb/entities/tools/wikitool.md
- kb/index.md
- kb/log.md
- kb/provenance.md
- kb/sources/INDEX.md
- kb/sources/Source - Public Release, Corpus Purge and History Squash Session 2026-09-01.md
- raw/notes/Conversation Transcript - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md
- raw/notes/Conversation Transcript - Public Release, Corpus Purge and History Squash Session 2026-09-01.md
- raw/notes/Conversation Transcript - Publish-Remote Gate and Issue Triage Session 2026-09-01.md
This commit is contained in:
2026-09-01 20:32:05 +02:00
parent 32a9b8eb3f
commit 00c2cf6ffe
13 changed files with 776 additions and 13 deletions
@@ -0,0 +1,72 @@
---
type: types/concept.md
concept_type: decision
tags: []
created: 2026-09-01
modified: 2026-09-01
related: [Chemenu]
sources: ['Source - Public Release, Corpus Purge and History Squash Session 2026-09-01']
confidence: 0.90
confidence_base: 0.70
provenance: sourced
summary: 'Private Korpusinhalte per Loeschung entfernen statt zu anonymisieren: ein Seitentitel ist der einzige Identifier eines Wikis, Umbenennen ist die volle page-lifecycle-Prozedur je Seite, Loeschen ist ein unterstuetztes Kommando.'
---
# Delete Rather Than Anonymize
**Typ:** Decision
## Definition
Wenn private oder sensible Inhalte aus einem Wiki entfernt werden müssen, ist Löschen einer
zugehörigen Seite in der Regel dem Anonymisieren (Umbenennen, Ersetzen sensibler Details bei
sonst unverändertem Inhalt) vorzuziehen - wenn ein unterstütztes Löschkommando existiert.
## Kernpunkte
- Ein Seitentitel ist in einem verlinkten Wiki oft der **einzige Identifier** einer Seite: Er
lebt in Wikilinks, Zitatmarkern und Frontmatter-Arrays jeder referenzierenden Seite. Ihn zu
ändern (Anonymisieren durch Umbenennen) verlangt deshalb eine vollständige Rename-Prozedur pro
betroffener Seite - bei mehreren zusammenhängenden Seiten multipliziert sich der Aufwand.
- Löschen dagegen ist ein einzelner, unterstützter Vorgang, der eine Seite mechanisch aus dem
Rest des Wikis de-linkt (bekannte Referenzarten: Frontmatter-Felder, ganzzeilige
Verweis-Aufzählungen). Er ist damit für strukturelle Bereinigung **schneller und weniger
fehleranfällig** als Anonymisierung.
- Bei Inhalten, die eine reale Topologie beschreiben (z. B. eine Infrastrukturdokumentation),
entschärft Anonymisieren einzelner Bezeichner (Hostnamen, IP-Adressen) die eigentliche
Preisgabe nicht: Die Struktur - welche Systeme wie zusammenhängen - bleibt erhalten, auch wenn
die Namen ausgetauscht sind.
- **Grenze der Methode:** Ein mechanisches Löschkommando entfernt typischerweise nur
strukturelle Referenzen (Frontmatter, Aufzählungen), nicht zwingend Erwähnungen im Fließtext
einer anderen Seite. Nach der Löschung ist eine gezielte Nachkontrolle nötig, ob der entfernte
Name noch im Klartext irgendwo im Wiki steht.
## Wann zu verwenden
- Der zu entfernende Inhalt ist als eigenständige Seite oder eigenständige Seitengruppe
abgrenzbar.
- Ein Löschkommando existiert, das Referenzen mechanisch bereinigt (nicht ein bloßes Entfernen
der Datei, das tote Links hinterlässt).
- Der Inhalt beschreibt eine reale, zusammenhängende Struktur (Infrastruktur, ein Netzwerk, eine
Organisation), bei der einzelne Bezeichner austauschen die eigentliche Preisgabe nicht behebt.
## Wann NICHT zu verwenden
- Wenn nur ein einzelner sensibler Wert innerhalb einer sonst wertvollen, generischen Seite
steht (z. B. ein Firmenname als Beispiel in einer sonst allgemeingültigen Anleitung) - dort ist
gezieltes Redigieren der Seite treffender als sie komplett zu verwerfen.
- Wenn die Seite Beziehungen trägt, die für sich genommen wertvoll und nicht sensibel sind - dann
kann eine Neufassung mit generischem Beispiel sinnvoller sein als Löschung.
## Verwandte Concepts
- [[Mass-Update Gate]]
## Beziehungen
- **gilt fuer:** [[Chemenu]]
## Siehe auch
- [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]]
- [[Chemenu]]
@@ -0,0 +1,71 @@
---
type: types/concept.md
concept_type: decision
tags: []
created: 2026-09-01
modified: 2026-09-01
related: [Chemenu]
sources: ['Source - Public Release, Corpus Purge and History Squash Session 2026-09-01']
confidence: 0.50
confidence_base: 0.70
provenance: sourced
summary: Ein Repo mit Code- und Inhaltsanteil erhaelt zwei Lizenzen; die Grenze zwischen ihnen ist kein zweiter, gepflegter Pfadkatalog, sondern der ohnehin vorhandene Dateiplan des Distributionswerkzeugs.
---
# Dual Licensing by File Plan
**Typ:** Decision
## Definition
Ein Repository, das sowohl Werkzeug-Code als auch inhaltliches Material (Dokumentation, Daten,
kompiliertes Wissen) enthält, bekommt zwei Lizenzdateien statt einer - eine für den Code, eine
für den Inhalt. Welche Datei zu welcher Lizenz gehört, wird nicht in einer eigenen, zweiten
Liste festgehalten, sondern aus dem Dateiplan abgeleitet, den ein vorhandenes
Distributions-/Build-Werkzeug ohnehin pflegt.
## Kernpunkte
- Der naheliegende Fehler ist, die Grenze zwischen „Code" und „Inhalt" als eigene, gepflegte
Aufzählung von Pfaden in der Lizenzdatei selbst festzuschreiben. Das ist eine zweite Kopie
einer Regel, die bereits an anderer Stelle existiert (dem Dateiplan des Build-/
Distributionswerkzeugs) - und die Kopie, die driftet, wenn sich Verzeichnisse verschieben.
- Stattdessen verweist die Lizenz-Notiz auf den bestehenden Plan (z. B. eine Funktion, die
berechnet, was in eine Distribution exportiert wird und was nicht) als **einzige** Quelle der
Wahrheit für die Grenze.
- Welche der beiden Lizenzen den generischen Dateinamen `LICENSE` trägt, ist keine
Nebensächlichkeit: Es sollte die Lizenz sein, die ein Code-Hosting-Dienst (Forge) für das
Repository insgesamt meldet - typischerweise die restriktivere/Copyleft-Lizenz. Ein Leser, der
eine Copyleft-Pflicht übersieht, wird dadurch geschädigt; wer eine Pflicht zu viel annimmt,
nicht.
- Ein Distributions-Export, der Code unter einer Copyleft-Lizenz ausliefert, muss die
zugehörige Lizenzdatei zwingend mitliefern (nicht optional, nicht still übersprungen, wenn sie
fehlt) - sonst ist die exportierte Instanz eine Lizenzverletzung, sobald sie veröffentlicht
wird.
## Wann zu verwenden
- Ein Repository trägt sowohl Software-/Werkzeugcode als auch Inhalt mit eigenem
Urheberrechtscharakter (Dokumentation, Wissensbasis, Daten), für die unterschiedliche Lizenzen
angemessen sind.
- Es existiert bereits ein Werkzeug, das programmatisch entscheidet, welche Dateien zu welcher
Kategorie gehören (z. B. für einen Export- oder Build-Schritt).
## Wann NICHT zu verwenden
- Bei einem Repository, dessen Inhalt untrennbar mit dem Code verwoben ist und für das keine
separate, maschinell nachvollziehbare Grenze existiert - dort wäre die Lizenz-Zuordnung selbst
wieder eine unabhängige, drift-anfällige Liste.
## Verwandte Concepts
- [[Chemenu]]
## Beziehungen
- **gilt fuer:** [[Chemenu]]
## Siehe auch
- [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]]
- [[Chemenu]]
+3 -1
View File
@@ -2,7 +2,7 @@
# kb/concepts/ - Index
76 page(s). Regenerated by `wikitool index rebuild`.
78 page(s). Regenerated by `wikitool index rebuild`.
## All
@@ -25,9 +25,11 @@
| [[CPPC]] | protocol | Hardwareschnittstelle Collaborative Processor Performance Control für feingranulares CPU-Power-Management zwischen Betriebssystem und AMD-Prozessor. | 2026-08-29 |
| [[Cross-platform Agent Skills]] | architecture | Architektur fuer Agent-Skills, die ueber mehrere LLM-Werkzeuge hinweg funktionieren; in Chemenu selbst am 2026-08-04 umgesetzt und ueberprueft | 2026-09-01 |
| [[Crystallization]] | workflow | Verdichten abgeschlossener Erkundungen, Debugging-Sitzungen und Recherchen zu strukturierten Wiki-Auszügen als eigenständige Wissensquellen. | 2026-08-29 |
| [[Delete Rather Than Anonymize]] | decision | Private Korpusinhalte per Loeschung entfernen statt zu anonymisieren: ein Seitentitel ist der einzige Identifier eines Wikis, Umbenennen ist die volle page-lifecycle-Prozedur je Seite, Loeschen ist ein unterstuetztes Kommando. | 2026-09-01 |
| [[Denylist over Allowlist]] | decision | Entscheidung, schreibbare Felder als Schema minus kurzer Sperrliste zu bestimmen statt als gepflegte Positivliste, weil die Positivliste eine zweite Kopie des Schemas waere | 2026-08-31 |
| [[Detect-Repair Asymmetry]] | problem | Werkzeugluecke, in der ein Check einen Defekt zuverlaessig meldet, aber kein Befehl ihn behebt - womit die Handeditierung der einzige verbleibende Ausweg ist | 2026-08-31 |
| [[Diff-Reviewable Agent Edits]] | decision | Entscheidung, Dateiaenderungen ueber Edit/Write statt ueber Shell-Heredocs zu fahren, weil nur das erste eine pruefbare Diff hinterlaesst | 2026-08-31 |
| [[Dual Licensing by File Plan]] | decision | Ein Repo mit Code- und Inhaltsanteil erhaelt zwei Lizenzen; die Grenze zwischen ihnen ist kein zweiter, gepflegter Pfadkatalog, sondern der ohnehin vorhandene Dateiplan des Distributionswerkzeugs. | 2026-09-01 |
| [[Entity Extraction]] | pattern | Erkennen und Strukturieren von Entities (Personen, Projekte, Bibliotheken, Concepts, Dateien, Entscheidungen, Systeme, Werkzeuge) samt typspezifischer Attribute aus Rohquellen. | 2026-08-29 |
| [[Episodic Memory]] | architecture | Speicherschicht für verdichtete Sitzungszusammenfassungen und Befunde; Brücke zwischen rohem Working Memory und langlebigem Semantic Memory. | 2026-08-29 |
| [[Event-Driven Automation]] | workflow | Muster, das automatische Auslöser an Wiki-Lebenszyklusereignisse hängt, um manuellen Pflegeaufwand und das Risiko der Verwahrlosung zu senken. | 2026-08-29 |
+7 -2
View File
@@ -4,8 +4,8 @@ entity_type: project
tags: [wiki, llm, knowledge-base]
created: 2026-08-04
modified: 2026-09-01
related: [Personalization Plane, Issue Label Scheme, Optional Instance Context File]
sources: [Source - Copilot Skill Restructure Instructions, Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04, Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30, Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31, Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31, Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31, Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31, Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31, Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31]
related: [Personalization Plane, Issue Label Scheme, Optional Instance Context File, Delete Rather Than Anonymize, Dual Licensing by File Plan]
sources: [Source - Copilot Skill Restructure Instructions, Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04, Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30, Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31, Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31, Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31, Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31, Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31, Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31, 'Source - Public Release, Corpus Purge and History Squash Session 2026-09-01']
confidence: 0.90
confidence_base: 0.90
provenance: mixed
@@ -60,6 +60,8 @@ Das Repository hat bereits ein deterministisches CLI, `tools/wikitool` (Python,
- **verwendet:** [[Personalization Plane]]
- **verwendet:** [[Issue Label Scheme]]
- **verwendet:** [[Optional Instance Context File]]
- **wendet an:** [[Delete Rather Than Anonymize]]
- **wendet an:** [[Dual Licensing by File Plan]]
## Details
@@ -210,6 +212,9 @@ Repositorys selbst und keine Aussagen aus einer Rohdatenquelle; der Änderungsda
- [[Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31]]
- [[Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31]]
- [[Optional Instance Context File]]
- [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]]
- [[Delete Rather Than Anonymize]]
- [[Dual Licensing by File Plan]]
## Fußnoten
+17 -1
View File
@@ -5,7 +5,7 @@ tags: [cli, automation, deterministic, wiki-management]
created: 2026-08-03
modified: 2026-09-01
related: [Semantic Lint Automation, Session Orientation, Iteration and Cost Limits, KB Stack Versioning, KB Migration, Personalization Plane, Detect-Repair Asymmetry, Write-Once Frontmatter Fields, Denylist over Allowlist, Command Round-Trip Integrity, Green Suite Blind Spot, Ambient Environment Dependency, Structural Enforcement over Documented Rule, Optional Instance Context File]
sources: [Source - LLM Improvements Codex Analysis, Source - LLM Improvements Sonnet Analysis, Source - Copilot Skill Restructure Instructions, Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04, Source - LLM Improvements Production Agent Gaps 2026, Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30, Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31, Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31, Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31, Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31, Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31, Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31, Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31, Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31]
sources: [Source - LLM Improvements Codex Analysis, Source - LLM Improvements Sonnet Analysis, Source - Copilot Skill Restructure Instructions, Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04, Source - LLM Improvements Production Agent Gaps 2026, Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30, Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31, Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31, Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31, Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31, Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31, Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31, Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31, Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31, 'Source - Public Release, Corpus Purge and History Squash Session 2026-09-01']
confidence: 0.90
confidence_base: 0.90
provenance: sourced
@@ -147,6 +147,20 @@ ist[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30].
## Historie
- 2026-09-01 - `2.1.0`-`2.2.2`: Vorbereitung und Durchführung der Veröffentlichung. `dist export`
bekommt `REQUIRED_ROOT_FILES` (fehlende Lizenzdateien lassen den Export scheitern statt still
weiterzulaufen) und `find_leaks()` (strukturelle Prüfung des fertigen Export-Plans gegen
Personalisierungsdateien, `instructions/dev/`, `kb/`- und `raw/`-Inhalte - bewusst kein
Text-Muster-Scan, weil der eigene Hostname legitim in `INSTALL.md`/`version.py` steht). `publish`
bekommt ein drittes Gate: das **Publish-Remote-Gate** prüft die aufgelöste Push-URL (nicht den
Remote-Namen) gegen eine optionale, gitignorete `.wikitool-remotes.json` und hat als einziges
der drei Gates keinen `--confirm`-Token - der Weg daran vorbei ist ein bewusster Edit der
Datei durch den Nutzer, nie durch einen Agenten. `doctor` bekommt den `publish-remotes`-Check.
Ein `raw_dir`-Testfixture löste `config.ROOT` gegen das echte Repo-Root statt die Fixture auf
und bestand nur, weil zufällig ein Verzeichnis existierte, das der Korpus-Schnitt entfernte -
in der Fixture geschlossen, nicht im einzelnen Test, aus demselben Grund wie Gitea #8.
Siehe [[Chemenu]], [[Mass-Update Gate]], [[Delete Rather Than Anonymize]],
[[Dual Licensing by File Plan]][^s-public-release-corpus-purge-and-history-squash-session-2026-09-01]
- 2026-09-01 - `2.0.0` (Commit `9a7abe6`, 730 Tests grün): das Python-Paket heißt `chemenu`
statt `wiki_tools`, **das Kommando bleibt `wikitool`**. Der Import-Name eines Pakets ist ein
flacher globaler Namensraum ohne Kollisionsschutz, `wiki_tools` war dafür zu generisch;
@@ -249,6 +263,7 @@ ist[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30].
- [[Structural Enforcement over Documented Rule]]
- [[Optional Instance Context File]]
- [[Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31]]
- [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]]
## Fußnoten
@@ -261,3 +276,4 @@ ist[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30].
[^s-conversation-agents-md-skill-restructuring-session-2026-08-04]: [[Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04]]
[^s-conversation-hardening-the-test-suite-against-silent-environment-dependencies-session-2026-08-31]: [[Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31]]
[^s-llm-improvements-codex-analysis]: [[Source - LLM Improvements Codex Analysis]]
[^s-public-release-corpus-purge-and-history-squash-session-2026-09-01]: [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]]
+5 -5
View File
@@ -13,11 +13,11 @@ The page tables live in a generated `INDEX.md` inside each collection, linked be
## Statistics
- **Total Pages:** 170
- **Total Pages:** 173
- **Comparisons:** 1
- **Concepts:** 76
- **Concepts:** 78
- **Entities:** 72
- **Sources:** 21
- **Sources:** 22
- **Last Updated:** 2026-09-01
---
@@ -27,9 +27,9 @@ The page tables live in a generated `INDEX.md` inside each collection, linked be
| Collection | Pages | Index |
|------------|------:|-------|
| `comparisons/` | 1 | [comparisons/INDEX.md](comparisons/INDEX.md) |
| `concepts/` | 76 | [concepts/INDEX.md](concepts/INDEX.md) |
| `concepts/` | 78 | [concepts/INDEX.md](concepts/INDEX.md) |
| `entities/` | 72 | [entities/INDEX.md](entities/INDEX.md) |
| `sources/` | 21 | [sources/INDEX.md](sources/INDEX.md) |
| `sources/` | 22 | [sources/INDEX.md](sources/INDEX.md) |
### entities/
+6
View File
@@ -55,3 +55,9 @@ und `doctor` grün.
Die Seite beschrieb sich als persoenliches IT-Wissenswiki; seit der Veroeffentlichung ist diese Instanz Testbett und oeffentliche Demo. Beschreibung, Zweck und Lizenz nachgezogen, die historische Aussage ueber die monolithische AGENTS.md als Ausgangspunkt datiert statt geloescht.
---
## [2026-09-01] ingest | raw/notes/Conversation Transcript - Public Release, Corpus Purge and History Squash Session 2026-09-01.md
Source-Seite angelegt, Chemenu und wikitool aktualisiert, zwei neue Concept-Seiten (Delete Rather Than Anonymize, Dual Licensing by File Plan), quer verlinkt.
---
+16 -3
View File
@@ -8,9 +8,9 @@ inline `[^cite-id]` footnote).
## Coverage Summary
- **Total raw files:** 21
- **Covered:** 21
- **Uncovered:** 0
- **Total raw files:** 24
- **Covered:** 22
- **Uncovered:** 2
---
@@ -76,6 +76,19 @@ inline `[^cite-id]` footnote).
- Covered by: [[Source - Conversation - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31]]
- Cited by: [[CI Integration]], [[Gitea Actions]]
### `raw/notes/Conversation Transcript - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md`
No source page covers this file yet.
### `raw/notes/Conversation Transcript - Public Release, Corpus Purge and History Squash Session 2026-09-01.md`
- Covered by: [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]]
- Cited by: [[Chemenu]], [[Delete Rather Than Anonymize]], [[Dual Licensing by File Plan]], [[wikitool]]
### `raw/notes/Conversation Transcript - Publish-Remote Gate and Issue Triage Session 2026-09-01.md`
No source page covers this file yet.
### `raw/notes/Conversation Transcript - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md`
- Covered by: [[Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31]]
+2 -1
View File
@@ -2,7 +2,7 @@
# kb/sources/ - Index
21 page(s). Regenerated by `wikitool index rebuild`.
22 page(s). Regenerated by `wikitool index rebuild`.
## All
@@ -28,5 +28,6 @@
| [[Source - LLM Improvements Sonnet Analysis]] | notes | Sonnet-Analyse, die AGENTS.md und wikitool mit Farzas Gist und awesome-llm-wiki vergleicht und die Codex-Analyse um konkrete Empfehlungen zu Qualitätsschwellen, Stilrichtlinie, Auditrhythmus und Skalierung ergänzt | 2026-08-03 |
| [[Source - LLM Wiki Pattern]] | article | Grundlegendes Muster für persönliche Wissensbasen mit LLMs: ein dauerhaftes Wiki schrittweise pflegen, statt es aus den Quellen neu herzuleiten. | 2026-07-26 |
| [[Source - LLM Wiki v2]] | article | Erweitertes LLM-Wiki-Muster mit Praxiserfahrungen aus agentmemory zu Memory Lifecycle, Confidence Scoring, Wissensgraph und Automatisierung. | 2026-07-26 |
| [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]] | notes | Sitzung, die den Chemenu-Stack von einer privaten Testinstanz in ein oeffentliches Repo ueberfuehrt: Korpus geloescht statt anonymisiert, Git-History auf einen Commit gesquashed, AGPL-3.0/CC-BY-4.0-Dual-Lizenz gewaehlt, dist export um einen Leak-Canary gehaertet. | 2026-09-01 |
| [[Source - Wine]] | notes | Wine-Konfiguration für Arch Linux: pacman-NoExtract-Einstellungen und Bottles-Runtime-Optionen einschließlich Proton- und Lutris-Varianten. | 2026-08-01 |
@@ -0,0 +1,87 @@
---
type: types/source.md
source_type: notes
author: Torben
raw_files: ['raw/notes/Conversation Transcript - Public Release, Corpus Purge and History Squash Session 2026-09-01.md']
source_language: de
date: 2026-09-01
tags: []
entities: [Chemenu, wikitool]
concepts: [Mass-Update Gate, Delete Rather Than Anonymize, Dual Licensing by File Plan]
summary: 'Sitzung, die den Chemenu-Stack von einer privaten Testinstanz in ein oeffentliches Repo ueberfuehrt: Korpus geloescht statt anonymisiert, Git-History auf einen Commit gesquashed, AGPL-3.0/CC-BY-4.0-Dual-Lizenz gewaehlt, dist export um einen Leak-Canary gehaertet.'
---
# Source: Public Release, Corpus Purge and History Squash Session 2026-09-01
**Autor:** Torben
**Datum:** 2026-09-01
**Raw-Dateien:** raw/notes/Conversation Transcript - Public Release, Corpus Purge and History Squash Session 2026-09-01.md
**Typ:** Notes
## Zusammenfassung
Torben bat darum, den Chemenu-Korpus zu bereinigen und das Repo zu veröffentlichen, mit
ausdrücklichem Wunsch nach Teufels-Advokat-Modus und einer kleinen Multi-Agent-Debatte. Drei
parallele Explore-Agenten inventarisierten private Daten, den Distributionsmechanismus und die
Git-History; die History-Prüfung erklärte den Baum fälschlich für „safe to publish", ohne
`USER.md` je zu öffnen — ein Befund, der später den Ausschlag für den vollständigen History-Schnitt
gab. Drei geforkte Debattierer (harte Trennung, geteiltes Upstream, Teufels-Advokat) argumentierten
gegeneinander; die Synthese übernahm „löschen statt anonymisieren" und „History squashen" von der
harten Position, das Clone-mit-Upstream-Modell von der geteilten Position, aber unter der
Bedingung, dass ein Remote-Gate zuerst existiert — eine Bedingung, die der Teufels-Advokat mit
seinem Leck-Argument erzwang.
Nutzer traf vier Entscheidungen über `AskUserQuestion`: Gitea öffentlich schalten (kleinste
Änderung), Korpus chirurgisch löschen, private Instanz als Clone mit Upstream und Gate zuerst,
und als Lizenz AGPL-3.0 (Stack) + CC-BY-4.0 (Inhalte) — die Affero-Variante bewusst wegen Issue
#19 (MCP-Frontend als Netzdienst).
Ausgeführt wurde: Lizenzdateien (AGPL-Text von gnu.org geholt, nicht aus dem Gedächtnis
rekonstruiert), ein Leak-Canary in `dist export` (`find_leaks()`, strukturell statt textbasiert,
weil ein Muster-Scan den eigenen legitimen Host mit ausschließen müsste), die Korpus-Löschung
(108 Seiten statt der im Plan geschätzten ~35, weil 40 Seiten mit generischen Titeln tatsächlich
um die private Infrastruktur herum geschrieben waren), der History-Squash auf einen Commit, und
die Veröffentlichung selbst.
Zwei Annahmen wurden durch Messung widerlegt und korrigiert: Ein Force-Push allein reicht nicht —
der alte HEAD blieb per SHA abrufbar, bis Reflogs auf dem Server verfielen und `gc --prune=now`
lief. Und `rg`-Scans ohne `--hidden` übersehen `.gitea/`, `.github/`, `.vibe/` — ein zweiter
Fund (private Referenzen in `ci.yml`) kam erst über `git grep` zum Vorschein.
## Kernaussagen
- Ein Seitentitel ist der einzige Identifier des Wikis; Löschen (`wikitool rm`) ist dafür billiger
und sicherer als Anonymisieren, das die volle `page-lifecycle`-Prozedur pro Seite verlangt.
- Der eigentliche Preisgeber bei einem Infrastruktur-Handbuch ist die Topologie, nicht der
Hostname — gefälschte IPs entschärfen keine Angriffskarte.
- Ein Force-Push macht alte Commits unreferenziert, aber nicht unerreichbar: Sie bleiben per SHA
fetchbar, bis Server-Reflogs verfallen sind und `git gc --prune=now` gelaufen ist.
- `dist export`s Lizenz-Dateien mussten zur Pflicht werden (`REQUIRED_ROOT_FILES`), weil das
übliche `if source.is_file()`-Muster eine fehlende Lizenz still überspringen würde — bei AGPL
eine Verletzung, sobald eine Instanz öffentlich landet.
- Ein Text-Muster-Scan für Leaks scheitert an legitimen Vorkommen des eigenen Hostnamens; ein
struktureller Scan (welche Pfade/Dateien dürfen nie im Plan stehen) umgeht das.
## Aufgaben
- [x] Korpus bereinigt, History gesquasht, Lizenzen gesetzt, Repo veröffentlicht (in dieser
Sitzung erledigt)
- [ ] Siehe Issue #27 (Decay-/Lint-Ausschluss für mitgelieferte Seiten) und #28 (Demo-Korpus als
eigene Fixture) für Folgearbeit aus dieser Sitzung
## Nicht übernommen
- Die konkreten Namen und Details der gelöschten privaten Infrastruktur (Hostnamen, IP-Bereiche,
persönliche Angaben) sind bewusst nicht in diese Source-Seite übernommen — sie zu wiederholen
widerspräche dem Zweck der Sitzung. Wo sie als Beispiel dienen mussten, steht hier nur die Art
der Information (z. B. "eine Homelab-Cluster-Dokumentation"), nie der Wortlaut.
- Der volle Wortlaut der drei Debattenpositionen ist nicht übernommen - nur ihre tragenden
Argumente und was aus ihnen in die Synthese einging. Der vollständige Text steht im Transkript.
## Verwandte Entities
- [[Chemenu]]
- [[wikitool]]
## Verwandte Concepts
- [[Mass-Update Gate]]
@@ -0,0 +1,128 @@
# Conversation Transcript - Private-Instance Merge Correction and Issue 30 Session
> Source: Claude Code session (`claude-opus-5`), chemenu workspace
> Collected: 2026-09-01
> Participant: Torben
> Fidelity: **faithful summary transcript, not a verbatim log.** Torben's questions and
> instructions are quoted verbatim; the assistant's reasoning is condensed. All shell output
> shown was produced by real, disposable test repositories built in a scratch directory during
> this session (not the chemenu repository itself) and is reproduced as run.
> No credentials appeared in the session.
> Third of three transcripts cut from this session; the first two cover the corpus/history work
> and the Publish-Remote Gate this one corrects a claim about.
Covers Torben asking what actually happens to the demo corpus in a private instance when the
upstream changes it - which exposed an unverified, incorrect claim the assistant had just
written into `instructions/private-instance.md` the same day. The claim was tested empirically,
found wrong, corrected in a released patch (2.2.1), and turned into a properly scoped, tested
merge procedure plus a new issue (#30) proposing the fix belongs in the tool itself, or that the
upstream should stop shipping content on the branch private instances pull machinery from.
---
## Turn 1 - "was passiert in der privaten instanz nach diesen schema wenn sich upstream der demo-korpus ändert?"
The assistant treated this as a request to verify, not answer from the existing text - the
previous transcript's `private-instance.md` had said a `git merge upstream/main` would see
*deleted-in-ours, unmodified-in-theirs* and resolve silently, which was written as an assumption
and never tested.
Built a throwaway upstream/private pair of git repos in the scratch directory to test it: private
instance deletes the demo corpus once, upstream then modifies one demo page, adds a new one, and
deletes another. Ran a plain `git merge upstream/main`. Result, measured rather than assumed:
- The upstream's **modified** page produced `CONFLICT (modify/delete)` and left the upstream's
version sitting in the working tree - resolving it the obvious way (`git add -A`) would commit
that version, bringing the deleted demo page back.
- The upstream's **new** page was staged silently. No conflict, no message.
- The upstream's **deleted** page (matching a page already deleted on the private side) produced
nothing - the one case that actually worked as claimed.
The middle case was the one the original claim missed entirely, and it is the dangerous one
because nothing announces it - a demo page the upstream adds simply arrives and starts showing
up in the private instance's own `lint`, `index`, `search` and `confidence decay`.
A second candidate fix was tested and also failed: a `.gitattributes` `merge=ours` driver for
`kb/**`/`raw/**`. Same three-scenario test showed the modify/delete conflict still occurred and
the new page still landed - the driver only resolves content conflicts on files both sides
touch, not modify/delete pairs or additions.
## Turn 2 - Fixing the instruction, in a released patch
`instructions/private-instance.md` was rewritten: the "Why a clone rather than a tarball"
section now states the measured three-case table instead of the wrong assumption. The update
procedure was rewritten to hold the merge open (`git merge --no-commit --no-ff`), force the
content stages (`kb/`, `raw/`) back to the pre-merge state while `HEAD` still points at the
commit before the merge, commit, and then run an explicit check
(`git diff --name-only $BEFORE HEAD -- kb raw` must be empty) - a check the reader cannot silently
skip past, unlike a claim they might trust. The bad advice in "Decision points" ("resolve a
conflict under kb/ as keep-deleted") was replaced, since that advice is exactly what leads
someone to `git add -A` the leaked content.
The corrected procedure was itself run against the same three-scenario test plus a fourth
(`raw/` alongside `kb/`), and against error paths (dirty working tree rejected, a second run
with nothing new to pull is a no-op) - all passing before publishing.
Version bumped `2.2.0 -> 2.2.1`. The changelog entry states plainly that the earlier text was
"nicht gemessen, sondern angenommen" (not measured, assumed) rather than framing it as a minor
wording fix. Published; tests green (752, unchanged in count - this was a documentation fix).
## Turn 3 - "stelle mal ein sauberes skripting hier exemplarisch dar. gibt es alternative setups? könnten wir die demo/test-seiten aus dem repo main irgendwie heraushalten? erstelle aus dem ganzen thema ein issue... aktualisiere/prüfe, ob #3 im gitea sauber ist. prüfe, ob wir sonst alle offenen enden verdrahtet haben."
Four asks in one message. Handled in order:
**A standalone script**, written and tested (not just described) against the same scenario:
rejects a dirty working tree, rejects a concurrent merge/rebase, holds the merge open the same
way the instruction's procedure now does, is a no-op on a second run with nothing new, and exits
non-zero with a rollback command if the post-merge diff check ever finds leaked content - the
check the manual procedure relies on a human to run, made unskippable.
**Alternative setups**, and the negative result from Turn 1 (`merge=ours` does not work) was kept
rather than omitted, since a rejected alternative is exactly the kind of finding this capture
procedure is meant to preserve.
**Whether the demo corpus can be kept out of `main` entirely** - assessed as the better fix in
principle: the private-instance script (and the instruction's manual procedure) treats a symptom
on every downstream instance, repeatedly; keeping content off the branch machinery is pulled from
would remove the need for either, by construction, for any new instance. Named as two variants
(a separate `demo` branch, or a separate demo repository) with the real cost stated rather than
glossed over - `main` becomes a content-free shell, which was the reason the corpus was kept in
the first place (as a walkable example), and `nightly.yml`'s corpus lint would need to move.
**Issue #30 opened**, carrying the measured table, the working script, both alternatives with
their tradeoffs, and the explicit note that it is not a duplicate of #28 but depends on it - #28
is why the corpus moves at all (demo and testbed sharing one `kb/`), #30 is what that movement
does to a downstream clone.
**Issue #3 checked against its own acceptance criteria** (all five, from the closed issue's own
text) rather than assumed closed-and-fine: a grep for the pre-rename name outside history/
changelog/transcripts, presence of a project entity page, the "Thoth" persona note in both
`SOUL.md` and its template, and no active technical identifier still using the old name. Found
clean - the handful of remaining mentions (`INSTALL.md`, two `kb/` pages) were all phrased as
history ("bis 2026-09-01", "damals"), which the criteria explicitly exempt.
**The wiring audit** turned up the two gaps described in the second transcript's closing turn
(`tools/CONTRACT.md` missing the new gate, `gates.md` not linking to `private-instance.md`) and
the stale project-page description - all three fixed in the same pass and published as 2.2.2,
verified with `docs verify`, `instructions verify`, `doctor` (16 checks OK), `lint` (clean but for
one pre-existing orphan page unrelated to this work), and the full test suite.
## Turn 4 - This capture
Torben asked for this session to be captured via `instructions/capture-session.md`, with an
explicit instruction to keep private and confidential material out - consistent with, not
separate from, everything the day's work had been about. Handled by generalizing every
infrastructure and personal-data reference that appeared during the day's audits rather than
reproducing the original identifiers, cutting the session into three topic transcripts (this
being the third), and filing this transcript's own existence as evidence rather than as new
open work - nothing in this turn required a new issue.
## Outcome
- **Version:** 2.2.0 -> 2.2.1 -> 2.2.2
- **Commits:** `private-instance.md` correction (2.2.1), documentation wiring + project-page
rewrite (2.2.2, shared with the second transcript's closing turn)
- **Tests:** 752, green throughout
- **Issues:** #30 opened; #3 verified against its own acceptance criteria and confirmed clean,
no action needed
- **CI:** green after each publish in this transcript's scope
@@ -0,0 +1,208 @@
# Conversation Transcript - Public Release, Corpus Purge and History Squash Session
> Source: Claude Code session (`claude-opus-5`), chemenu workspace
> Collected: 2026-09-01
> Participant: Torben
> Fidelity: **faithful summary transcript, not a verbatim log.** Torben's instructions and
> decisions are quoted verbatim; the assistant's reasoning and the exploration agents' findings
> are condensed. Command outputs shown are real, but every private hostname, IP address and
> personal detail that appeared during the audit has been **generalized rather than repeated** -
> reproducing them here would undo the point of the session. No secret values (tokens, keys)
> ever appeared.
> **Several passages are second-hand.** Three `Explore` subagents (private-data inventory,
> distribution mechanism, git-history audit) and three forked debate agents (hard-separation,
> shared-upstream, devil's-advocate positions) ran in the background; their findings are
> summarized here, not reproduced verbatim, and are named as such at each point they inform a
> decision.
> One of three transcripts cut from the same session; the other two cover building the
> Publish-Remote Gate and the private-instance procedure, and correcting a bug found in that
> procedure afterward (issue #30).
Covers turning the chemenu wiki stack from a private testbed into a publishable repository:
deciding what to delete versus anonymize, squashing the git history, choosing a license, and
verifying the result anonymously end to end. Resulted in the corpus purge (108 pages, ~90 raw
files removed), a single-commit public history, `LICENSE`/`LICENSE-CONTENT`/`NOTICE`, the
`dist export` leak canary (2.1.0), a CI fixture fix (2.1.1), and the repository going public on
Gitea.
---
## Turn 1 - "ich möchte die kb hier bereinigen, es soll nur noch test content sein, ich möchte das repo veröffentlichen..."
Torben's instruction, in substance: clean the KB down to test content, publish the repository,
falsify or remove IP addresses, keep the repo usable as a demo and a testbed going forward; he
would rebuild his real private instance separately. He asked for tips on three specific
questions - how a private fork could pull upstream fixes back, how to set up that private copy
and where to develop the stack, and whether a `kb/manual/` should ship with the distribution so
it documents itself - explicitly requested "mindestens ... teufels anwalt modus" and a small
multi-agent debate, and flagged himself as new to packaging/distributing an LLM application.
The session started in plan mode. Three `Explore` subagents ran in parallel:
- **Private-data inventory** - catalogued what in `raw/` and `kb/` was hard-private (a real
home-lab cluster's bootstrap manual, several personal notes, a 2.46 MB conversation transcript
full of infrastructure references), what was anonymizable (internal hostnames, private IP
ranges), and what was legitimately generic (the stack's own concepts, technologies, tools).
- **Distribution mechanism** - read `dist_cmd.py`, `INSTALL.md` and the version-check machinery;
confirmed `dist export` already ships no `kb/`/`raw/` content and that the update feed's
default URL pointed at the (then-private) origin repo.
- **Git-history audit** - measured `.git` size, largest blobs, deleted-file history, and
concluded the tree was "safe to publish" - a conclusion the session later disproved, see Turn 4.
## Turn 2 - The debate
Three forked debaters argued from the same context:
- **A (hard separation):** delete and rebuild the corpus rather than anonymize, because a page
title is the wiki's only identifier and lives in wikilinks/citations/frontmatter across the
corpus - renaming is the full page-lifecycle procedure, deleting is a supported command.
Squash history rather than selective `filter-repo`, because the history audit itself had just
been shown to under-report risk. No shared git ancestry between the public repo and the
private instance, ever.
- **B (shared upstream):** clone-with-`upstream`-remote instead, because the tarball update path
in `INSTALL.md` is `cp -r` with no three-way merge; argued the leak risk from shared history is
a mechanism problem (a remote allowlist), not a discipline problem, and that most of the
corpus (the ~190 generic pages) is worth keeping as real test data rather than deleting it all.
- **C (devil's advocate):** attacked both positions' shared premises - "just a testbed" was
false (`USER.md` is tracked and carries real personal data), "publish the repo" was
underspecified (which host, and what breaks), there was no `LICENSE` at all, a shipped manual
would decay under `confidence_decay.py` and mislead a new instance, and demo/testbed are
conflicting goals for one `kb/`.
The assistant's synthesis kept A's "delete, don't anonymize" and "squash the history" (C's
finding that the audit under-reported risk made this decisive), adopted B's clone-with-`upstream`
model but **conditioned it on a remote-allowlist gate existing first** (addressing C's leak
concern with code, not discipline), rejected the shipped manual per C's decay argument, and
decided the surviving corpus should lean toward the stack's own self-documentation rather than
Torben's real infrastructure - which the actual corpus math later validated (Turn 5).
## Turn 3 - Clarifying questions and plan approval
The assistant asked Torben to choose among concrete options (`AskUserQuestion`) rather than
picking on his behalf:
- **Publish target:** "Gitea öffentlich schalten" (chosen) over mirroring to GitHub or keeping
Gitea private with a GitHub mirror - smallest change, CI/release feed stay correct as-is.
- **Corpus:** "Chirurgisch löschen (Empfehlung)" (chosen) over full synthetic rebuild or
anonymization.
- **Private instance:** "Clone mit upstream, Gate zuerst (Empfehlung)" (chosen) over hard
separation or a later migration.
- **License:** first pass "Was wäre CC-BY-4 für content und eine GPL oder LGPL fürs Tooling?
Berate mich hier noch mal" - the assistant advised against LGPL (no library-linking use case
here to justify the fetch-only variant), and named the real choice as GPL vs. **AGPL**, because
issue #19 (an MCP frontend for `wikitool`) points toward running the stack as a network
service, which is exactly the gap GPL leaves and AGPL closes. Torben chose **AGPL-3.0 +
CC-BY-4.0**.
The written plan covered: publish blockers (license, `dist export` allowlist, `INSTALL.md`
token wording), the corpus purge, the history squash, the private-instance model with the gate
as a precondition, why the manual idea was declined, and a leak-canary for `dist export`. Torben
approved it via `ExitPlanMode` without further changes.
## Turn 4 - Executing the license and leak-canary work (2.1.0)
Before touching content: a full repo bundle backup outside the tree, verified by `git bundle
verify` and a commit-count comparison (150 commits, all 15 tags present).
- Fetched the AGPL-3.0 text from `gnu.org` (not reconstructed from memory - a license must be
the authoritative text) and copied the CC-BY-4.0 text from the vendored `commonplace`
submodule, per the license each already carries.
- Added `LICENSE` (AGPL - deliberately the AGPL rather than a separate `LICENSE-CODE`, because
that is the file a forge reports for the repository, and under-noticing a copyleft obligation
harms a reader in a way over-noticing does not), `LICENSE-CONTENT` (CC-BY), `NOTICE` (the
license boundary and the `commonplace` attribution CC-BY requires).
- `dist_cmd.py`: added the three license files to `ROOT_FILES`, and a separate
`REQUIRED_ROOT_FILES` check that **fails the export** if they are missing - every other
`ROOT_FILES` entry is copied `if source.is_file()` and silently skipped otherwise, which is
wrong for a license (a distribution shipping AGPL code with no license text is a violation the
moment it is published).
- Added `find_leaks()`: a structural (not text-pattern) check of the finished export plan against
personalization files, `instructions/dev/`, `kb/` pages and `raw/` sources - rejected a
hostname/IP text-scan approach, because the project's own host legitimately appears in
`INSTALL.md` and `version.py`, so such a scan would either whitelist the string it's looking
for or false-positive on every export.
- Six new tests in `test_dist_cmd.py`; full suite green; version bumped `2.0.0 -> 2.1.0`.
## Turn 5 - The corpus purge
A workshop (`work/publish-cleanup`) was opened per `work/CONTRACT.md`, because ~103 planned
`wikitool rm` calls exceed a single iteration-budget unit.
Analysis found the plan's estimate wrong in a way worth recording: not ~35 pages would become
sourceless after deleting the obviously-private ones, but **75**. Splitting them: 28 were the
user's own infrastructure (unambiguous), and **40 carried generic technology titles but were
written entirely around the user's own cluster** (a storage page explained itself via one
specific storage class name, a Kubernetes page via the user's own network ranges) - not
reusable pages with a private example, but private documentation with a generic heading. The
remaining 7 were genuinely clean in body text but sourced from the user's personal
document-processing pipeline.
Presented to Torben as a three-way choice; he chose **"Alle 75 löschen"** over keeping the
clean 7 (via provenance reclassification) or rewriting the 40 as vendor-neutral pages. The
result: 152 pages plus 25 sources remained by design - the stack's own self-documentation
(gates, lint, versioning, search, the wiki pattern itself), which the earlier debate had argued
for without knowing this would be the actual outcome.
Execution: `wikitool rm --page <title> --yes` per page across three units (27 sources, 28
infra, 48 entangled), 90 raw files removed including the full cluster bootstrap tree and the
2.46 MB transcript. `wikitool rm` was found to de-link only mechanically (frontmatter refs and
whole-line link bullets) and to deliberately leave inline prose wikilinks and plain-text
mentions standing - roughly 20 pages needed manual follow-up to actually remove the remaining
references, which `lint` and a targeted `rg` scan surfaced.
Also reset: `kb/log.md` (116 private references, no regenerator - reset to the
`dist_templates/log.md` starting state, a deliberate one-time stack-dev operation, not a
hand-edit of a generated file), `USER.md`/`SOUL.md` rewritten as an explicit demo-operator
persona rather than Torben's real profile.
## Turn 6 - Squashing the history
Backup re-verified before the destructive step. An orphan root commit was built from the purged
working tree, `main` reset onto it, all 15 tags deleted (locally, then individually on the
remote - a batch refspec push failed silently), `git reflog expire --expire=now --all` and
`git gc --prune=now --aggressive`, then a `--force` push.
**Verified rather than trusted:** a fresh clone attempted `git fetch --depth=1 origin
<old-head-sha>` immediately afterward and succeeded - the objects were still reachable through
Gitea's own reflog on the bare repository, contradicting the earlier belief that force-pushing
was sufficient. The rejected shortcut here was accepting Gitea's own scheduled cleanup jobs as
proof; Torben ran them once, and the same fetch test still succeeded afterward. Only a direct
`reflog expire` + `gc --prune=now` run on the bare repository itself (which Torben ran, having
shell access the assistant did not) closed it - reverified by the same fetch test returning
`not our ref`.
A second leak was found by scanning **hidden directories** (`.gitea/`, `.github/`, `.vibe/`),
which the earlier `rg` sweeps had silently skipped without `--hidden` - two references to an
internal CI branch name in `.gitea/workflows/ci.yml`, fixed and amended into the squashed
commit before the first push.
## Turn 7 - Public switch, CI fixture bug, and verification
Torben switched the Gitea repository to public. Verified anonymously (no token, no SSH key):
repository API reports `private: false`, the release feed serves the latest tag, and a clean
`git clone` over HTTPS from an empty directory succeeds. A further leak scan of that anonymous
clone found one remaining hit: the 2.1.1 changelog entry (see below) had *listed* the private
fixture names it replaced, which put them back into the public history it was announcing the
removal from. Corrected in the same commit that introduced it.
Separately, the first CI run on the squashed history failed on a test unrelated to the corpus
purge in content but caused by it: `test_legacy_source_pages_flags_url_and_directory` checks
`(config.ROOT / legacy).is_dir()` against the **real** repository root rather than the test
fixture's own tree, and had only ever passed because this checkout happened to have a
`raw/documents/` directory - which the corpus purge had just emptied. Git does not track empty
directories, so the directory vanished from CI's checkout and stayed in the local one: green
here, red there. Reproduced locally by removing the directory and rerunning; fixed in the
`raw_dir` fixture (`conftest.py`) rather than the one test, matching the reasoning already
recorded for a prior, similar case (Gitea #8). Several other test fixtures still used the
user's real system names and were renamed to generic, unrelated placeholders
alongside. Published as 2.1.1 after Mass-Update Gate clearance from Torben.
## Outcome
- **Version:** 2.0.0 -> 2.1.1
- **Commits:** license/leak-canary work, corpus purge (multiple), history squashed to one root
commit, CI fixture fix
- **Tests:** 630 -> 752, all green
- **Issues:** none opened in this transcript's scope (see the other two transcripts for #27-#30)
- **CI:** green on the squashed history after the fixture fix; release `v2.1.1` built and
anonymously downloadable
@@ -0,0 +1,154 @@
# Conversation Transcript - Publish-Remote Gate and Issue Triage Session
> Source: Claude Code session (`claude-opus-5`), chemenu workspace
> Collected: 2026-09-01
> Participant: Torben
> Fidelity: **faithful summary transcript, not a verbatim log.** Torben's instructions are
> quoted verbatim; the assistant's design reasoning is condensed. Command outputs and test
> results shown are real. No credentials appeared in the session; where a private hostname
> could have been used as a code example, a generic placeholder is used instead, matching what
> was actually committed.
> Continues directly from "Public Release, Corpus Purge and History Squash Session" (same day).
> Two of three transcripts cut from this session; the third covers a bug found afterward in the
> procedure this one builds (issue #30).
Covers building the Publish-Remote Gate (a third code-enforced gate, alongside the Mass-Update
and rebase-review gates), writing `instructions/private-instance.md`, updating six open Gitea
issues for the rename and the new architecture, opening three new issues (#27, #28, #29), and
deleting the Gitea Actions run history at Torben's request. Resulted in version 2.2.0, then a
documentation-only 2.2.2.
---
## Turn 1 - "1. remote allowlist. 2. unterbreche und warte auf mich, wenn ich gitea scharf schalten soll... 3. setup a) meiner lokalen dev-umgebung"
Torben asked for three things in one message, plus: "parallel issuen anlgen und aktualisieren
nach eigenem ermessen, prüfe auch vorhandene, evtl. müssen wir hier auch noch tätig werden?"
**The gate.** Designed to pin the **resolved push URL**, not the remote name - a name-based
allowlist would pass a `publish` whose `origin` had been repointed, which is the exact failure
it exists to catch. `git remote get-url --push <remote>` is read at check time so a `pushurl`
override is respected. The file (`.wikitool-remotes.json`) is gitignored and per-checkout, for
the same reason `ENVIRONMENT.md` is: two clones push to two different places, and a committed
copy would tell a private clone the public upstream is a legitimate target for its own content.
Absence means unrestricted, matching the pattern of the other optional per-checkout files;
`doctor` reports the state and WARNs only when a checkout has more than one remote and no
allowlist.
**Deliberately no `--confirm` token**, unlike the other two gates. Their question ("is this
change right?") is answerable per changeset; this gate's question ("does this content belong in
that repository?") is a standing property of the checkout, so the only way past it is the user
editing the file themselves - an agent editing it to clear a refusal would be opening a gate on
its own initiative, which the repository's own rules forbid.
Implementation: `config.PUBLISH_REMOTES_FILENAME`, `read_allowed_push_urls()` /
`push_url_for()` / `publish_remote_refusal()` in `git_publish.py`, checked before the reconcile
step in `publish_command` (before any network contact, so a refused publish never even fetches
from the wrong place), `doctor.check_publish_remotes()`, twelve new tests covering the URL-vs-name
distinction, `pushurl` precedence, a broken/missing/empty allowlist, and that no flag exists to
bypass it. `instructions/gates.md` and `AGENTS.md` updated to describe a third gate. Version
bumped `2.1.1 -> 2.2.0`; the Mass-Update Gate itself fired at 10 files and Torben cleared it with
the printed token.
**`instructions/private-instance.md`** (new): the procedure for cloning with the public repo as
`upstream`, arming the gate *before* the first `publish` (not after - the assistant stressed this
ordering explicitly, since a gate added later leaves the earlier window open), taking the write
credential away from the private clone as a second, independent control, and where stack
development happens ("in the public repo, not here" - not a preference but a structural fact,
since `instructions/dev/` does not survive `dist export`). **This file's description of what a
`git merge upstream/main` actually does to the content stages was wrong as first written** - see
the third transcript for the correction.
**The Gitea admin cheat-sheet** (delivered as a reply, not committed): what to check before
flipping the repo public (`DISABLE_REGISTRATION`, `REQUIRE_SIGNIN_VIEW`, rate limits, the
Actions runner's network exposure), and the follow-up steps (`INSTALL.md`, anonymous release
check, a clone test). Also flagged that the open issues would go public with the repo, which is
what motivated the issue-triage pass below.
## Turn 2 - Issue triage
Read the labels (`prio/1..3`, `size/XS..L`) and the open issues. Several pre-dated the
`llm-wiki-test1` -> `chemenu` rename (issue #3) and still named the old package path
(`tools/wiki_tools/...`) or the old repository name in code examples:
- **#6** title corrected in place (`wiki_tools` -> `chemenu` path).
- **#7** (`dist upgrade`) commented: the "origin repo is private" fallback it describes no
longer applies once the repo is public, and its urgency for *this* instance specifically
dropped, because the private instance now takes updates via `git merge upstream/main` (real
three-way merge) rather than the tarball-copy path the issue was written against - it remains
the right design for any instance without shared git history.
- **#10** (coverage reporting) commented: step 1 is done (1.8.1 shipped `pytest-cov` without a
failure threshold), the test count referenced is stale (630 -> 752, and the gap is itself
evidence for the issue's own argument - the raw_dir fixture bug from the first transcript), and
one code example named a private CI branch and needs neutralizing before being read publicly.
- **#4, #5** flagged as needing the same path correction but not rewritten in this pass.
**Three new issues opened**, each traced to a decision made and then set aside earlier in the
day rather than invented fresh:
- **#27** - the shipped-manual idea the debate rejected (first transcript, Turn 2) needs a
decay/lint exemption for distributed pages before it becomes buildable at all; names the exact
blocker (`confidence_decay.py` has no exemption path) and the two things still undecided (how
a shipped page is recognized, what exactly is exempted).
- **#28** - the demo-vs-testbed tension the debate argued through (assistant recommended
testbed, C objected) is not resolved, only decided for now; proposes a curated fixture corpus
as the eventual answer and names why (`kb_dir`/`raw_dir` fixtures already cover the small case,
this is about the dense, interconnected one).
- **#29** - catalogs which open issues still carry pre-rename paths and a private hostname
(#10's CI example), separating "pointer, fix it" references from "citation of what was true
then, date it" references rather than blanket-editing everything.
## Turn 3 - Public verification and the actions-history request
After Torben confirmed the repository was public, verification ran anonymously: repo API
(`private: false`), release feed (latest tag served without auth), a clean HTTPS clone from an
empty directory (three commits, two tags, all three license files present, 170 pages, no leak
hits including in hidden files), and the full `INSTALL.md` release-tarball path end to end -
checksum verified, license files present in the unpacked tree, `kb/`/`raw/` empty as designed,
`instructions/dev/` absent.
Torben: "an der Stelle: wenn du per mcp die action runner historie löschen kannst, leere sie
bitte komplett, da finde ich keinen knopf für und dort dürften noch alte tarballs herumgeistern."
The assistant checked: the Gitea MCP server exposes `dispatch`/`cancel`/`rerun` for Actions runs
but no delete, and the delete route Gitea's own API defines (`DELETE
/api/v1/repos/{owner}/{repo}/actions/runs/{run}`) requires a token the assistant did not hold.
Findings reported instead of silently working around the missing capability: **zero artifacts**
existed already (confirmed via the anonymous artifacts API), but an anonymous SPA data endpoint
the run pages call was readable and returned old commit titles from the squashed-away history -
no hostnames or personal data among the six reachable runs, but development history the squash
was meant to remove. A `curl` loop using a write-scoped token was handed to Torben to run
himself, rather than asking for a token in the session.
Torben ran it and reported back ("die action-historie habe ich jetzt per api gelöscht") in the
same message as "korrigiere die install.md wie vorgeschlagen." Both handled: the anonymous SPA
endpoint was re-tested across all previously-reachable run numbers and returned nothing for any
of them, closing the loop; `INSTALL.md`'s "repo is currently private, you need a token" language
was removed from three places (the download command, the configuration table, a dedicated
paragraph - the paragraph rewritten to explain the token is still needed **for a private fork**,
not for this repository), "Weg C" was reworded from "Torben's personal wiki" to a description of
the testbed/demo nature of the corpus, and a new "Weg D" documented the private-instance path
with a pointer to `private-instance.md`. No version bump (prose only).
## Turn 4 - Wiring audit (from the third transcript's closing turn, included here for the gate/issue thread)
A later pass (opened by a different question, documented fully in the third transcript) checked
whether the gate work here was actually cross-referenced: `tools/CONTRACT.md` did not mention
the Publish-Remote Gate at all despite it being `publish`'s third exit-42 path - fixed in both
the command-table entry and the error-contract entry, since a tool's error contract is exactly
where a caller learns what a given exit code means and whether retrying is safe. `gates.md` did
not link to `private-instance.md`, the procedure it exists for - fixed. The project's own KB
page (`kb/entities/projects/Chemenu.md`) still described the instance as a personal wiki with no
mention of the license or its public, testbed-and-demo status - rewritten, keeping the
historical note about the pre-restructuring `AGENTS.md` but dating it explicitly rather than
stating it as a current fact. Published as 2.2.2.
## Outcome
- **Version:** 2.1.1 -> 2.2.0 -> 2.2.2
- **Commits:** Publish-Remote Gate + `private-instance.md` (2.2.0, Mass-Update Gate cleared),
`INSTALL.md` correction (unversioned prose), documentation wiring + project-page rewrite
(2.2.2)
- **Tests:** 752, all green throughout (12 new for the gate)
- **Issues:** #6 title fixed; #7, #10 commented; #27, #28, #29 opened
- **CI:** green on every push in this transcript's scope; Gitea Actions run history removed by
Torben via the API, verified anonymously empty afterward