move: source_type: Default streichen, unclassified als sichtbares Fach, layout: fuer source (schliesst #66)
CI / verify (push) Successful in 53s
Release / release (push) Successful in 35s

Files changed:
- CHANGES.md
- VERSION
- instructions/dev/corpus-policy.md
- instructions/wiki-ingest/SKILL.md
- kb/index.md
- kb/log.md
- kb/sources/COLLECTION.md
- kb/sources/INDEX.md
- kb/sources/Source - AMD Powermanagement CPU.md
- kb/sources/Source - Arch Linux Cheat Sheet.md
- kb/sources/Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04.md
- kb/sources/Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31.md
- kb/sources/Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31.md
- kb/sources/Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31.md
- kb/sources/Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31.md
- kb/sources/Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31.md
- kb/sources/Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31.md
- kb/sources/Source - Conversation - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31.md
- kb/sources/Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md
- kb/sources/Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30.md
- kb/sources/Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md
- kb/sources/Source - Copilot Skill Restructure Instructions.md
- kb/sources/Source - Docker Cheatsheet.md
- kb/sources/Source - Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02.md
- kb/sources/Source - Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04.md
- kb/sources/Source - LLM Improvements Codex Analysis.md
- kb/sources/Source - LLM Improvements Production Agent Gaps 2026.md
- kb/sources/Source - LLM Improvements Sonnet Analysis.md
- kb/sources/Source - LLM Wiki Pattern.md
- kb/sources/Source - LLM Wiki v2.md
- kb/sources/Source - MCP Read Server Implementation Session 2026-09-02.md
- kb/sources/Source - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md
- kb/sources/Source - Public Release, Corpus Purge and History Squash Session 2026-09-01.md
- kb/sources/Source - Publish-Remote Gate and Issue Triage Session 2026-09-01.md
- kb/sources/Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02.md
- kb/sources/Source - Wine.md
- kb/sources/Source - qmd - GitHub Repository.md
- kb/sources/analyses/Source - Copilot Skill Restructure Instructions.md
- kb/sources/analyses/Source - LLM Improvements Codex Analysis.md
- kb/sources/analyses/Source - LLM Improvements Production Agent Gaps 2026.md
- kb/sources/analyses/Source - LLM Improvements Sonnet Analysis.md
- kb/sources/articles/Source - AMD Powermanagement CPU.md
- kb/sources/articles/Source - LLM Wiki Pattern.md
- kb/sources/articles/Source - LLM Wiki v2.md
- kb/sources/documents/Source - qmd - GitHub Repository.md
- kb/sources/notes/Source - Arch Linux Cheat Sheet.md
- kb/sources/notes/Source - Docker Cheatsheet.md
- kb/sources/notes/Source - Wine.md
- kb/sources/trackers/Source - Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02.md
- kb/sources/trackers/Source - Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04.md
- kb/sources/transcripts/Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04.md
- kb/sources/transcripts/Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30.md
- kb/sources/transcripts/Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md
- kb/sources/transcripts/Source - MCP Read Server Implementation Session 2026-09-02.md
- kb/sources/transcripts/Source - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md
- kb/sources/transcripts/Source - Public Release, Corpus Purge and History Squash Session 2026-09-01.md
- kb/sources/transcripts/Source - Publish-Remote Gate and Issue Triage Session 2026-09-01.md
- kb/sources/transcripts/Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02.md
- tools/CONTRACT.md
- tools/chemenu/lint_core.py
- tools/chemenu/tests/conftest.py
- tools/chemenu/tests/test_lint.py
- tools/chemenu/tests/test_new_page.py
- tools/chemenu/tests/test_provenance.py
- tools/chemenu/tests/test_touch.py
- tools/chemenu/tests/test_type_resolver.py
- tools/chemenu/tests/test_xref.py
- types/source.md
- types/source.schema.yaml
- types/type-spec.md
- work/reclassify-source-types/README.md
- work/reclassify-source-types/plan.md
This commit is contained in:
2026-09-08 20:38:15 +02:00
parent 7f74303a00
commit b138fd8e64
51 changed files with 467 additions and 96 deletions
@@ -0,0 +1,62 @@
---
type: types/source.md
source_type: transcript
author: GitHub Copilot (Claude Sonnet 5)
raw_files: [raw/notes/Conversation Transcript - AGENTS.md Skill Restructuring Session 2026-08-04.md]
source_language: en
date: 2026-08-04
tags: [skills, agents-md, wikitool, fact-check, restructuring]
entities: [AGENTS.md, wikitool, Chemenu, GitHub Copilot, Claude Code, Codex CLI, Mistral Vibe]
concepts: [Cross-platform Agent Skills, Token Economics, Context Isolation]
summary: Geprüfte und umgesetzte Aufteilung der 5 Workflows aus AGENTS.md in 5 einzelne Skills unter .agents/skills/; korrigiert falsche und unbelegte Aussagen aus einem früheren, ungeprüften Ingest derselben Anweisungen
---
# Source: Conversation - AGENTS.md Skill Restructuring Session 2026-08-04
**Autor:** Torben
**Datum:** 2026-08-04
**Quelle:** raw/notes/Conversation Transcript - AGENTS.md Skill Restructuring Session 2026-08-04.md
**Typ:** notes
## Zusammenfassung
Diese Sitzung analysierte, ob die fünf Workflows von `AGENTS.md` in diskrete, unabhängig entdeckbare Agent-Skills umstrukturiert werden sollten, dann wurden Faktenprüfung und Implementierung dieser Umstrukturierung durchgeführt. Die Forschung stellte fest, dass VS Code Copilot's nativer Skill-Mechanismus (`.github/skills/`, `.agents/skills/`, `.claude/skills/` mit 3-stufiger progressiver Offenlegung) der eigentliche Enabler der Idee ist, die der Benutzer beschrieb - nicht Farzas Gist, das eine einzelne Skill-Datei mit Befehlsargument-Hinweis ist, nicht mehrere unabhängig entdeckbare Skills.
Der Benutzer fügte dann einen "Web-Suchergebnis, synthetisiert" Anweisungssatz ein, der eine konkrete plattformübergreifende Umstrukturierung über GitHub Copilot, Claude Code, Codex CLI und Mistral Vibe vorschlug. Jede konkrete technische Aussage in diesem Dokument wurde unabhängig gegen primäre Quellen überprüft (offizielle Claude Code/Codex/Mistral Vibe Dokumentation, `agentskills.io` und die zitierten GitHub Repositories), bevor sie für die Planung verwendet wurde, gemäß dieser Wiki's eigener "keine sichere Antwort ohne Quelle" Regel. Zwei Aussagen wurden als falsch oder nicht überprüfbar befunden und korrigiert: Codex CLI's echter Skill-Standort ist `.agents/skills/` (nativ, kein Symlink), nicht `~/.codex/skills/`; und die "5-8x"/"61% Reduktion, 100% Lösungsquote auf 8.260-Datei-Corpus" Token-Ökonomie-Statistiken haben keine auffindbare Quelle und wurden explizit aus dem Plan ausgeschlossen.
Die Umstrukturierung wurde dann implementiert: 5 Skills (`wiki-ingest`, `wiki-query`, `wiki-lint`, `wiki-manage`, `wiki-status`) unter `.agents/skills/`, gespiegelt zu `.claude/skills/` über neue `tools/wikitool skills sync`/`verify` Befehle, und root `AGENTS.md` von 745 auf ~573 Zeilen reduziert. Diese Quelle wird auch eingereicht, um spezifische falsche/nicht überprüfbare Aussagen zu ersetzen, die bereits aus einer früheren, nicht überprüfbaren Aufnahme desselben eingefügten Anweisungssatzes in der Wiki eingereicht wurden.
## Kernaussagen
- VS Code's nativer `SKILL.md` Progressive-Disclosure-Mechanismus (nicht Farzas Single-Skill-Design) ist das, was eine echte Multi-Skill-Aufteilung lohnenswert macht - nur der Körper des relevanten Skill wird geladen.
- Codex CLI liest nativ `.agents/skills/` (gescannt von CWD bis zum Repo-Root, plus `$HOME/.agents/skills/`) - kein Symlink erforderlich, was die frühere Ingest-Aussage korrigiert.
- Mistral Vibe liest nativ `.vibe/skills/` und `.agents/skills/` (Projekt, trusted-folder-gated) sowie die `~/.vibe/skills/`/`~/.agents/skills/` Benutzerbereich-Äquivalente - direkt bestätigt aus `mistralai/mistral-vibe`'s Quellcode und Changelog.
- Claude Code liest nur `.claude/skills/` (Projekt) oder `~/.claude/skills/` (persönlich/Plugin) - es liest `.agents/skills/` nicht nativ, daher ist ein erzeugter Spiegel erforderlich.
- Die "5-8x Token-Kosten" und "61%/100% Lösungsquote auf 8.260 Dateien" Statistiken aus dem eingefügten Anweisungssatz haben keine auffindbare Quelle und sollten nirgends in dieser Wiki als Fakt behandelt werden.
- `kfchou/wiki-skills`, `vanillaflava/wiki-skills-vanillaflava` und `yugasun/llm-wiki-skills` sind alle echte Repositories, die dieses allgemeine Muster implementieren, bestätigt durch direkte Repository-Inspektion.
## Aufgaben
- [x] AGENTS.md in 5 Skills unter `.agents/skills/` umstrukturieren
- [x] `tools/wikitool skills sync`/`verify` hinzufügen und zu `.claude/skills/` spiegeln
- [ ] Falsche `~/.codex/skills/` Aussage in `Codex CLI.md` korrigieren
- [ ] Nicht überprüfte Token-Ökonomie-Statistiken in `Token Economics.md` kennzeichnen
- [ ] Die empirische "entdeckt Copilot `.agents/skills/` mit Zero-Config" Prüfung in einer zukünftigen Sitzung erneut ausführen (in dieser Sitzung unklar)
## Verwandte Entities
- [[AGENTS.md]]
- [[wikitool]]
- [[Chemenu]]
- [[GitHub Copilot]]
- [[Claude Code]]
- [[Codex CLI]]
- [[Mistral Vibe]]
- [[wiki-skills]]
- [[wiki-skills-vanillaflava]]
- [[llm-wiki-skills]]
## Verwandte Concepts
- [[Cross-platform Agent Skills]]
- [[Token Economics]]
- [[Context Isolation]]
@@ -0,0 +1,127 @@
---
type: types/source.md
source_type: transcript
author: Claude Code (claude-opus-5)
raw_files: [raw/notes/Conversation Transcript - Auto Mode and Tool Choice Session 2026-08-31.md]
source_language: en
date: 2026-08-31
tags: [claude-code, auto-mode, permissions, tool-choice, harness]
entities: [Claude Code, wikitool]
concepts: [Claude Code Auto Mode, Diff-Reviewable Agent Edits]
summary: 'Sitzung zum auto-Berechtigungsmodus von Claude Code: die vom Modus injizierte Bash-Praeferenz, ihre Korrektur zugunsten diffbarer Edits, und was zur Dokumentationslage belegt bzw. nicht belegt ist'
---
# Source: Conversation - Auto Mode and Tool Choice Session 2026-08-31
**Autor:** Claude Code (claude-opus-5)
**Datum:** 2026-08-31
**Raw-Dateien:** raw/notes/Conversation Transcript - Auto Mode and Tool Choice Session 2026-08-31.md
**Typ:** Notes
## Zusammenfassung
Das Transkript ist eine vom Assistenten am Sitzungsende rekonstruierte Zusammenfassung, kein
wörtliches Protokoll. Es ist eines von drei Transkripten derselben Sitzung; die beiden anderen
behandeln die Werkzeugkorrekturen zu den Issues #12 und #13
([[Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31]])
und die Issue-Triage
([[Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31]]).
Gegenstand ist ausdrücklich nicht der Wiki-Stack, sondern [[Claude Code]] als Harness. Die
Sitzung erzeugte keinen Commit; ihr Ergebnis war eine dauerhaft gespeicherte Arbeitsregel und
ein lokal abgelegter Entwurf für Produkt-Feedback.
Die Quelle trägt Material aus **drei Erfassungsschichten**, und ihr Kopfblock benennt sie
selbst. Diese Unterscheidung ist der wichtigste Teil der Quelle und wird auf allen von ihr
gestützten Seiten mitgeführt:
| Schicht | Was darunter fällt | Belegwert |
|---|---|---|
| Lokal belegt | Ausgabe von `claude --help` auf Claude Code 2.1.251, Inhalt von `~/.claude/settings.json`, Existenz des `dangerouslyDisableSandbox`-Parameters am Bash-Werkzeug, Torbens wörtliche Aussagen | In der Sitzung selbst bezeugt |
| Aus zweiter Hand | Alles im Abschnitt "What the subagent found documented": ein `claude-code-guide`-Subagent hat die Claude-Code-Dokumentation durchsucht und berichtet. Niemand in der Sitzung hat diese Dokumentation selbst gelesen | Vermittler in der Kette, Treue ist Annahme |
| Ausdrücklich unbelegt | Die Vermutung, die Bash-Präferenz hänge mit der Sandbox zusammen | Zum Zeitpunkt der Äußerung als Spekulation markiert und vom Subagenten **nicht** bestätigt |
Der Anlass war eine Beschwerde über die Arbeitsweise des Assistenten. Torbens Frage wörtlich:
*"Warum verwendest du seit neuestem immer die Shell um Dateien zu editieren anstelle der file
edit Tools? Das macht die Session schwer nachvollziehbar."* Ursache war eine vom aktiven
Berechtigungsmodus in die Sitzung injizierte Anweisung, die Bash den dedizierten
Datei-Werkzeugen vorzieht:
> While auto mode is active: Do your work through the Bash tool wherever it can accomplish the
> job: read files with `cat`, `head`, or `sed -n`, search with `grep` and `find`, and make file
> changes with `sed`, heredocs, or short scripts, rather than using the dedicated Read, Edit, or
> Write tools. Fall back to a dedicated tool only when Bash genuinely cannot do the job.
Der Assistent war ihr gefolgt und hatte `lint.py`, `frontmatter_io.py` und `run_budget.py` über
heredoc'te `python3 - <<'PY'`-Blöcke mit `s.replace(old, new)` umgeschrieben. Die daraus
abgeleitete Regel steht auf [[Diff-Reviewable Agent Edits]], die Mechanik des Modus auf
[[Claude Code Auto Mode]].
## Kernaussagen
- **Der benannte Schaden ist die fehlende Diff.** Ein `python3 - <<'PY'`-Block mit
`s.replace(old, new)` zeigt dem Leser zwei String-Literale und keine Änderungsansicht. Was
vorher in der Datei stand und was jetzt darin steht, ist nicht sichtbar; das `Edit`-Werkzeug
zeigt genau das. Bei einem einzeiligen `sed` ist der Unterschied unerheblich, beim
Mehrblock-Umbau eines Compiler-Moduls nicht.
- **Die Auflösung stützt sich auf den Wortlaut der Anweisung selbst.** Deren Qualifikator
*"wherever it can accomplish the job"* trägt die Entscheidung: ein Edit, dessen Diff niemand
prüfen kann, erfüllt die Aufgabe nicht. Zusätzlich rangiert die ausdrückliche Anweisung des
Nutzers über einer Modus-Voreinstellung. Lesen mit `cat`/`sed -n` bleibt zulässig, Schreiben
nicht. Die daraus gewordene Arbeitsregel: `Edit`/`Write` für Dateiänderungen, Bash für `git`,
`pytest`, [[wikitool]], `grep` und `find`. Sie wurde in das dauerhafte Gedächtnis des
Assistenten geschrieben, damit sie die Sitzung überdauert.
- **`auto` ist ein Berechtigungsmodus, kein Performance-Modus** - lokal belegt aus
`claude --help` auf Version 2.1.251: einer von sechs Werten für `--permission-mode`, neben
`acceptEdits`, `bypassPermissions`, `manual`, `dontAsk` und `plan`.
- **Das Bash-Werkzeug dieser Sitzung führt einen `dangerouslyDisableSandbox`-Parameter**, ist
also standardmäßig sandboxed; das Scratchpad-Verzeichnis der Sitzung wird als ohne
Berechtigungsabfragen nutzbar beschrieben. Lokal belegt.
- **Aus zweiter Hand (`claude-code-guide`-Subagent):** `auto` lässt ein separates
Klassifikator-Modell Aktionen vor der Ausführung bewerten, statt nachzufragen. Details,
Schaltwege und die dokumentierte Falle mit `permissions.defaultMode` in einer
Projekt-Settings-Datei stehen auf [[Claude Code Auto Mode]].
- **Der belastbare Negativbefund:** die Bash-Präferenz selbst steht **nicht** in der
öffentlichen Dokumentation - weder ihr Text noch eine Begründung - und es wurde keine
Einstellung gefunden, die sie einzeln abschaltet, ohne `auto` ganz zu verlassen.
- **Die Sandbox-Erklärung blieb Vermutung.** Dass die Bash-Präferenz existiert, weil
sandboxed Shell-Arbeit der Pfad ist, den der Modus ohne Rückfrage genehmigen kann, während
`Write`/`Edit` das sind, was ein Berechtigungssystem am ehesten absichern will, wurde in der
Sitzung ausdrücklich als Spekulation gekennzeichnet und vom Subagenten nicht bestätigt.
- **Eine Korrektur im Verlauf:** die früher in der Sitzung geäußerte Behauptung, es gebe einen
`/auto`-Slash-Command, war falsch und wurde zurückgenommen.
- **Zustand dieser Instanz:** `~/.claude/settings.json` enthält nur `theme`,
`inputNeededNotifEnabled` und `agentPushNotifEnabled`, kein `permissions.defaultMode`. `auto`
war also die eingebaute Voreinstellung für Plan und Version, keine hier getroffene Wahl.
- **Empfehlung der Sitzung:** in `auto` bleiben. Der Ausstieg kostet Berechtigungsabfragen auf
allem, für ein Problem, das eine stehende Arbeitsregel bereits löst. Als Alternative wurde
`permissions.defaultMode: "acceptEdits"` in der globalen Settings-Datei genannt - genehmigt
Edits, fragt bei Shell-Kommandos nach und ist damit praktisch die Umkehrung der Beschwerde.
## Aufgaben
- [ ] Der Entwurf für Produkt-Feedback - eine injizierte Anweisung, die das sichtbare
Arbeitsverhalten ändert, sollte dokumentiert und einzeln abschaltbar sein - liegt lokal und
wartet darauf, dass Torben ihn abschickt oder verwirft.
## Nicht übernommen
- **Die konkreten heredoc-Umbauten an `lint.py`, `frontmatter_io.py` und `run_budget.py`.** Sie
gehören inhaltlich zu den Issues #12/#13 und sind auf
[[Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31]]
erfasst. Hier zählen sie nur als Beispiel für die Diff-Frage.
- **Die Sandbox-Hypothese als Erklärung.** Bewusst nicht auf eine Seite übernommen: sie war als
Spekulation gekennzeichnet und wurde nicht bestätigt. Übernommen wurde stattdessen der
Negativbefund, dass die Dokumentation zur Bash-Präferenz schweigt.
- **Die vollständige Aufzählung der sechs `--permission-mode`-Werte mit ihren Bedeutungen.** Nur
`auto` war Gegenstand der Sitzung; für die anderen fünf liegt außer dem Namen nichts vor, und
eine Seite, die sie erklärt, würde das erfinden.
- **Der Wortlaut des Feedback-Entwurfs.** Er ist unabgeschickter Entwurfstext, kein Befund.
## Verwandte Entities
- [[Claude Code]]
- [[wikitool]]
## Verwandte Concepts
- [[Claude Code Auto Mode]]
- [[Diff-Reviewable Agent Edits]]
@@ -0,0 +1,170 @@
---
type: types/source.md
source_type: transcript
author: Claude Code (claude-opus-5)
raw_files: ['raw/notes/Conversation Transcript - Comma Bug, Budget Refund and Lint Report Path Session 2026-08-31.md']
source_language: en
date: 2026-08-31
tags: [wikitool, cli, frontmatter, yaml, iteration-budget, lint, raw-immutability, gitea]
entities: [wikitool, Chemenu, AGENTS.md, Gitea]
concepts: [Iteration and Cost Limits, Mass-Update Gate, Lint Workflow, KB Stack Versioning, Detect-Repair Asymmetry]
summary: Sitzung, die Komma-Werte in --set ausdrueckbar macht, das Flow-Quoting im Frontmatter repariert, abgelehnte Aufrufe dem Iteration Budget zurueckerstattet, die Obergrenze auf 60 hebt und lint seinen Reportpfad nennen laesst (Stack 1.2.0)
---
# Source: Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31
**Autor:** Claude Code (claude-opus-5)
**Datum:** 2026-08-31
**Raw-Dateien:** raw/notes/Conversation Transcript - Comma Bug, Budget Refund and Lint Report Path Session 2026-08-31.md
**Typ:** Notes
## Zusammenfassung
Das Transkript ist eine vom Assistenten am Sitzungsende rekonstruierte Zusammenfassung, kein
wörtliches Protokoll; die zitierten Befehlsausgaben sind echt, Torbens Anweisungen kurz und
wörtlich, die Begründungen des Assistenten verdichtet. Es ist eines von drei Transkripten
derselben Sitzung; die beiden anderen behandeln Issue-Triage und den `auto`-Berechtigungsmodus
des Harness und werden getrennt eingelesen.
Die Sitzung schloss die Gitea-Issues #12 und #13 und lieferte Stack-Version `1.2.0` aus
(Commit `40adbb7`), gefolgt von einer Inhaltskorrektur (`5426a6e`). Inhaltlich sind es vier
Änderungen: `--set` kann Arraywerte mit Komma ausdrücken (Escape `\,` und wiederholtes `--set`,
das anhängt statt zu ersetzen), `dump_frontmatter` quotet solche Werte beim Schreiben korrekt,
das Iteration-Budget erstattet einen Slot zurück, wenn ein Aufruf abgelehnt wurde, und die
Obergrenze steigt von 30 auf 60. Dazu nennt `lint` jetzt den Pfad seines Reports und schreibt
ihn immer.
Der Fix machte eine ältere Contract-Verletzung reparierbar: eine Rohdatei war beim Ingest vom
2026-08-30 umbenannt worden, um zum Flag zu passen. Sie bekam ihren ursprünglichen Namen
zurück. Dabei fiel die Lücke auf, die als Issue #14 offen ist - kein `wikitool`-Befehl schreibt
`raw_files:` auf einer bestehenden Seite, obwohl `lint` und `sources coverage` kaputte
Referenzen zuverlässig melden. Das ist der Fall, den [[Detect-Repair Asymmetry]] beschreibt.
## Kernaussagen
- **Ein Trennzeichen ohne Escape macht legale Daten unausdrückbar.** `parse_list()` splittete
hart auf `,`. Shell-Quoting hilft nicht: die Quotes sind längst weg, bevor der Wert den
Parser erreicht. Ein `raw_files:`-Pfad mit Komma im Dateinamen war damit nicht ausdrückbar -
und der Ausweg, den ein Agent tatsächlich nahm, war, die Rohdatei umzubenennen, also die
Immutabilitätsregel aus `raw/CONTRACT.md` zu brechen.
- **Beide Vorschläge aus Issue #12 wurden umgesetzt, weil sie verschiedene Fälle bedienen:**
`\,` als literales Komma über einen Lookbehind (`re.compile(r"(?<!\\),")`) plus Unescape je
Element, und wiederholtes `--set` auf einem *Array*-Feld hängt an statt zu ersetzen. Skalare
behalten „last one wins", weil es dort nichts anzuhängen gibt. Die Append-Form ist die
trennzeichenfreie und damit die richtige, wenn ein Element selbst ein Komma enthält. Der
Escape reicht über denselben Helper auch bis `xref add --entities`.
- **Der zweite Defekt kam vom Test, nicht vom Issue.** Der End-to-End-Test - Rohdatei mit Komma
anlegen, mit `\,` referenzieren, die geschriebene Seite zurücklesen - fiel weiterhin durch.
Escape und Append waren korrekt; die *Datei* war es nicht. `dump_frontmatter` schreibt Listen
im Flow-Stil (`[a, b]`), aber `_format_scalar` entschied über das Quoting mit einer
Round-Trip-Probe auf Dokumentebene, wo ein Komma ein gewöhnliches Zeichen ist. Innerhalb von
`[...]` ist es ein Indikator, und `raw_files: [raw/notes/Versioning, CI-CD.md]` liest sich als
zwei Elemente zurück.
- **Behoben in `frontmatter_io.py`, ohne das Designprinzip der Datei aufzugeben:**
`_round_trips_as_string(text, flow=True)` probt in genau dem Kontext, in dem der Wert
geschrieben wird, und fragt weiterhin den YAML-Loader, statt Regeln aufzuzählen. Der neue
Helper `_quote()` lässt sich vom Dumper eine einelementige Flow-Sequenz geben und streift die
Klammern ab, weil ein blanker Plain-Scalar aus `safe_dump` einen `...`-Dokumentende-Marker
mitbringt - für ein Dokument richtig, in einer Liste Unsinn.
- **Bestehende Ausgabe bleibt unverändert:** `tags: [k8s, ci-cd]` bleibt ungequotet,
`year: '1945'` bleibt exakt wie zuvor gequotet. Neu gequotet werden nur Werte, die vorher
still zerbrochen sind.
- **Das Budget zählte Reibung statt Iteration.** Die Rückerstattung ist nicht auf Exit-Code 1
gekeyt - das hätte `lint --fail-on-error` gratis gemacht, sobald es etwas findet - sondern
auf `_util.fail()`. `fail()` heißt: der Befehl hat *abgelehnt* (zurückgewiesenes Argument
oder ein lesender Check, der Befunde meldet), es ist nichts passiert, also Erstattung. Ein
Befehl, der seine Arbeit getan hat und danach ein Nicht-Null-Ergebnis meldet, wirft
`typer.Exit(1)` direkt und bleibt gezählt; `lint --fail-on-error` ist genau dieser Fall, denn
es hat seinen Report vorher geschrieben.
- **Mechanik der Erstattung:** `record_and_check()` meldet zurück, ob es belastet hat, und
`cli._run_traced` ruft im `finally`-Block `run_budget.refund()`, wenn der Prozess durch
`fail()` verlassen wurde. Der Aufruf bleibt in `recent`, damit der Loop-Breaker ihn weiterhin
sieht - für eine wiederholt kaputte Invokation ist der Loop-Breaker das richtige Instrument,
nicht der Zähler.
- **Verworfen:** Schreibvorgänge an den Schreibstellen zu markieren (35 Stellen in 15 Dateien),
um die Erstattung auf „es wurde nichts geschrieben" zu keyen. Das ist fail-open: eine neue
Schreibstelle, die den Marker vergisst, schwächt still ein Gate.
- **Obergrenze 30 → 60** auf Torbens Anweisung („verdopple die Tool call Limits zusätzlich").
Das Kalibrierungsband (5-15 einfach, 15-25 komplex) blieb unangetastet, weil es die Arbeit
beschreibt; die Obergrenze beschrieb nichts und lag so dicht am Band, dass der Overhead eines
realen Ingests sie allein erreichte. Nachgezogen in `AGENTS.md`, `instructions/gates.md`,
`tools/CONTRACT.md`, `README.md`, der `work plan`-Vorlage und der Einheitengröße in
`migrate-corpus.md` (jetzt „near 55 pages; aim for 48 or fewer").
- **Der Loop-Breaker blieb bewusst bei 3** und wurde zurückgemeldet statt still mitverdoppelt:
er ist ein Detektor für drei identische Aufrufe, kein Budget, und eine Verdopplung ließe
einen festgefahrenen Agenten doppelt so lange kreisen.
- **`lint` schrieb ohne `--markdown` gar keine Datei** und kippte den vollen Report nach
stdout. Es gab also keinen Pfad zu nennen und keinen Weg zurück in einen übersprungenen
Abschnitt außer einem zweiten Lauf. Jetzt wird der volle Report immer geschrieben,
standardmäßig nach `reports/Lint Report <datum>.md`, und der Pfad ausgegeben; `--markdown`
überschreibt weiterhin das Ziel. Gedruckt werden nur Abschnitte mit Befunden, `--full` druckt
alles, `--json` druckt die Befunde und schreibt nichts.
- **Die Skills wurden mitgezogen:** `wiki-lint` und `wiki-status` sagen jetzt beide, die Datei
zu lesen statt `lint` erneut aufzurufen. `wiki-status` Schritt 3 nimmt die Hub-Statistik aus
der Reportdatei, weil sie eine Statistik und kein Befund ist und deshalb nicht mehr in der
gedruckten Zusammenfassung auftaucht.
- **Nicht umgesetzt:** `lint` ganz vom Budget auszunehmen, der dritte Vorschlag aus Issue #13.
Das Issue selbst verweist die Frage in eine eigene Entscheidung, und der Fall hat sich
verschoben, seit `lint` eine Datei schreibt.
- **658 Tests grün**, in der normalen und in der gehärteten Umgebung aus Issue #8
(`GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null HOME=<leer>`). Zwei neue Tests
fielen dort zunächst mit `ERROR No author configured for this instance` - der dritte und
vierte Fall derselben stillen Umgebungsabhängigkeit; behoben, indem die Tests `WIKI_AUTHOR`
selbst setzen.
- **Das [[Mass-Update Gate]] hielt an einem 21-Dateien-Changeset**, druckte die Aufschlüsselung
nach Bereich und die `--confirm`-Zeile; der Assistent gab die vollständige Liste wieder und
stoppte. Torbens Freigabe war ein Wort, danach entstand `40adbb7` mit 21 geänderten Dateien,
593 Einfügungen und 73 Löschungen. Verifiziert wurde anschließend gegen das Repository, dass
`HEAD` gleich `origin/main` ist, der Baum sauber und `VERSION` gleich `1.2.0` - nicht gegen
die Erfolgszeile des Werkzeugs.
- **Die Rückbenennung der Rohdatei** lief über `git mv` mit 100 % Ähnlichkeit, also mit
erhaltener Historie; `raw_files:` und die `**Raw-Dateien:**`-Prosazeile der betroffenen
Source-Seite wurden korrigiert, `sources rebuild-index` baute den Provenance-Index neu,
`sources coverage` meldete 0 nicht abgedeckte und 0 kaputte Referenzen, `lint` war über 255
Seiten sauber. Der korrigierte Wert steht seither gequotet im Frontmatter - ohne den zweiten
Fix hätte die Rückbenennung sich beim Schreiben selbst wieder zerlegt.
- **Issue #14 - die Lücke, die dabei sichtbar wurde:** kein `wikitool`-Befehl schreibt
`raw_files:` auf einer bestehenden Seite. `touch` deckt die Felder ab, die die Seite selbst
beschreiben, `xref` die Seiten-Referenz-Arrays, und `raw_files:` ist keines von beidem, weil
es auf einen Pfad zeigt und nicht auf einen Seitentitel. Invariante 1 aus `AGENTS.md`
verbietet die Handeditierung dieses Feldes nicht - es steht in keiner ihrer Aufzählungen -,
aber sie widerspricht dem Kernprinzip, dass Mechanisches das Werkzeug erledigt. Vorgeschlagen
sind `sources relink` oder, näher am Problem, ein `raw rename`, das `git mv` und jede
referenzierende Source-Seite in einem Schritt erledigt: die einzige Form, in der der
Zwischenzustand „Datei weg, Referenz hängt" nie existiert.
## Aufgaben
- [ ] Gitea-Issue #14 - `raw rename` bzw. `sources relink`, damit `raw_files:` auf einer
bestehenden Seite nicht mehr von Hand korrigiert werden muss
- [ ] Offen und bewusst vertagt: ob `lint` ganz vom Iteration Budget ausgenommen wird (dritter
Vorschlag aus Issue #13)
## Nicht übernommen
- **Die vollständige Dateiliste des 21-Dateien-Changesets** aus der Gate-Ausgabe. Sie ist
Betriebsdetail eines einzelnen Publishes; nach dem Commit trägt sie keine dauerhafte Aussage
mehr, und der Commit selbst ist genannt.
- **Die beiden Schwestertranskripte derselben Sitzung** (Issue-Triage und Label-Schema,
`auto`-Berechtigungsmodus). Sie werden getrennt eingelesen und bekommen eigene Source-Seiten;
hier stünden sie unbelegt.
- **Die Gitea-Läufe 62, 63 und 64** als eigene Artefakte. CI-Grün zu einem Zeitpunkt ist ein
Zustand, keine dauerhafte Aussage; die Testzahl und der Umgebungsdefekt sind übernommen.
- **Die Einzelheiten der 658 Tests.** Übernommen sind nur die Gesamtzahl und der Defekt, der
sich daran zeigte.
- **Die Issues #12 und #13 als eigene Seiten.** Sie sind geschlossen, und ihr Ergebnis steht
auf [[wikitool]], [[Iteration and Cost Limits]] und [[Lint Workflow]].
## Verwandte Entities
- [[wikitool]]
- [[Chemenu]]
- [[AGENTS.md]]
- [[Gitea]]
## Verwandte Concepts
- [[Iteration and Cost Limits]]
- [[Mass-Update Gate]]
- [[Lint Workflow]]
- [[KB Stack Versioning]]
- [[Detect-Repair Asymmetry]]
@@ -0,0 +1,100 @@
---
type: types/source.md
source_type: transcript
author: Torben Nehmer
raw_files: [raw/notes/Conversation Transcript - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31.md]
source_language: en
date: 2026-08-31
tags: []
entities: [ENVIRONMENT.md, CLAUDE.md, AGENTS.md, wikitool]
concepts: [Optional Instance Context File, Personalization Plane]
summary: 'Sitzung, die ENVIRONMENT.md als optionales drittes Root-Dokument einfuehrt: gitignored, doctor meldet aber scheitert nie, Kontext ohne Autoritaet (1.8.0, Issue #24)'
---
# Source: Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31
**Autor:** Torben Nehmer
**Datum:** 2026-08-31
**Raw-Dateien:** raw/notes/Conversation Transcript - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31.md
**Typ:** Notes
## Zusammenfassung
Sitzung, die `ENVIRONMENT.md` als drittes Root-Dokument der Sitzungsebene einführt, neben
`USER.md` und `SOUL.md`. Die Datei hält fest, womit *ein bestimmter Checkout* arbeitet: Harness,
publizierte Skills, erreichbare MCP-Server, Connectoren, Git-Remotes, wo CI läuft. Ausgeliefert
als Stack-Version 1.8.0 im Commit `a243a4a`, Gitea-Issue #24 in derselben Sitzung angelegt und
geschlossen.
Die Sitzung begann mit einem Widerspruch: der Nutzer nannte Issue #10, beschrieb aber eine ganz
andere Aufgabe. #10 ist Coverage-Reporting; kein offenes Issue passte zur Beschreibung. Statt
eine der beiden Lesarten zu wählen, wurde nachgefragt — die Antwort war "beides", woraufhin für
die beschriebene Arbeit ein neues Issue entstand.
Inhaltlich ist die Seite die Abgrenzung gegen die bestehende [[Personalization Plane]]: dasselbe
Muster aus Template, Setup-Schritt und Health-Check, aber an drei Stellen bewusst anders —
optional statt Pflicht, gitignored statt committet, und ausdrücklich Kontext ohne Autorität.
## Kernaussagen
- **Ein Health-Check darf eine optionale Datei melden, aber nie an ihr scheitern.**
`doctor.check_environment()` gibt `OK` bei Abwesenheit, `OK` bei ausgefüllter Datei und `WARN`
nur bei einem umbenannten, nie ausgefüllten Template. Aus dem Docstring der Funktion:
"Missing it costs a session some questions, not correctness, so this check never FAILs - the
whole point of the file is that it is optional, and a FAIL would make it mandatory by the back
door." Verworfen wurde `FAIL` bei fehlender Datei, wie es der `personalization`-Check tut.
- **Gitignored, weil zwei Clones zwei Umgebungen sind.** Eine committete Fassung gäbe dem
zweiten Clone Antworten, die falsch sind statt zu fehlen — und falsch ist hier schlimmer, weil
die Datei geglaubt wird. `USER.md`/`SOUL.md` sind demgegenüber committet und nur vom Export
ausgenommen.
- **Das Ignore-Muster muss eine Datei von ihrem eigenen Template trennen.** Das nachlässige
`ENVIRONMENT.md*` würde beide schlucken. `docs verify` prüft deshalb beide Richtungen:
`ENVIRONMENT.md` in `REQUIRED_IGNORE_CANARIES`, `ENVIRONMENT.md.template` in
`REQUIRED_TRACKED_PATHS`. Der `.gitignore`-Eintrag ist verankert (`/ENVIRONMENT.md`).
- **Kontext, keine Autorität.** Die Datei beschreibt, was da ist, nicht was erlaubt ist. Ein
gelisteter Remote autorisiert kein `git push` — Invariante 5 führt weiter über
`wikitool publish` —, ein gelisteter MCP-Server öffnet kein Gate, und nichts darin ist eine
Quelle nach Invariante 3. Keine Zugangsdaten: die Datei liegt im Klartext im Arbeitsverzeichnis
und in jedem Agenten-Kontext.
- **Import statt Link in [[CLAUDE.md]], weil die Entscheidung nebenbei fällt.** Der in die Datei
geschriebene Prüfstein: "a session that has to go look the answer up will instead ask the user
again, which is the cost the file exists to remove." `ENVIRONMENT.md` ist zugleich der erste
Import, der legitim nie existieren darf — die Toleranz gegenüber unaufgelösten Imports gab es
schon vorher für `USER.md`/`SOUL.md` vor dem Setup, hier wird sie zum Dauerzustand.
- **`instructions/dev/` schied als Ort aus, obwohl der Auftrag "im dev skillset" sagte.**
`instructions/CONTRACT.md` verbietet Referenzen von außen auf dieses Verzeichnis, weil sie
beim `dist export` ins Leere zeigen würden; ein Link aus `CLAUDE.md` bräuchte die
`dist:strip`-Marker-Konstruktion. Mehr Mechanik für weniger Reichweite — und der Inhalt
(MCP-Server, Remotes) betrifft auch reine Content-Sitzungen.
- **[[AGENTS.md]] braucht einen eigenen Abschnitt, nicht nur die Tabellenzeile**, weil die
übrigen Harnesses `CLAUDE.md` nie lesen und die Datei sonst nur unter Claude Code existierte.
## Aufgaben
- [x] Gitea-Issue #24 angelegt (`prio/2`, `size/M`) und nach der Umsetzung geschlossen
- [x] `ENVIRONMENT.md` für diesen Checkout angelegt — 40 Zeilen, nur Werte
## Nicht übernommen
- **Der vollständige Turn-für-Turn-Verlauf.** Das Transkript hält ihn fest; hier steht, was
daraus dauerhaft gilt.
- **Die mechanischen Folgeänderungen**: die Umnummerierung von `setup-instance.md` (Schritte
9-13 zu 10-14) samt der Querverweis-Korrektur "Schritt 11" → "Schritt 12", und die Korrektur
von `CLAUDE.md`s Formulierung "the fourth import" zu "the last import". Beides ist im Repo
nachlesbar und trägt keine Regel.
- **Der Inhalt der für diesen Checkout angelegten `ENVIRONMENT.md`** (welche Remotes, welcher
MCP-Server). Die Datei ist gitignored und beschreibt eine Arbeitskopie, nicht das Repo — als
Wiki-Wissen wäre sie genau die zweite, driftende Kopie, die die Datei selbst vermeiden soll.
- **Der Coverage-Teil derselben Sitzung.** Eigenes Transkript, eigene Quellseite: derselbe
Publish, aber ein anderes Thema.
## Verwandte Entities
- [[ENVIRONMENT.md]] - in dieser Sitzung entstanden
- [[CLAUDE.md]] - importiert die neue Datei
- [[AGENTS.md]] - Namenstabellen-Zeile und eigener Abschnitt „Environment"
- [[wikitool]] - `doctor`-Check, Root-Allowlist von `dist export`, Ignore-Kanarien
## Verwandte Concepts
- [[Optional Instance Context File]] - die Verallgemeinerung, in dieser Sitzung entstanden
- [[Personalization Plane]] - das Muster, gegen das abgegrenzt wird
@@ -0,0 +1,124 @@
---
type: types/source.md
source_type: transcript
author: Claude Code (claude-opus-5)
raw_files: [raw/notes/Conversation Transcript - Gate Counting and Measured Calibration Session 2026-08-31.md]
source_language: en
date: 2026-08-31
tags: [gate, mass-update-gate, iteration-budget, calibration, publish, measurement]
entities: [wikitool, Chemenu]
concepts: [Mass-Update Gate, Iteration and Cost Limits]
summary: 'Sitzung, die zwei nie gemessene Grenzen an realen Laeufen kalibriert: generierte Dateien zaehlen nicht mehr gegen das Mass-Update Gate, und das Kalibrierungsband fuer komplexe Workflows steigt von 15-25 auf 20-35 Aufrufe (Stack 1.5.0)'
---
# Source: Conversation - Gate Counting and Measured Calibration Session 2026-08-31
**Autor:** Claude Code (claude-opus-5)
**Datum:** 2026-08-31
**Raw-Dateien:** raw/notes/Conversation Transcript - Gate Counting and Measured Calibration Session 2026-08-31.md
**Typ:** Notes
## Zusammenfassung
Das Transkript ist eine treue Zusammenfassung, kein wörtliches Protokoll: Torbens Anweisung
steht wörtlich, die Aufrufzahlen und die Vorher/Nachher-Dateizahlen sind in der Sitzung
gemessene Werte, die Begründungen des Assistenten sind verdichtet. Es ist eines von zwei
Transkripten dieses Sitzungsabschnitts; das andere behandelt `touch --set/--add/--remove` und
wird getrennt eingelesen.
Ausgelöst hat die Sitzung eine Beobachtung, kein Issue: drei gewöhnliche Ingests waren
nacheinander am [[Mass-Update Gate]] stehen geblieben, und Torben hielt zugleich das
dokumentierte Kalibrierungsband für die Anzahl der Tool-Aufrufe für zu niedrig. Beide Hälften
erwiesen sich als messbar statt als Geschmacksfrage, und die Messwerte lagen bereits im
Repository - die Changesets der drei Ingests und die Sitzungszähler in
`tools/.wikitool_session/budget.json`.
Ergebnis ist Stack-Version `1.5.0` (Commit `3166c31`, 9 Dateien, 678 Tests grün): generierte
Dateien werden weiterhin committet und gepusht, zählen aber nicht mehr gegen die Gate-Schwelle,
und das Band für einen komplexen Multi-Tool-Workflow steigt von 15-25 auf 20-35 Aufrufe. Die
Schwelle von 10 und die Budget-Obergrenze von 60 blieben unverändert.
## Kernaussagen
- **Die Beobachtung des Nutzers, wörtlich:** „automatic erzeugte files wie Index.md können wir
Raus nehmen. Wir hatten drei normale ingests und alle liegen ins Gate wo immer ein Haufen
Datenbank files dazu kommen" - und zum zweiten Punkt: „Ich habe den Eindruck, dass die
Maßgabe 15-20/29-25 zu gering ist".
- **Die Teile lagen schon da und waren nur nie verbunden.** `git_publish.py` kannte über
`is_generated()` bereits `kb/index.md`, `kb/log.md`, `kb/provenance.md` und jede `INDEX.md`,
und besaß mit `GATE_EXEMPT_PREFIXES = ("work/",)` plus `counted_files()` bereits einen
Ausnahmemechanismus. `is_generated` wurde nur zur *Gruppierung* der angezeigten Dateiliste
benutzt, unter der Überschrift „rebuilt by wikitool - no review needed" - ein Hinweis, der dem
Prüfer sagte, er müsse diese Dateien nicht lesen, während die Zählung ihn weiter dazu
brachte, sie freizugeben.
- **Begründung der Ausnahme:** Eine generierte Datei trägt keine Entscheidung. Sie ist über
`index rebuild` bzw. `sources rebuild-index` aus dem Baum reproduzierbar, ihre Freigabe
entscheidet also nichts und erzeugt nur die Prüfermüdung, gegen die die Schwelle existiert.
Committet und gepusht werden sie unverändert.
- **Gemessen an den drei realen Changesets desselben Tages:** Comma Bug 14 Dateien, gezählt
vorher 14 (Gate) / jetzt 9; Issue Triage 16, gezählt 16 (Gate) / jetzt 9; Auto Mode 11,
gezählt 11 (Gate) / jetzt 5. Keiner der drei war eine Massenänderung, keiner würde jetzt noch
anhalten.
- **Das Gate bleibt scharf:** Zehn echte Seiten lösen weiterhin aus, egal wie viel
Index-Rauschen mitfährt, und ein Test hält genau das fest, damit die Ausnahme nicht still zur
Abschaltung wird.
- **Die Weigerungszeile führt beide Gründe getrennt auf** - „3 under work/ and 5 generated by
wikitool committed but not counted". Ein Prüfer, der bei einem 14-Dateien-Commit „9 counted"
liest, hält die Differenz sonst für einen Fehler. Die Trennung hält die Gründe außerdem
ehrlich: Scratch-Zustand und abgeleitete Ausgabe sind nicht dasselbe.
- **Der `--confirm`-Token fasst jetzt nur noch zusammen, was ein Mensch tatsächlich gelesen
hat.** Eine neu gebaute `INDEX.md` macht eine bereits erteilte Freigabe nicht mehr ungültig.
- **Die alte Zählweise war ungetestet.** Alle 67 Gate-Tests liefen grün, *bevor* die Tests für
das neue Verhalten geschrieben waren - kein Test hatte je behauptet, dass generierte Dateien
mitgezählt werden. Das ist ein Teil der Erklärung, warum das Verhalten so lange unbemerkt
blieb.
- **Für die zweite Hälfte lag die Evidenz in `tools/.wikitool_session/budget.json`**, das die
Aufrufzahlen je Sitzung ohnehin mitschreibt. Vier reale Ingests: `ingest-comma-bug-2026-08-31`
30 Aufrufe, `ingest-transcript-personalization-plane` 29, `ingest-issue-triage-2026-08-31` 26,
`ingest-auto-mode-2026-08-31` 24. Eine Stack-Sitzung (`issue-14-2026-08-31`) lag bei 9.
- **Jeder dieser Ingests lag auf oder über der Decke des dokumentierten Bandes von 15-25**, ohne
etwas Ungewöhnliches zu tun. Eine Richtgröße, die der Normalfall überschreitet, ist keine
Richtgröße: sie lehrt einen Agenten, dass die Zahlen dekorativ sind - genau das Versagen,
gegen das das Iteration-Budget immun sein sollte.
- **Neues Band: ~5-15 für eine einfache Aufgabe (gemessen 5-9), ~20-35 für einen komplexen
Multi-Tool-Workflow.** Nachgezogen in `run_budget.py`, `instructions/gates.md` sowie den
Skills `wiki-ingest` und `wiki-lint`. Die Obergrenze von 60 blieb unangetastet - sie ist kein
Ziel, sondern der Punkt, ab dem eine Sitzung als festgefahren gilt.
- **Die Provenance-Unterscheidung wurde bewusst erhalten.** Das alte Band ist eine übernommene
Branchen-Faustregel, und [[Iteration and Cost Limits]] führt es mit Quelle genau als solche.
Es wurde **nicht** umgeschrieben: es ist eine belegte Aussage über den Stand der Technik,
nicht über diese Instanz. Was diese Instanz gemessen hat, ist eine andere Behauptung, die
ihre eigene Quelle braucht - weshalb sie auf dieses Transkript wartete, statt direkt in die
Seite geschrieben zu werden.
- **`gates.md` hält jetzt zusätzlich fest, woher die Zahl kommt und wie man sie neu misst**, und
nennt dafür `tools/.wikitool_session/budget.json`. Eine Richtgröße ohne Messvorschrift veraltet
still - was hier passiert war.
## Aufgaben
- [ ] Keine offenen Punkte aus dieser Sitzung. Beide Kalibrierungen sind in `1.5.0` ausgeliefert.
## Nicht übernommen
- **Die Testzahlen im Einzelnen.** Übernommen sind die Gesamtzahl (678) und der Befund, dass die
67 Gate-Tests das alte Zählverhalten nie geprüft hatten; die einzelnen Testnamen tragen keine
dauerhafte Aussage.
- **Das Schwestertranskript derselben Sitzung** zu `touch --set/--add/--remove` und den
write-once-Frontmatterfeldern. Es wird getrennt eingelesen und hat eine eigene Source-Seite;
hier stünde es unbelegt.
- **Eine eigene Concept-Seite für „Kalibrierung aus Messung".** Die Aussage - eine Richtgröße
ohne Messvorschrift veraltet still - steht als Kernpunkt auf [[Iteration and Cost Limits]],
wo sie den konkreten Fall trägt. Eine zweite, allgemeine Seite wäre derselbe Satz an einem
zweiten Ort.
- **Die Aufrufzahl 9 der Stack-Sitzung `issue-14-2026-08-31`** als eigener Beleg für das
Einfach-Band. Sie ist im Transkript ein Vergleichswert am Rand; das Band 5-15 ist mit
„gemessen 5-9" bereits als gemessene Größe geführt.
## Verwandte Entities
- [[wikitool]]
- [[Chemenu]]
## Verwandte Concepts
- [[Mass-Update Gate]]
- [[Iteration and Cost Limits]]
@@ -0,0 +1,129 @@
---
type: types/source.md
source_type: transcript
author: Torben
raw_files: [raw/notes/Conversation Transcript - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31.md]
source_language: en
date: 2026-08-31
tags: [tests, ci, tooling, quality]
entities: [wikitool, Chemenu, Gitea Actions, AGENTS.md]
concepts: [Green Suite Blind Spot, Ambient Environment Dependency, Structural Enforcement over Documented Rule]
summary: 'Sitzung, die die Testsuite gegen stille Umgebungsabhaengigkeiten haertet (1.7.1, Issue #8): autouse-Fixture statt zweitem CI-Job, 702 Tests in vier Umgebungen, plus der Befund, dass checkout@v7 den CI-Container selbst konfiguriert'
---
# Source: Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31
**Autor:** Torben
**Datum:** 2026-08-31
**Raw-Dateien:** raw/notes/Conversation Transcript - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31.md
**Typ:** Notes
## Zusammenfassung
Die Sitzung setzt Gitea-Issue #8 um und liefert `1.7.1` (`31c9b81`, Tag `v1.7.1`): eine
autouse-pytest-Fixture, die jeden Test von der Maschine trennt, auf der er läuft. Der Anlass lag
Wochen zurück - der erste CI-Lauf, der überhaupt bis `pytest` kam (Run 52), warf zwei Tests um,
die auf jeder Entwicklermaschine monatelang grün waren, weil `config.default_author()` per
`git config user.name` die *globale* git-Konfiguration desjenigen las, der die Suite startete.
Die Quelle ist vor allem deshalb interessant, weil die Messung vor der Änderung ein anderes Bild
ergab als erwartet: die Suite war unter der gehärteten Umgebung **bereits grün** (695 Tests). Die
vier bekannten Fälle waren in `1.0.1` und `1.2.0` einzeln repariert, ein fünfter existierte in
diesem Moment nicht. Damit war die Änderung keine Reparatur, sondern ein Schutz - und ein Schutz,
dessen Wirkung getrennt nachgewiesen werden muss, weil "alles bleibt grün" über ihn nichts
aussagt. Die Sitzung führt diesen Nachweis explizit: ohne Fixture liefert `default_author()` in
einem Nicht-Repository den globalen git-Namen des Entwicklers, mit Fixture `None`.
Zwei Befunde gehen über den Issue-Text hinaus. Erstens deckt die Fixture auch git-eigene
Identitäts- und Ortsvariablen ab, die der Vorschlag nicht nannte. Zweitens - und für die
Bewertung der verworfenen Alternative entscheidend - zeigt das CI-Log von Run 79, dass
`actions/checkout@v7` inzwischen selbst eine globale git-Konfiguration im Job-Container anlegt.
Der Container ist damit nicht mehr die konfigurationsfreie Maschine, als die Run 52 ihn
vorgefunden hatte.
## Kernaussagen
- **Der Auslöser und seine Wiederholung.** Run 52 (2026-08-30) meldete `2 failed, 628 passed` mit
`AssertionError: ERROR No author configured for this instance.` Beide Tests wurden in `1.0.1`
repariert. In `1.2.0` führten **zwei neue Tests dieselbe Abhängigkeit erneut ein**, geschrieben
von jemandem, der das Issue vorher gelesen hatte. Der Issue-Kommentar zieht daraus den Schluss,
der die Sitzung steuert: "die Suite lädt neue Fälle schneller ein, als jemand sie findet."
- **Zwei Optionen, eine seit dem Kommentar entschieden.** Autouse-Fixture in `conftest.py` gegen
einen zweiten, gehärteten `pytest`-Schritt in CI. Der CI-Schritt meldet erst nach dem Push und
schützt den Lauf des Entwicklers nie - also genau dort nicht, wo die Fälle entstehen.
- **Die Messung vor der Änderung ergab 695 grüne Tests unter der gehärteten Umgebung.** Kein
fünfter Fall war offen. Das verschiebt die Änderung von Reparatur zu Schutz und macht einen
eigenen Wirksamkeitsnachweis nötig.
- **Der Wirksamkeitsnachweis.** In der Sitzung ausgeführt: `default_author() with the ambient
environment: 'Torben Nehmer'`. Unter der Fixture antwortet dieselbe Funktion `None`. Der neue
Test wäre vorher rot gewesen und ist nachher grün - was die Ausgangsmessung nicht zeigen
konnte.
- **Über den Vorschlag hinaus abgedeckt:** `GIT_DIR`, `GIT_WORK_TREE`, `GIT_AUTHOR_NAME`,
`GIT_AUTHOR_EMAIL`, `GIT_COMMITTER_NAME`, `GIT_COMMITTER_EMAIL`, `EMAIL`. Begründung im Code:
`GIT_AUTHOR_NAME` sticht `git config user.name` und ist damit derselbe Fehler durch eine andere
Tür; ein verirrtes `GIT_DIR` würde jedes Fixture-Repo auf den Checkout des Entwicklers zeigen
lassen.
- **`WIKI_TRACE_DIR` bleibt als einzige Variable gesetzt.** Tracing wird nie suite-weit
abgeschaltet, weil zwei Telemetrie-Tests behaupten, dass ein Trace geschrieben wird.
`isolated_trace_dir` nimmt `hermetic_environment` jetzt als Parameter - nicht für einen Wert,
sondern damit die Reihenfolge der beiden autouse-Fixturen ausgesprochen ist statt aus der
Deklarationsreihenfolge zu folgen.
- **Bewusst kein `WIKI_AUTHOR` in der Fixture-Basis.** Der billigere Weg wäre der falsche
gewesen: ein gemeinsamer Default macht den `None`-Zweig von `default_author()` untestbar, weil
dieser Zweig nur auf einer Maschine existiert, die niemanden kennt. Die Suite sähe grüner aus
und bewiese weniger.
- **Ein Test, der direkt patcht, bleibt.** `test_new_source_fails_hard_without_any_author` patcht
`default_author` weiterhin, obwohl die Umgebung jetzt ohnehin `None` liefern würde. Der Patch
pinnt den Wert unabhängig von der Umgebung und hält den Test damit bei der Fehlerbehandlung der
CLI statt bei der Umgebung.
- **Vier Umgebungen, ein Ergebnis: 702 Tests grün.** Entwickler-Shell; absichtlich vergiftet
(`WIKI_AUTHOR`, `WIKI_TRACE=0`, `WIKITOOL_*` und `GIT_*` auf Müll); `env -i` mit leerem `HOME`
und ohne git-Konfiguration; CI-Container (`702 passed in 15.84s`). Der vergiftete Lauf war im
Issue nicht verlangt und prüft die Gegenrichtung: nicht "übersteht die Suite, nichts zu haben",
sondern "übersteht sie, das Falsche zu haben".
- **Die Fixture wird selbst getestet.** `test_hermetic_env.py` behauptet die geleerten Variablen,
das leere `HOME`, dass `git config user.name` nichts antwortet, und alle drei Zweige von
`default_author()`. Begründung: eine Fixture, gegen die nichts assertet, kann eine Variable
verlieren, ohne dass ein Lauf rot wird - dasselbe Versagen eine Ebene höher.
- **`actions/checkout@v7` legt selbst eine globale git-Konfiguration an.** Aus dem Log von Run 79:
`Copying '/root/.gitconfig' to '/tmp/b93ea7a3-.../.gitconfig'` und `Temporarily overriding
HOME='/tmp/b93ea7a3-...' before making global git config changes`; der Tool-Environment-Schritt
schreibt zusätzlich `safe.directory` global. Der Job-Container hatte die Eigenschaft
"keine globale Konfiguration" in Run 52 also zufällig. Ein Guard, der darauf baut, hätte
irgendwann still aufgehört zu greifen.
- **CI bleibt bei einem Testlauf.** Der Kommentar am Tests-Schritt in `.gitea/workflows/ci.yml`
hält fest, warum der zweite Lauf nicht nachgerüstet wird.
- **Der `dist export`-Schritt meldete 11 Instructions und 5 Skills gegen 14 und 6 im Dev-Baum** -
Beleg, dass `instructions/dev/testing-conventions.md` die Distribution nicht erreicht.
## Aufgaben
- [x] Issue #8 umgesetzt, verifiziert und geschlossen (`1.7.1`, `31c9b81`, Tag `v1.7.1`)
- [ ] Gitea-Issue #22 (`prio/3`, `size/XS`): `lint` zählt Zitat-*Zeilen* statt Zitat-Blöcke
(`lint.py:157`), ein umbrochenes Zitat wird als vier gemeldet
- [ ] Gitea-Issue #23 (`prio/2`, `size/S`): nichts erzwingt, dass eine neue Tool-Variable in
`_WIKITOOL_ENV` landet - die Regel steht in `testing-conventions.md`, aber genau eine
Prosa-Regel war die Prämisse von #8
## Nicht übernommen
- **Die konkrete Liste der geleerten Variablen als Wiki-Inhalt.** Sie steht in `conftest.py` und
in `instructions/dev/testing-conventions.md`; eine dritte Kopie im `kb/` wäre die, die driftet
(AGENTS.md-Invariante 8). Die Kernaussagen nennen nur die Kategorien und die Begründung.
- **Die Publish- und Verifikationsmechanik** (`publish` ohne `--message` endet mit Exit 2,
`git ls-remote` als Gegenprobe). Das ist in `publish-cycle.md` und `SOUL.md` geregelt, nicht
Erkenntnis dieser Sitzung.
- **Die vollständigen Issue-Texte von #22 und #23.** Der Tracker hat Zustand und Verlauf, das
Wiki nicht; hier steht nur, dass und warum sie existieren.
- **Der `git init -q -b main`-Hinweis** zur `init.defaultBranch`-Advisory. Werkzeugdetail ohne
eigenen Erkenntniswert, steht in der Instruction.
## Verwandte Entities
- [[wikitool]]
- [[Chemenu]]
- [[Gitea Actions]]
- [[AGENTS.md]]
## Verwandte Concepts
- [[Green Suite Blind Spot]]
@@ -0,0 +1,132 @@
---
type: types/source.md
source_type: transcript
author: Claude Code (claude-opus-5)
raw_files: ['raw/notes/Conversation Transcript - Issue Triage, Labels and TODO Retirement Session 2026-08-31.md']
source_language: en
date: 2026-08-31
tags: [gitea, issues, labels, triage, ci-cd, paths-ignore, stack-dev]
entities: [Chemenu, Gitea, Gitea Actions, Gitea MCP Server, wikitool]
concepts: [Issue Label Scheme, KB Stack Versioning, Detect-Repair Asymmetry]
summary: 'Sitzung, die das gesamte offene Issue-Board priorisiert, den Beleg fuer greifende paths-ignore-Filter erbringt (Issue #11 geschlossen) und TODO.md zugunsten von Gitea-Issues mit prio/- und size/-Labels abschafft (Stack 1.2.1)'
---
# Source: Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31
**Autor:** Claude Code (claude-opus-5)
**Datum:** 2026-08-31
**Raw-Dateien:** raw/notes/Conversation Transcript - Issue Triage, Labels and TODO Retirement Session 2026-08-31.md
**Typ:** Notes
## Zusammenfassung
Das Transkript ist eine vom Assistenten am Sitzungsende rekonstruierte Zusammenfassung, kein
wörtliches Protokoll; die zitierten Befehlsausgaben und Issue-Titel sind echt. Es ist eines von
drei Transkripten derselben Sitzung. Die beiden anderen behandeln die Werkzeugkorrekturen zu
den Issues #12 und #13 (eingelesen als
[[Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31]])
und den `auto`-Berechtigungsmodus des Harness.
Die Sitzung hat drei Ergebnisse. Erstens wurde das gesamte offene Issue-Board priorisiert, mit
einem ausdrücklich benannten Kriterium: was laufende Arbeit blockiert oder beschädigt, nicht
was viel Aufwand kostet. Zweitens fiel beim Prüfen eines Publish der Beleg an, dass Gitea
`paths-ignore` wie GitHub auswertet; damit war Issue #11 ohne eine Zeile Code geschlossen.
Drittens wurde `TODO.md` gelöscht und durch Gitea-Issues mit einem zweiachsigen Label-Schema
ersetzt, das als [[Issue Label Scheme]] festgehalten ist.
Ausgeliefert wurde Stack-Version `1.2.1` (Commit `9fa70f3`, 5 Dateien): eine PATCH-Version,
weil die neue Regel unter `instructions/dev/` liegt und damit keine ausgelieferte Instanz
erreicht.
## Kernaussagen
- **Das Priorisierungskriterium war Schaden, nicht Aufwand.** Die Issues #12 und #13 kamen
gemeinsam an die Spitze, weil beide eine Regel gebogen hatten statt nur zu stören: der
Komma-Bug führte zur Umbenennung einer Rohdatei gegen die Immutability-Regel aus
`raw/CONTRACT.md`, und die Budget-Buchführung drängte die Sitzung in `--override-budget`
gegen Invariante 6. Ein Werkzeug, das seinen Benutzer regelmäßig gegen die eigenen
Invarianten des Stacks drückt, ist hier die teuerste Fehlerklasse.
- **Reihenfolge-Urteile mit Begründung.** #8 (Testhärtung) vor #10 (Coverage), weil eine
Coverage-Messung auf einer umgebungsabhängigen Suite die Umgebung mitmisst. #7 (`dist
upgrade`) galt als das bestgeschriebene Issue des Boards und trotzdem nicht als vorrangig,
weil es sich erst auszahlt, sobald eine zweite Instanz existiert. #6 (Backlink-Ranking) kam
ans Ende, weil es als einziges die Kern-Suchlogik ändert und keine Suchanfrage aktenkundig
ist, die heute falsch rankt; ohne diesen Vorher-Fall ist das eigene Abnahmekriterium des
Issues nicht erfüllbar. #3 (Produktname) wurde als "keine Priorität, sondern eine Uhr"
eingeordnet: technisch blockiert es nichts, wird aber mit jedem Commit teurer, der eine
weitere `llm-wiki-test1`-Referenz hinzufügt.
- **`paths-ignore` greift, und das ist jetzt beobachtet.** Commit `f916376` war ein reiner
Content-Publish (`kb/index.md`, `kb/log.md`, `kb/provenance.md`, acht Seiten unter `kb/*/**`,
eine Datei unter `raw/notes/`) und erzeugte keinen einzigen Lauf, während die Stack-Commits
davor und danach je zwei erzeugten. Der Befund wurde in den Kommentarkopf von
`.gitea/workflows/ci.yml` geschrieben, damit er nicht erneut als Annahme behandelt wird.
- **Der Befund entlastete ein zweites Issue.** Weil der Filter greift, läuft
`lint --fail-on-error` bei einem Content-Publish tatsächlich nicht mehr; die stärkste Hälfte
der Begründung für den nächtlichen Drift-Check aus Issue #9 bleibt damit stehen. Dessen
eigene Voraussetzung, ob dieser Gitea-Build `on: schedule` überhaupt auswertet, ist unberührt
und weiter offen.
- **Zwei Achsen, beide Pflicht, bewusst keine dritte.** `prio/1..3` und `size/XS..L`. Eine
Priorität ohne Kosten ist eine halbe Entscheidung, deshalb sind beide verpflichtend. Eine
dritte Achse (Art, Bereich, Status) wurde verworfen als der Punkt, ab dem eine Taxonomie
eigene Pflege braucht, auf einem Board mit einem einzigen Betreuer. Details auf
[[Issue Label Scheme]].
- **Der Ort der Regel war die tragende Entscheidung.** `README.md` und `AGENTS.md` gehen in
jede ausgelieferte Instanz, und eine ausgelieferte Instanz hat kein Issue-Board auf
`gitea.nehmer.net`. `instructions/dev/` ist der einzige Ort, der zugleich agentenlesbar ist
und nie ausgeliefert wird, weil `dist export` ihn vollständig ausschließt. Aus demselben
Grund war der Release ein PATCH.
- **Das CI-Versions-Gate greift auch für nicht ausgelieferte Pfade.** Sein Muster passt auf
`instructions/`, also verlangt eine Änderung unter `instructions/dev/` einen Versionsbump,
obwohl sie keine Instanz erreicht. Das wurde vor dem Bump in `ci.yml` nachgesehen statt
angenommen.
- **Die Notiz zur Recherchefähigkeit wurde vollständig nach Issue #15 übernommen**, samt
Quellen, Befund, der A/B/C-Tabelle mit der Entscheidung für C, dem Schnitt, der den Netzaufruf
aus `wikitool` heraushält, den Perplexity-Details einschließlich des
`/v1/sonar`-Abkündigungsdatums 2026-09-27 sowie sechs offenen Contract-Änderungen und drei
offenen Entscheidungen. Abnahmekriterien wurden ergänzt, weil die Notiz keine hatte. Die
inhaltliche Rahmung: Recherche ist der fehlende Ausgang aus Invariante 3. Heute ist "das Wiki
hat dazu keine belastbare Quelle" eine Sackgasse; Recherche wäre die Antwort "dann hol eine".
Die offene Entwurfsfrage ist nicht Skill oder nicht, sondern wohin ein Perplexity-Bericht
gehört, wenn `raw/` alles vom LLM Geschriebene ausschließt und `kb/` verlangt, dass jede
Aussage auf eine Datei unter `raw/` zurückführt.
- **Notiz auf #8:** Zwei Tests, die *während* des #12-Fix von jemandem geschrieben wurden, der
#8 vorher gelesen hatte, führten dieselbe stille Umgebungsabhängigkeit erneut ein. Die
interessante Frage verschiebt sich damit von "wie viele unbekannte Fälle gibt es" zu "die
Suite bekommt neue schneller, als jemand die alten findet".
## Aufgaben
- [ ] Issue #8 (Testsuite gegen Umgebungsabhängigkeiten härten, `prio/1 size/M`) ist das
nächste Arbeitspaket auf dem Board.
- [ ] Issue #9 bleibt offen an der Frage, ob dieser Gitea-Build `on: schedule` auswertet.
- [ ] Issue #3 (Produktname) läuft mit: jede weitere `llm-wiki-test1`-Referenz erhöht die
spätere Umbenennungslast.
## Nicht übernommen
- **Die vollständige Board-Tabelle mit allen zehn Issue-Nummern, Titeln und Labels.** Sie ist
ein Momentzustand des Boards und veraltet mit dem nächsten Triage-Lauf. Das Board selbst ist
die Quelle der Wahrheit; die Seite [[Issue Label Scheme]] hält stattdessen die Bedeutung der
Achsen fest, die stabil bleibt.
- **Der Inhalt der Issues #14 und #15 im Detail.** #14 ist auf
[[Detect-Repair Asymmetry]] bereits als der Fall beschrieben, den das Concept meint. #15 ist
eine offene Entwurfsfrage mit drei unentschiedenen Punkten; eine Concept-Seite dazu würde
einen Entwurf als Entscheidung darstellen, den niemand getroffen hat.
- **Die Reihenfolge-Begründungen zu den Issues #4, #5 und #10 im Einzelnen.** Sie tragen keine
über den Einzelfall hinausgehende Regel; das Kriterium, nach dem sie gefällt wurden, steht
oben.
- **Die Historie von `TODO.md`.** Ausdrücklich abbedungen: "An ihrer Historie bin ich nicht
interessiert."
## Verwandte Entities
- [[Chemenu]]
- [[Gitea]]
- [[Gitea Actions]]
- [[Gitea MCP Server]]
- [[wikitool]]
## Verwandte Concepts
- [[Issue Label Scheme]]
- [[KB Stack Versioning]]
- [[Detect-Repair Asymmetry]]
@@ -0,0 +1,89 @@
---
type: types/source.md
source_type: transcript
author: Claude Code (claude-opus-5)
raw_files: [raw/notes/Conversation Transcript - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31.md]
source_language: en
date: 2026-08-31
tags: []
entities: [wikitool, Chemenu, Gitea Actions]
concepts: [CI Integration]
summary: 'Sitzung, die einen nightly.yml-Workflow gegen Gitea-Issue #9 baut (schedule + workflow_dispatch, lint --fail-on-error als Kern), einen doctor-Bootstrap-Defekt findet und behebt, und die tatsaechliche Ausloesung des schedule-Triggers unverifiziert laesst'
---
# Source: Conversation - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31
**Autor:** Claude Code (claude-opus-5)
**Datum:** 2026-08-31
**Raw-Dateien:** raw/notes/Conversation Transcript - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31.md
**Typ:** Notes
## Zusammenfassung
Zweiter Teil derselben Sitzung wie
der Sitzungsmitschrift,
hier zu Gitea-Issue #9: `ci.yml`s `paths-ignore` unterdrückt CI bei einem reinen
Content-Publish (belegt in [[Gitea Actions]]), also läuft `lint --fail-on-error` dort nicht mehr
mit. `.gitea/workflows/nightly.yml` schließt diese Lücke mit `on: schedule` (`17 3 * * *` UTC)
plus `workflow_dispatch`, ohne Push-Trigger, in derselben Runner-Form wie `ci.yml`.
Vor dem Bau wurde die Vorbedingung geprüft, nicht angenommen: `curl -s
https://gitea.nehmer.net/api/v1/version` ergab `1.26.1` - weit über der 1.20-Version, die
Actions-Schedules einführte, was das Feature plausibel macht, aber nicht beweist, dass der
Cron auf diesem Server tatsächlich feuert.
Die Sichtbarkeitsfrage für einen fehlgeschlagenen Lauf wurde dem Nutzer vorgelegt statt
angenommen: die Empfehlung war ein automatisch angelegtes Issue bei Fehlschlag, Torben wählte
stattdessen ausdrücklich "Nur Gitea-Notification" - kein Meldeschritt im Workflow, Begründung im
Workflow-Kopf dokumentiert, damit die Auslassung nicht als vergessen gelesen wird.
Der erste `workflow_dispatch`-Testlauf (Run 83) schlug zu Recht fehl: `doctor` meldete `FAIL
git-identity` und `FAIL skills`, weil ein frischer Checkout noch keine Instanz ist - keine
git-Konfiguration im Container, keine publizierten Skills vor `instructions sync`.
`instructions verify` wurde dadurch nie erreicht, der eigentliche Prüfzweck des Laufs blieb
unbeobachtet. Behoben durch einen Bootstrap-Schritt (git-Identität setzen,
`tools/wikitool instructions sync`) vor `doctor`; Run 85 danach grün auf allen sieben Schritten.
Das Issue bleibt **offen**: beide beobachteten Läufe waren `workflow_dispatch`, keiner
`schedule`. Ob dieser Gitea-Stand den Cron-Trigger tatsächlich auslöst, lässt sich erst ab
2026-09-01 03:17 UTC beobachten.
## Kernaussagen
- Ein `workflow_dispatch`-Erfolg beweist, dass der Job läuft - nicht, dass der Zeitplan feuert.
Beide Aussagen wurden in der Sitzung bewusst auseinandergehalten.
- `doctor` prüft eine arbeitsfähige Instanz, kein bloßer Checkout ist eine - ein neuer Workflow,
der `doctor` aufruft, braucht denselben Bootstrap wie ein frischer Clone
(`instructions/bootstrap.md`).
- Die Entscheidung "wie wird ein Fehlschlag sichtbar" wurde dem Nutzer vorgelegt und explizit
gegen die Empfehlung des Agenten entschieden (Gitea-eigene Notification statt Auto-Issue).
- Der erste rote Lauf lag vor dem eigentlichen Prüfzweck des Workflows, nicht in ihm - der Wert
des Testlaufs war, das selbst zu zeigen.
## Aufgaben
- [x] `.gitea/workflows/nightly.yml` erstellt (schedule + workflow_dispatch, Runner-Form aus
`ci.yml` übernommen)
- [x] Lokal bewiesen, dass ein absichtlich gebrochener Korpus den Lauf rot macht
- [x] Bootstrap-Lücke (`doctor` git-identity/skills) gefunden und behoben
- [x] Run 85: alle sieben Schritte grün
- [ ] Beobachtung, ob `on: schedule` auf diesem Gitea-Stand tatsächlich feuert (ab
2026-09-01 03:17 UTC) - Gitea-Issue #9 bleibt dafür offen
## Nicht übernommen
- Die beiden Lint-Fixes (Gitea #20, #22) aus demselben `/stack-dev`-Aufruf sind eine eigene
Quelle - anderer Teil des Stacks, siehe
der Sitzungsmitschrift.
- Kein Artefakt-Upload für den Lint-Bericht (`reports/` ist gitignored) - bewusst weggelassen,
weil `lint --fail-on-error` die Befunde bereits ins Job-Log druckt; nachrüstbar, falls sich das
als unzureichend erweist.
## Verwandte Entities
- [[wikitool]]
- [[Chemenu]]
- [[Gitea Actions]]
## Verwandte Concepts
- [[CI Integration]]
@@ -0,0 +1,146 @@
---
type: types/source.md
source_type: transcript
author: Claude Code (claude-opus-5)
raw_files: [raw/notes/Conversation Transcript - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md]
source_language: en
date: 2026-08-31
tags: [wikitool, cite, xref, footnotes, schema, tests, gitea]
entities: [wikitool, Chemenu, Gitea]
concepts: [Command Round-Trip Integrity, Green Suite Blind Spot, Detect-Repair Asymmetry, Write-Once Frontmatter Fields, Denylist over Allowlist]
summary: 'Sitzung, die zwei Datenintegritaetsdefekte in wikitool findet und behebt: cite add loeschte Inhalt hinter dem Fussnotenblock (1.5.1, #17) und die Ref-Arrays einer Source-Seite waren unerreichbar (1.6.0, #18) - beide unter vollstaendig gruener Testsuite'
---
# Source: Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31
**Autor:** Claude Code (claude-opus-5)
**Datum:** 2026-08-31
**Raw-Dateien:** raw/notes/Conversation Transcript - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md
**Typ:** Notes
## Zusammenfassung
Das Transkript ist eine zusammenfassende Rekonstruktion der Sitzung, kein wörtliches Protokoll;
die zitierten Befehlsausgaben und die gemessenen Zahlen sind echt. Gegenstand sind zwei
Datenintegritätsdefekte in [[wikitool]], beide am 2026-08-31 gefunden und am selben Tag
behoben. Der erste: `cite add` löschte jeden Inhalt hinter dem Fußnotenblock (Gitea-Issue #17,
Stack `1.5.1`, Commit `bb4123b`). Der zweite: die Referenz-Arrays einer Source-Seite waren nach
dem Anlegen unerreichbar, während `xref add` dort ein undeklariertes `related:` schrieb, das
`xref remove` nicht mehr räumen konnte (Issue #18, `1.6.0`, Commit `ce03749`). Beide waren
`prio/1`.
Beide Befunde stammen aus einem Ingest: ein Subagent meldete, worauf er gestoßen war. Der
Bericht wurde nicht übernommen, sondern am Code nachgestellt, und die Prüfung erweiterte den
Umfang beide Male. Zwischen Befund und Reparatur lagen zwei Issues - was offen ist, gehört in
den Tracker, bevor Code angefasst wird.
Die Verallgemeinerung, die die Sitzung über sich selbst zieht, ist die dauerhaftere Aussage:
beide Defekte lebten unter einer vollständig grünen Testsuite, weil nie ein Test das falsche
Verhalten festgehalten hatte. Eine Suite prüft, wovon sie weiß.
## Kernaussagen
- **Defekt 1, der Mechanismus.** `split_cite_block()` nahm alles von der Überschrift
`## Fußnoten` bis zum Dateiende als Block und behielt daraus nur die Zitatdefinitionszeilen; jeder
Aufrufer setzte die Seite anschließend als `head + gerenderter Block` wieder zusammen. Da
`xref add` seine Abschnitte ans Dateiende hängt, entschied allein die Reihenfolge der beiden
Kommandos, ob eine Seite ihre Querverweise behielt.
- **Der Umfang wurde gemessen, nicht geschätzt:** 8 Seiten mit zusammen 74 Zeilen standen in
der gefährdeten Position, [[Detect-Repair Asymmetry]] mit 14 Zeilen am schlimmsten. Der
laufende zweite Ingest wurde an dieser Stelle angehalten, weil er `cite add` auf Seiten aus
genau dieser Liste aufgerufen hätte.
- **Zwei weitere Befehle waren betroffen, die das Issue nicht genannt hatte.** `rename`
benutzt denselben Codepfad und hätte denselben Inhalt gelöscht. Und eine Fußnotenreferenz, die nur in
einem Abschnitt *hinter* dem Block stand, galt als unreferenziert, worauf
`cite sync` seine Definition als verwaist gelöscht hätte - ein zweiter Verlustpfad mit
derselben Ursache.
- **Der Fix macht die Seite selbstheilend.** Der Block endet jetzt an der nächsten Überschrift
statt am Dateiende, alles dahinter wird auf den Kopf zurückgefaltet, und der gerenderte Block
wird immer zuletzt ausgegeben. Damit bringt die erste Zitatoperation eine verrutschte Seite
von selbst wieder in Ordnung, und `xref add` darf weiter am Dateiende anhängen: der
Widerspruch zwischen beiden Kommandos ist aufgelöst statt umgangen.
- **Loser Text im Block wird gerettet, nicht abgelehnt.** Das dritte Akzeptanzkriterium des
Issues verlangte einen Abbruch. Das wurde mit Begründung abgelehnt: derselbe Codepfad läuft
unter `lint` und `corpus_diff`, wo eine Ausnahme das *Lesen* der Seite verweigern würde,
statt den Befund zu melden.
- **Der Test wurde rot bewiesen, bevor ihm geglaubt wurde.** Statt zu behaupten, der neue Test
hätte den Defekt gefangen, wurde die alte Implementierung rekonstruiert und gegen ihn laufen
gelassen: `ALTER Code -> Beziehungen erhalten: False`, `NEUER Code -> Beziehungen erhalten:
True`.
- **Der Korpus wurde repariert und nachgemessen.** `cite sync --all` normalisierte elf Seiten -
die acht gefährdeten plus drei, die nur neu sortiert werden mussten. Danach: 0 Seiten mit
Inhalt hinter dem Block, bei je Seite unveränderter Zahl an Zitatdefinitionen und Bullets.
Die Zeilendifferenz im Diff kam vom neu umbrochenen `summary:`, nicht von verlorenem Inhalt.
- **Defekt 2, drei Symptome mit einer Ursache.** `xref_link_source` schrieb nur die Zielseiten
und nie die eigenen Arrays der Source-Seite. `types/source.md` deklariert
`page_ref_fields: [entities, concepts]`, das von `xref add` dort geschriebene `related:` war
also undeklariert. Und `strip_frontmatter_ref()` räumte nur deklarierte Felder. Ein Kommando
erzeugte damit einen Zustand, den ein anderes nicht rückgängig machen konnte.
- **Die Feldwahl folgt der Collection, nicht einer Tabelle.** `kb/entities/` bekommt
`entities:`, `kb/concepts/` bekommt `concepts:`; das Verzeichnis *ist* der Feldname. Eine
neue Collection braucht hier deshalb keine Codeänderung, sondern einen Typ, der das passende
Feld deklariert. Eine Typ-zu-Feld-Zuordnung wurde genau deswegen verworfen: sie wäre eine
zweite Kopie dessen, was die Type-Specs bereits sagen.
- **`xref add` prüft beide Seiten, bevor es eine schreibt,** damit eine Ablehnung keine halbe
Verknüpfung hinterlässt; die Meldung nennt die Felder, die der Typ tatsächlich deklariert.
`xref remove` fegt undeklarierte Reste mit Feldnamen aus den Type-Specs und löscht den
Schlüssel ganz, sobald er leer ist - `related: []` würde die Seite weiter an der Validierung
scheitern lassen.
- **Der Beleg, dass die beiden Kommandos Inversen sind:** die referenzierende Concept-Seite kam
byteidentisch aus dem Zyklus zurück, nachdem `xref remove` die Rückreferenz beidseitig
geräumt und `xref link-source` sie exakt wiederhergestellt hatte. Repariert wurde
ausschließlich mit dem Werkzeug, ohne `rm --yes` und ohne Handeditierung von Frontmatter.
- **Die Denylist aus `1.4.0` war richtig, ihr Verweisziel nicht.** Sie lehnte
Seiten-Referenz-Felder mit dem Hinweis ab, `xref add` und `xref remove` seien dafür zuständig -
eine ungeprüfte Behauptung über die Fähigkeiten eines anderen Kommandos, und für genau die
Felder einer Source-Seite falsch. Eine Ablehnung, die auf ein anderes Kommando verweist,
gehört mit einem Test ausgeliefert, der zeigt, dass jenes Kommando den Fall abdeckt.
- **Beide Defekte lebten unter einer vollständig grünen Suite.** 678 Tests waren grün, bevor
die Zitat-Tests geschrieben wurden; 67 Gate-Tests waren grün vor der Zählungsänderung
desselben Tages. In keinem der beiden Fälle hatte je ein Test das falsche Verhalten
festgehalten, und genau so hat es überlebt. Der Befund stützt die Prämisse von Gitea-Issue #8.
- **Ein Bericht aus zweiter Hand wurde nachgestellt statt übernommen.** Die Befunde des
Subagenten wurden am Code nachvollzogen, bevor irgendetwas geändert wurde, und die Prüfung
erweiterte den Umfang zweimal: beim ersten Defekt um `rename` und den `cite sync`-Verlustpfad,
beim zweiten um die Feststellung, dass `xref remove` das undeklarierte Feld gar nicht
erreichen konnte.
- **Beide Befunde wurden als Issues abgelegt, bevor Code angefasst wurde** (#17, #18), nach
`instructions/capture-session.md`: was noch offen ist, gehört in den Tracker und nicht in ein
Transkript oder in jemandes Kopf.
- **Ergebnis:** `1.5.1` als PATCH und `1.6.0` als MINOR, Commits `bb4123b` und `ce03749`, 689
Tests grün in der normalen und in der gehärteten Umgebung (11 neue), 8 Seiten entschärft und
normalisiert, der Schema-Fehler auf `main` repariert, Issues #17 und #18 geschlossen.
## Aufgaben
- [ ] Gitea-Issue #8 - die Prämisse „eine Suite prüft nur, wovon sie weiß" ist mit dieser
Sitzung belegt; das Issue selbst bleibt offen
## Nicht übernommen
- **Die Liste der acht gefährdeten Seiten.** Übernommen sind die Zahl, die Zeilensumme und die
am stärksten betroffene Seite. Die Liste beschreibt einen Zustand, den `cite sync --all` im
selben Lauf beseitigt hat, und wäre ab dem Reparaturcommit falsch.
- **Der Wortlaut der Ablehnungsmeldung von `xref add`.** Übernommen ist die Entwurfsregel
dahinter - beide Seiten prüfen, bevor eine geschrieben wird, und auf das zuständige Kommando
routen -, weil der Wortlaut sich ändern kann und die Regel nicht.
- **Die Einzelheiten der elf neuen Tests.** Übernommen sind die Gesamtzahl 689 und die
Vorgehensweise, den Test gegen die rekonstruierte alte Implementierung rot zu beweisen.
- **Die interne Modul- und Funktionsstruktur** über `split_cite_block()`, `xref_link_source()`
und `strip_frontmatter_ref()` hinaus. Diese drei tragen die Erklärung des Defekts; die
übrigen Aufrufstellen sind Implementierungsdetail und ändern sich.
- **Issues #17 und #18 als eigene Seiten.** Beide sind geschlossen; ihr Ergebnis steht auf
[[wikitool]], [[Command Round-Trip Integrity]] und [[Green Suite Blind Spot]].
## Verwandte Entities
- [[wikitool]]
- [[Chemenu]]
- [[Gitea]]
## Verwandte Concepts
- [[Command Round-Trip Integrity]]
- [[Green Suite Blind Spot]]
- [[Detect-Repair Asymmetry]]
- [[Write-Once Frontmatter Fields]]
- [[Denylist over Allowlist]]
@@ -0,0 +1,144 @@
---
type: types/source.md
source_type: transcript
author: Claude Code (claude-opus-5)
raw_files: ['raw/notes/Conversation Transcript - Versioning, CI-CD and Content Migration Session 2026-08-30.md']
source_language: en
date: 2026-08-30
tags: [versioning, ci-cd, migration, gitea, wikitool, release]
entities: [wikitool, Chemenu, Act Runner, Gitea Actions, Gitea, Gitea MCP Server, Claude Code]
concepts: [KB Stack Versioning, KB Migration, Mass-Update Gate, CI Integration]
summary: Sitzung, die Stack-Versionierung mit CI und Release-Artefakten baut, sie um eine getrennte KB-Versionierung mit Migrationskette ergaenzt und die Gitea-Actions-Pipeline in Betrieb nimmt
---
# Source: Conversation - Versioning CI-CD and Content Migration Session 2026-08-30
**Autor:** Claude Code (claude-opus-5)
**Datum:** 2026-08-30
**Raw-Dateien:** raw/notes/Conversation Transcript - Versioning, CI-CD and Content Migration Session 2026-08-30.md
**Typ:** Notes
## Zusammenfassung
Das Transkript ist eine vom Assistenten am Sitzungsende rekonstruierte Zusammenfassung, kein
wörtliches Protokoll; Befehlsausgaben darin sind echt, Torbens Fragen und Entscheidungen sind
eng wiedergegeben, die Begründungen des Assistenten verdichtet. Die Sitzung lief vom 2026-08-29
bis 2026-08-30 und deckt drei Arbeitspakete ab, die sich als dieselbe Mechanik von verschiedenen
Seiten erwiesen: Versionierung des Stacks mit CI und Release-Artefakten (ausgeliefert als
`0.1.0`, dann `1.0.0`), eine darauf aufsetzende Content-Migrationsstrategie und schließlich das
Inbetriebnehmen der Pipeline. Resultierende Commits: `2508f7a`, `7d63d61`, `c3034ab`, `db03b08`,
`aace3e7`, `401d700`, `b94166b`.
Der erste Entwurf versionierte nur den Stack. Torben verwarf ihn mit der Frage, wo die aktuelle
Version einer KB gespeichert wird und wie eine KB über mehrere Versionen hinweg aktualisiert
wird. Das legte einen Fehler offen: Stack- und Content-Version waren zusammengeworfen, obwohl
eine Instanz Maschinerie `1.4.0` tragen kann, während ihr Inhalt noch in `1.2.0`-Form vorliegt -
genau der Zustand, den jedes Upgrade durchläuft. Der zweite Entwurf trennt drei Fakten in drei
Dateien und baut die Migrationskette als geordnetes Intervall. Er wurde freigegeben und
umgesetzt.
Parallel wurde die Gitea-Actions-Pipeline gegen den Runner auf `ci-runner.example.net` gebracht.
Die Diagnose über den neu verfügbaren Gitea-MCP-Server ergab das Gegenteil der Annahme: Die
Runner hatten die Workflows die ganze Zeit angenommen und scheiterten am Checkout, weil
`actions/checkout` eine JavaScript-Action ist, die act_runner mit `node` im Job-Container
ausführt - und das gepinnte `debian:trixie-slim` bringt keins mit. Der erste Lauf, der bis
`pytest` kam, fand einen echten Fehler in zwei Tests, die auf jeder Entwicklermaschine
monatelang grün gewesen waren.
## Kernaussagen
- **Die Version beschreibt den Stack; der Content hat seine eigene Version.** Drei Fakten, drei
Dateien: `VERSION` (welche Maschinerie installiert ist, geschrieben von `version bump`),
`.wikitool-release.json` (woher sie kam, erzeugt von `dist export`) und `.wikitool-kb.json`
(in welcher Form der Inhalt vorliegt, geschrieben von `migrate done`). Getrennte Dateien, weil
der Release-Stempel erzeugt ist und nie von Hand geändert werden darf, der KB-Zustand dagegen
veränderlicher Instanzzustand ist.
- **Kompatibilität ist die linkeste Nicht-Null-Komponente** - dieselbe Regel, die Cargos
Caret-Ranges verwenden. Sie gilt einheitlich für `0.x` und `1.x`; ab `1.0.0` liest sie sich als
gewöhnliches Semver. Keine Pre-Release-Suffixe, weil eine zweite Ordnungsregel vom Release-Feed,
von der Migrationskette und von der Kompatibilitätsprüfung gleichermaßen befolgt werden müsste.
- **Die Migrationskette ist ein Intervall, keine Fallunterscheidung.** `migrate status` bildet
`(kb_version, VERSION]` aus den Migrationsdokumenten und ordnet aufsteigend; von `1.3.1` nach
`2.0.0` laufen `1.4.0`, `1.7.0`, `2.0.0` nacheinander. Dass keine Migration auf `1.3.x` zielt,
ist kein Sonderfall, sondern schlicht nicht im Intervall. `migrate done` verweigert jede
Version, die nicht das nächste Glied ist - damit ist ein Sprung unmöglich und ein
unterbrochenes mehrstufiges Upgrade fortsetzbar.
- **Zählen, nicht Mengen vergleichen.** `kb_scan.extract_wikilinks()` liefert ein Set. Das ist
richtig für `lint` (löst der Verweis auf?) und falsch für eine Migrationsprüfung (ist einer
verschwunden?). Drei der vier Defekte, die die frühere Übersetzung fand, hatten unveränderte
Link-Mengen und nur veränderte Zählungen.
- **Der Runner nahm die Workflows immer an.** `actions/checkout` ist eine JavaScript-Action, die
act_runner mit `node` **im Job-Container** ausführt; das gepinnte `debian:trixie-slim` hat
keins, daher `exec: "node": executable file not found in $PATH` und `exitcode '127'`. Die
Lösung war eine Zeile in einer apt-Liste: `nodejs` **vor** dem Checkout installieren, plus
`actions/checkout@v7`. `runs-on: linux-docker` blieb, weil die Läufe 46-51 bewiesen, dass das
Label routet und den Container startet.
- **Ein CI-Lauf ist Evidenz, ein lokaler Lauf ist Gewohnheit.** Lauf 52 kam als erster bis
`pytest` und ließ zwei von 630 Tests fallen: `config.default_author()` ruft `git config
user.name` mit `cwd=config.ROOT`, das Fixture-Root ist kein Repository, also antwortete die
globale git-Konfiguration dessen, der die Suite ausführte. Im Container als root gibt es keine.
Behoben in den Tests, nicht durch eine git-Identität für CI: Das hätte den Lauf grün gemacht
und den Fehler stehen gelassen.
- **Das Origin-Repository ist privat, und Gitea antwortet anonym identisch** mit `404` für ein
unsichtbares und für ein nicht existierendes Repository. `curl` beweist damit nichts über den
CI-Zustand; Läufe werden über den Gitea-MCP-Server gelesen. `WIKITOOL_UPDATE_TOKEN` ist
dadurch Voraussetzung statt Ausnahme.
- **`${{ gitea.token }}` genügt für Releases, Tags und Asset-Uploads.** Kein Actions-Secret mit
`write:repository` nötig. Belegt dadurch, dass `release.yml` beim Versionssprung auf `1.0.1`
von selbst feuerte und `llm-wiki-stack-1.0.1.tar.gz` samt `.sha256` hochlud.
- **`paths-ignore` scheitert bewusst offen.** Die Liste steht zweimal statt einmal über einen
YAML-Anker, weil GitHubs Parser Anker ablehnt und Gitea sie nicht dokumentiert akzeptiert; es
gibt keine `!**/CONTRACT.md`-Negation, weil Gitea negierte Filtermuster nicht dokumentiert; und
`kb/CONTRACT.md` ist absichtlich nicht ausgenommen, weil es unter einem Content-Verzeichnis
liegt, aber zum Stack gehört. Alles Unvorhergesehene löst weiterhin CI aus.
- **Die verworfene Methodik lag im git-Verlauf.** Der geschlossene Workshop `translate-kb-de`
wurde aus `de0862f` zurückgeholt und trug eine vollständige Arbeitsweise: Einheiten nach dem
Iterationsbudget geschnitten, Batches getrennt davon nach dem Mass-Update Gate, Frontmatter/H1/
Wikilink-Ziele/Cite-IDs vor allem anderen gegen `HEAD` geprüft, `lint` über jede Einheit
vollständig gelesen, und Zusammenfassungen von der orchestrierenden Sitzung geschrieben statt
von einem Subagenten übernommen.
## Aufgaben
- [ ] Gitea-Issue #7 - `dist upgrade` bauen (in dieser Sitzung bewusst zurückgestellt)
- [ ] Gitea-Issue #8 - Testsuite gegen stille Umgebungsabhängigkeiten härten
- [ ] Gitea-Issue #9 - nächtlichen Drift-Check einrichten
- [ ] Gitea-Issue #10 - Coverage
- [ ] Gitea-Issue #11 - bestätigen, dass Gitea die `paths-ignore`-Muster wie erwartet auswertet;
ausdrücklich als Beobachtung geführt, nicht als Bauaufgabe - der Beleg kommt beim nächsten
reinen Content-Publish von selbst
## Nicht übernommen
- **Die turn-für-turn-Struktur des Transkripts.** Der Verlauf der Sitzung ist Chronologie, keine
dauerhafte Aussage; die Entscheidungen wurden auf die Concept- und Entity-Seiten gehoben, die
Reihenfolge blieb hier.
- **Die Commit-Hashes einzelner Zwischenschritte** (`2508f7a`, `7d63d61`, `db03b08`) über die
Zusammenfassung hinaus. Der git-Verlauf und `CHANGES.md` führen sie bereits; eine zweite Kopie
in `kb/` wäre der driftende Doppeleintrag, den der Stack sonst überall vermeidet.
- **Die Modul- und Dateiliste der Implementierung** (`corpus_diff.py`, `kb_state.py`,
`migrate_cmd.py`) unterhalb dessen, was die Concept-Seiten zum Verständnis brauchen. Die
Codestruktur ist im Repository nachlesbar und veraltet in `kb/` schneller als dort.
- **Die Zahlen der Verifikationsläufe** (248 verglichene Seiten, 2,2 s, 630 Tests, 29 gezählte
Dateien am Mass-Update Gate). Sie belegen einen Stichtag, nicht eine Eigenschaft; nur die
Negativkontrolle `'Docker' 2->1` bei gleichzeitig stillem `lint` wurde übernommen, weil sie die
Aussage trägt, auf der die Strategie ruht.
- **Die Korrektur der Modellzuschreibung** in der Kopfzeile des Transkripts (erste Fassung nannte
„Claude Sonnet 5", das Sitzungslog `claude-opus-5`). Sie betrifft die Quelle selbst und ist
über `author:` bereits festgehalten.
## Verwandte Entities
- [[wikitool]]
- [[Chemenu]]
- [[Act Runner]]
- [[Gitea Actions]]
- [[Gitea]]
- [[Gitea MCP Server]]
- [[Claude Code]]
## Verwandte Concepts
- [[KB Stack Versioning]]
- [[KB Migration]]
- [[Mass-Update Gate]]
- [[CI Integration]]
@@ -0,0 +1,144 @@
---
type: types/source.md
source_type: transcript
author: Claude Code (claude-opus-5)
raw_files: [raw/notes/Conversation Transcript - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md]
source_language: en
date: 2026-08-31
tags: [wikitool, cli, frontmatter, touch, schema, idempotenz, gitea]
entities: [wikitool, Chemenu, Gitea, AGENTS.md]
concepts: [Write-Once Frontmatter Fields, Denylist over Allowlist]
summary: 'Sitzung, die write-once-Frontmatterfelder reparierbar macht: touch bekommt --set/--add/--remove ueber eine Denylist statt einer Allowlist, ein idempotentes --remove und einen bewusst engen Scope (Stack 1.4.0, Gitea-Issue #14)'
---
# Source: Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31
**Autor:** Claude Code (claude-opus-5)
**Datum:** 2026-08-31
**Raw-Dateien:** raw/notes/Conversation Transcript - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md
**Typ:** Notes
## Zusammenfassung
Das Transkript ist eine zusammenfassende Rekonstruktion der Sitzung, kein wörtliches Protokoll.
Die zitierten Befehlsausgaben sind echt, Torbens drei Entwurfsentscheidungen sind samt der ihm
vorgelegten Optionen festgehalten, die Begründungen des Assistenten sind verdichtet. Es ist
eines von zwei Transkripten dieses Sitzungsabschnitts; das zweite behandelt die Zählregel des
Mass-Update Gate und die gemessene Kalibrierung des Iteration Budget und wird getrennt
eingelesen.
Gegenstand ist Gitea-Issue #14, ausgeliefert als `touch --set/--add/--remove` in Stack-Version
`1.4.0` (Commit `dbe2f73`, 9 Dateien, 674 Tests grün). Der Defekt, den es schließt: ein Feld,
das `new` einmal geschrieben hat, war danach nicht mehr erreichbar. `touch` kannte nur die
Felder `modified`, `summary`, `provenance` und `confidence_base`; Handeditierung ist genau das,
was der Stack verhindern soll; Löschen und Neuanlegen zerreißt jede bestehende Referenz auf die
Seite; und `new` ist nicht idempotent, das Zeitfenster für den richtigen Wert war also genau
einen Befehl breit.
Den bleibenden Wert der Sitzung tragen drei Entscheidungen, die Torben mit ausgewiesenen
Trade-offs vorgelegt wurden: Denylist statt Allowlist für die schreibbaren Felder, Ersetzen
plus `--add`/`--remove` für Listenfelder, und ein bewusst enger Auslieferungsschnitt, der
`raw rename` als Issue #16 abspaltet.
## Kernaussagen
- **Die Vorarbeit lag schon im Code.** `validate_fields()` in `touch.py` validiert **pro Feld**
statt pro Dokument - genau die Form, die ein `--set` braucht. Der Grund steht im Docstring:
eine Validierung über das ganze Dokument würde sich weigern, `modified:` auf einer Seite zu
bumpen, die aus einem unbeteiligten Grund ungültig ist, also auf der Seite, die Wartung am
dringendsten braucht.
- **Entscheidung 1 - Denylist statt Allowlist.** Schreibbar ist alles, was das Schema für den
Seitentyp deklariert, abzüglich einer kurzen begründeten Sperrliste. Das Argument, das den
Ausschlag gab: eine gepflegte Allowlist ist eine zweite Kopie des Schemas, und die Kopie ist
die Seite, die driftet - Invariante 8 aus `AGENTS.md`, angewandt auf eine Konstante. Der
Preis der Allowlist wäre gewesen, dass jedes neue Schema-Feld eine Codeänderung braucht.
- **Gesperrt sind vier Gruppen, jede mit dem Befehl benannt, dem das Feld gehört:** `type:`
ändert Schema *und* Verzeichnis der Seite und gehört nach `page-lifecycle.md`; `confidence:`
ist aus `confidence_base` abgeleitet und nicht autorisiert; `related:`, `sources:`,
`entities:` und `concepts:` gehören `xref`, weil ein blanker Frontmatter-Schreibvorgang die
Gegenrichtung und die Body-Bullets stehen ließe.
- **Entscheidung 2 - Ersetzen plus `--add`/`--remove`.** Reines Ersetzen wäre eine Regel
gewesen, hätte aber verlangt, für ein einzelnes Tag die ganze Liste zu nennen. Der Preis der
gewählten Variante sind drei Optionen statt einer.
- **Die Teilfrage, was `--remove` mit einem nicht vorhandenen Element tut, entschied der
Assistent selbst und wies das aus:** es gelingt und wird gemeldet. Idempotent wie
`xref remove`, weil ein Reparaturbefehl, der sich beim zweiten Lauf verweigert, nicht
skriptbar ist - aber nie stillschweigend, weil ein stiller No-op genauso aussieht wie eine
gelungene Entfernung, und genau so verbirgt sich ein vertippter Elementname.
- **Entscheidung 3 - enger Schnitt.** Nur `touch --set`; die Dateiverschiebung bleibt zweistufig
(`git mv`, dann `touch --set raw_files=…`). Die Alternative, `raw rename` mitzuliefern, hätte
Issue #14 vollständig geschlossen und den Zwischenzustand vermieden, zum Preis von `size/M`:
Rückwärtssuche über alle `raw_files:`-Referenzen, Verhalten bei mehreren Besitzern,
Contract-Zeilen für zwei Befehle. `raw rename` wurde Issue #16 (`prio/2`, `size/S`).
- **Zwei Kommandos, eine Implementierung.** `_coerce_set_value`, `_parse_set_fields` und
`_check_raw_files_exist` wanderten aus `new_page.py` nach `commands/_util.py` und verloren
ihren führenden Unterstrich. Ohne das hätte `touch --set` den Komma-Defekt aus Issue #12 am
ersten Tag geerbt; ein Test deckt genau diesen Fall ab, mit einer Rohdatei, deren Name ein
Komma enthält, referenziert über `\,` und als ein Pfad zurückgelesen.
- **Der Existenzcheck für `raw_files:` gilt auch für `touch`,** identisch zu dem, den `new`
ausführt. Er ist I/O und keine Datenform, also kann kein Schema ihn ausdrücken.
- **Die beiden Ablehnungen sind bewusst unterschiedlich formuliert.** Ein gesperrtes Feld ist
ein Routing-Problem, die Meldung nennt deshalb den zuständigen Befehl. Ein unbekanntes Feld
ist ein Tippfehler oder der falsche Seitentyp, die Meldung listet deshalb auf, welche Felder
die Seite tatsächlich hat - der Nutzwert liegt darin, zu erfahren, dass `tags` gemeint war.
- **Eine Falle im Testaufbau, einmal beseitigt.** `test_touch.py` rief den Typer-Callback direkt
mit vollständiger Argumentliste auf; drei neue Optionen brachen sieben Aufrufstellen mit
`TypeError: 'OptionInfo' object is not iterable`, weil ein direkt aufgerufener Callback für
jedes ausgelassene Argument ein `OptionInfo`-Objekt bekommt. Die Tests laufen jetzt über einen
`_touch(**overrides)`-Helper, der jede Option belegt; die nächste Option kostet eine Zeile
statt sieben.
- **Der Beleg am realen Korpus:** [[Diff-Reviewable Agent Edits]] war Stunden zuvor von einem
Ingest angelegt worden, dessen `--set tags=`-Wert ein Komma am Ende trug, worauf alles hinter
dem Trennzeichen verlorenging. Der Subagent hatte alle drei Auswege korrekt geprüft und
verworfen - `touch` konnte `tags:` nicht setzen, Handeditierung kommt Invariante 1 zu nahe,
`rm` plus `new` hätte die `concepts:`-Referenz der Source-Seite zerrissen. Die Seite behielt
`[agent-workflow]` dauerhaft, wegen eines Kommas. Mit `touch --add` trägt sie jetzt
`[agent-workflow, context-engineering, tooling]`.
- **Der zweite Aufruf desselben `--add` meldete "already up to date; nothing to change",** der
`--remove` eines nicht vorhandenen Elements meldete "not present, nothing removed" und endete
ebenfalls erfolgreich - die zugesagte Idempotenz, an der Kommandozeile gezeigt.
- **Dass dies eine Rate und kein Einzelfall war:** drei Fehlschläge in drei aufeinanderfolgenden
Ingests desselben Tages, an zwei verschiedenen Feldern, von drei verschiedenen Agenten. Einer
davon war ein nachgestelltes Komma.
- **Ergebnis:** `1.4.0` als MINOR (neue Fähigkeit, rückwärtskompatibel), Commit `dbe2f73` über
9 Dateien, 674 Tests grün in der normalen und in der gehärteten Umgebung, Issue #14
geschlossen mit den drei Entscheidungen im Protokoll, Issue #16 eröffnet.
## Aufgaben
- [ ] Gitea-Issue #16 - `raw rename`, das `git mv` und jede referenzierende Source-Seite in
einem Schritt erledigt (`prio/2`, `size/S`)
## Nicht übernommen
- **Die Modul- und Funktionsnamen der Testumbauten** über den `_touch`-Helper hinaus. Der
Umbau selbst ist eine dauerhafte Aussage über die Testschnittstelle, die einzelnen sieben
Aufrufstellen sind es nicht.
- **Der vollständige Wortlaut der beiden Fehlermeldungen.** Übernommen ist die Entwurfsregel
dahinter - Routing-Problem nennt den Befehl, Tippfehler nennt die vorhandenen Felder -, weil
der Wortlaut sich ändern kann und die Regel nicht.
- **Das Schwestertranskript desselben Sitzungsabschnitts** (Zählregel des Mass-Update Gate,
gemessene Kalibrierung des Iteration Budget). Es wird getrennt eingelesen und bekommt eine
eigene Source-Seite; hier stünde es unbelegt.
- **Die Einzelheiten der 674 Tests.** Übernommen sind die Gesamtzahl und die Testfalle, die
sich daran zeigte.
- **Issue #14 als eigene Seite.** Es ist geschlossen, und sein Ergebnis steht auf [[wikitool]],
[[Write-Once Frontmatter Fields]] und [[Detect-Repair Asymmetry]].
## Verwandte Entities
- [[wikitool]]
- [[Chemenu]]
- [[Gitea]]
- [[AGENTS.md]]
## Verwandte Concepts
- [[Denylist over Allowlist]]
- [[Detect-Repair Asymmetry]]
- [[Diff-Reviewable Agent Edits]]
## Beziehungen
## Siehe auch
@@ -0,0 +1,109 @@
---
type: types/source.md
source_type: transcript
author: Torben
raw_files: [raw/notes/Conversation Transcript - MCP Read Server Implementation Session 2026-09-02.md]
source_language: de
date: 2026-09-02
tags: []
entities: [wikitool, Chemenu]
concepts: [Publish-Remote Gate, Mass-Update Gate, Iteration and Cost Limits, MCP-Leseserver]
summary: 'Sitzung, die die Sequenz aus Issue #36 umsetzt: Publish-Remote Gate scharf, Lesepfad gehaertet, Root-Aufloesung und Bibliotheksgrenze gezogen, MCP-Leseserver gebaut - vier Versionsstufen 2.2.3 bis 2.4.0, dazu INSTALL-MCP.md und Issue #37.'
---
# Source: MCP Read Server Implementation Session 2026-09-02
**Autor:** Torben
**Datum:** 2026-09-02
**Raw-Dateien:** raw/notes/Conversation Transcript - MCP Read Server Implementation Session 2026-09-02.md
**Typ:** Notes
## Zusammenfassung
Diese Sitzung arbeitet die vierstufige Sequenz aus Issue #36 ab, dem Sammel-Issue für den Weg
zum MCP-Leseserver: #34 (Publish-Remote-Gate scharf stellen), #33 (Lesepfad vor der Exposition
härten), #31 (Root-Auflösung von der Importzeit lösen und eine Bibliotheksgrenze ziehen), #19
(der Leseserver selbst). Jeder Schritt endet mit einem Versions-Bump und einem Testlauf; die
Reihenfolge folgt dem Master-Issue, weil #33 dieselben Dateien anfasst, die #31 strukturell
umbaut, und #31 die Grenze liefert, auf der #19 aufsetzt.
`.wikitool-remotes.json` fehlte in diesem Checkout trotz Dokumentation, die das Gegenteil
behauptete - angelegt und gegen ein erfundenes Ziel gegengeprüft (Exit 42). Der Lesepfad bekam
sechs Fixes gegen einen 267-Byte-YAML-Alias, der zu 672.603 Knoten expandiert, gegen einen
ReDoS-Zweig in der Ranking-Funktion, einen fehlenden Subprozess-Timeout, und einen Korpus-Cache,
der nie einen schmutzigen Arbeitsbaum cacht. `config.ROOT` und alle abgeleiteten Pfade waren zur
Importzeit gebunden; die Auflösung ist jetzt lazy (`CHEMENU_ROOT` → Walk-up), und der reine
Lesekern (`search/service.py`, `lint_core.py`, `types_core.py`) importiert kein `typer` mehr.
Der MCP-Server (`tools/chemenu/mcp/`) exponiert `search`/`types`/`describe_type`/`lint`/`status`
über `chemenu.api.Corpus` - strukturell ohne Schreibpfad, mit Commit-Stempel auf jeder Antwort
und einer Startverweigerung, falls Telemetrie in den bedienten Baum schreiben würde.
Nach Freigabe des 37-Datei-Changesets (Mass-Update-Gate, Token `46442f4419c1`) folgten
`INSTALL-MCP.md` für Menschen, ein Verweis auf die separate Traefik-ForwardAuth-Middleware
(`gitea-mcp-forward-auth`), und Issue #37 für das noch fehlende Container-Image - mit den
konkreten CI-Vorlagen aus `gitea-mcp-forward-auth` (Registry-Push) und `gitea-mcp`
(Dockerfile-Form, aber DockerHub statt der eigenen Registry). Alle vier Sequenz-Issues wurden
geschlossen, #36 blieb offen, weil sein eigenes Abschlusskriterium - ein Konsument, der
nachweislich über die Middleware antwortet - erst mit #37 erfüllbar ist.
## Kernaussagen
- Gemessen: Korpus-Parse 265 ms → 54 ms (`CSafeLoader`), `wikitool search` end-to-end
593 ms → 347 ms; die verbleibenden ~262 ms sind Modulimport und entfallen erst im residenten
MCP-Prozess.
- Der ReDoS-Zweig (`_contains` mit `re.search` gegen nutzergesteuerten Regex) wurde gelöscht,
nicht begrenzt - `rg` wendet das Muster ohnehin mit einer linearen Engine an, bevor die
Funktion je läuft.
- `monkeypatch.setattr(config, "ROOT", ...)` baute nach der lazy-Auflösung die stale Bindung
beim Teardown wieder auf, weil es den *aufgelösten* alten Wert zurückschreibt - `config.reset()`
musste dazukommen, in derselben autouse-Fixture, die das Problem eine Ebene höher (Umgebungsvariablen)
bereits kannte.
- Der MCP-Server hat keinen Schreibpfad, weil `chemenu.api` nichts unter `chemenu.commands`
importiert - nicht, weil eine Liste gefiltert wird. Ein Test importiert das Servermodul in
einem frischen Interpreter und prüft `sys.modules`.
- Ein Stempel-Bug wurde beim Schreiben des Golden-Tests selbst gefunden: `_stamp()` fragte nach
der *aktuellen* statt der beim Laden tatsächlich gelesenen Revision und hätte bei einem
minimal verzögerten zweiten Zugriff `commit: null` auf einem sauberen Baum liefern können.
- `gitea-mcp` ist als Registry-Vorlage ungeeignet - sein Release-Workflow pusht nach DockerHub
(Fork des Upstream), nicht in die eigene Gitea-Registry.
## Aufgaben
- [x] #34, #33, #31, #19 umgesetzt und mit Abschlusskommentar geschlossen
- [x] `INSTALL-MCP.md` geschrieben, in `INSTALL.md`/`README.md` verlinkt, in `dist export` aufgenommen
- [x] Issue #37 (Container-Image) angelegt, mit neun offenen Entscheidungen benannt
- [ ] #37 selbst umsetzen
- [ ] #36 schließen, sobald #37 den Middleware-Nachweis liefert
- [ ] #23 (Env-Var-Erzwingung) - `CHEMENU_ROOT` wurde von Hand in `_WIKITOOL_ENV` eingetragen
- [x] `kb/entities/tools/qmd.md` - falsche Sprachangabe korrigiert (siehe Korrektur unten)
## Korrektur zum Transkript-Kopf
Der Fidelity-Block des Rohtranskripts sagt: "One of two transcripts cut from this session; the
other covers fixing `kb/entities/tools/qmd.md`". Dieses zweite Transkript wurde nie geschrieben
- `raw/` ist unveränderlich, die Korrektur gehört hierher, nicht in die Datei selbst. Tatsächlich
lief die Korrektur ohne eigenes Transkript: direkt gegen `tobi/qmd` auf GitHub geprüft und als
eigene Quelle mit eigenem Raw-Beleg abgelegt (`Source - qmd - GitHub Repository`,
`raw/documents/qmd - GitHub Repository.md`) - eine Quellen-Verifikation statt eines
Gesprächsprotokolls, was für eine Sprachangaben-Korrektur die passendere Belegform ist.
## Nicht übernommen
- Der vollständige Wortlaut der geprüften Docstrings, Kommentare und Testfälle - das Transkript
benennt Dateien und die tragenden Eigenschaften, der Code selbst ist die Quelle.
- Die exakten neun offenen Entscheidungspunkte aus Issue #37 (Korpus im Image vs. Volume,
Basis-Image, Healthcheck etc.) - dort bereits vollständig dokumentiert, hier nicht dupliziert.
- Der Wortlaut der abgerufenen READMEs von `gitea-mcp-forward-auth` und `gitea-mcp` - nur die
für die Entscheidung relevanten Fakten (Config-Variablen, Workflow-Form, Registry-Ziel)
wurden übernommen.
## Verwandte Entities
- [[wikitool]]
- [[Chemenu]]
## Verwandte Concepts
- [[Publish-Remote Gate]]
- [[Mass-Update Gate]]
- [[Iteration and Cost Limits]]
- [[MCP-Leseserver]]
@@ -0,0 +1,83 @@
---
type: types/source.md
source_type: transcript
author: Torben
raw_files: [raw/notes/Conversation Transcript - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md]
source_language: de
date: 2026-09-01
tags: []
entities: [Chemenu, wikitool]
concepts: [Publish-Remote Gate, Delete Rather Than Anonymize]
summary: 'Sitzung, die eine ungeprueft niedergeschriebene Merge-Behauptung in private-instance.md durch einen empirischen Test widerlegt, die Prozedur korrigiert (2.2.1) und Issue #30 mit einem getesteten Skript sowie zwei Architekturvorschlaegen anlegt.'
---
# Source: Private-Instance Merge Correction and Issue 30 Session 2026-09-01
**Autor:** Torben
**Datum:** 2026-09-01
**Raw-Dateien:** raw/notes/Conversation Transcript - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md
**Typ:** Notes
## Zusammenfassung
Torben fragte, was in der privaten Instanz nach dem beschriebenen Schema passiert, wenn Upstream
den Demo-Korpus ändert - eine Frage, die eine am selben Tag geschriebene, aber nie getestete
Behauptung in `instructions/private-instance.md` traf. Statt die bestehende Textstelle zu
verteidigen, wurde sie an einem Wegwerf-Repo-Paar empirisch geprüft: Ein `git merge
upstream/main` löst eine geänderte, gelöschte Demo-Seite **nicht** still auf, sondern erzeugt
einen `modify/delete`-Konflikt und lässt die Upstream-Fassung im Arbeitsbaum liegen; eine neu
angelegte Demo-Seite wird dagegen **stillschweigend** gestaged, ohne Konflikt und ohne Meldung.
Ein zweiter, naheliegender Fix (`.gitattributes` mit `merge=ours` für die Inhaltsverzeichnisse)
wurde ebenfalls getestet und ebenfalls widerlegt - der Treiber wirkt nur bei Inhaltskonflikten
auf beidseitig vorhandenen Dateien, nicht bei modify/delete oder Neuanlage.
Die Instruktion wurde korrigiert (Version 2.2.1): Der Merge wird mit `--no-commit` offengehalten,
die Inhaltsverzeichnisse werden auf den Stand vor dem Merge zurückgezwungen, solange `HEAD` noch
dorthin zeigt, erst dann wird committet - gefolgt von einer Kontrolle
(`git diff --name-only $BEFORE HEAD -- kb raw` muss leer sein), die nicht stillschweigend
übersprungen werden kann. Ein eigenständiges, getestetes Skript wurde daraus abgeleitet und in
Issue #30 hinterlegt, zusammen mit zwei Architekturvorschlägen: das Verfahren als `wikitool`-
Kommando statt als Shell-Rezept, oder - als eigentliche Ursachenbehebung - den Demo-Korpus
grundsätzlich von dem Branch fernzuhalten, von dem private Instanzen ihre Maschinerie ziehen.
Anschließend wurde Issue #3 (Chemenu-Rebranding) gegen seine eigenen Abnahmekriterien geprüft
und für sauber befunden, und eine Verdrahtungslücke geschlossen (`tools/CONTRACT.md` kannte das
Publish-Remote-Gate nicht, `gates.md` verlinkte nicht auf die Prozedur, die Chemenu-Projektseite
beschrieb sich noch als privates Wiki) - veröffentlicht als 2.2.2.
## Kernaussagen
- Eine Behauptung über Git-Merge-Verhalten ist erst nach einem Test eine Tatsache. Am selben Tag
geschrieben zu haben ist kein Beleg für Richtigkeit.
- `git merge` behandelt "eine Datei geändert" und "eine Datei neu angelegt" unterschiedlich: Nur
Ersteres erzeugt einen sichtbaren Konflikt. Eine Prozedur, die nur den Konfliktfall bedenkt,
übersieht die stille Neuanlage.
- `.gitattributes`-Merge-Treiber wie `merge=ours` wirken nur auf Inhaltskonflikte zwischen
beidseitig vorhandenen Dateiversionen, nicht auf modify/delete-Paare oder Neuanlagen.
- Eine Kontrollprüfung, die ein Mensch lesen und verstehen muss, um einen Fehler zu bemerken, ist
schwächer als eine, die bei einem Fehler selbst nicht-null zurückgibt.
- Wiederkehrende Symptome bei jeder Downstream-Instanz sind oft ein Zeichen, dass die eigentliche
Ursache stromaufwärts liegt und dort einmalig behoben werden sollte.
## Aufgaben
- [x] `private-instance.md` korrigiert und als 2.2.1 veröffentlicht
- [x] Issue #30 angelegt (Skript + zwei Architekturvorschläge, hängt an #28)
- [x] Issue #3 gegen Abnahmekriterien geprüft, sauber
- [ ] Issue #30 selbst ist offen - siehe dort für den Entscheidungsstand
## Nicht übernommen
- Die im Transkript vollständig gezeigten Testskript-Läufe (Shell-Ausgabe der Wegwerf-Repos)
sind hier nicht wiederholt - die Kernaussage (welches Verhalten gemessen wurde) ist auf die
Concept-Seite [[Publish-Remote Gate]] und in Issue #30 übernommen, der Beleg bleibt im
Transkript.
## Verwandte Entities
- [[Chemenu]]
- [[wikitool]]
## Verwandte Concepts
- [[Publish-Remote Gate]]
- [[Delete Rather Than Anonymize]]
@@ -0,0 +1,87 @@
---
type: types/source.md
source_type: transcript
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,71 @@
---
type: types/source.md
source_type: transcript
author: Torben
raw_files: [raw/notes/Conversation Transcript - Publish-Remote Gate and Issue Triage Session 2026-09-01.md]
source_language: de
date: 2026-09-01
tags: []
entities: [Chemenu, wikitool]
concepts: [Publish-Remote Gate, Mass-Update Gate, Issue Label Scheme]
summary: Sitzung, die ein drittes, Token-loses Gate fuer publish baut, instructions/private-instance.md schreibt, sechs Gitea-Issues auf den Rename und die neue Architektur nachzieht und die Actions-Run-Historie entfernen laesst.
---
# Source: Publish-Remote Gate and Issue Triage Session 2026-09-01
**Autor:** Torben
**Datum:** 2026-09-01
**Raw-Dateien:** raw/notes/Conversation Transcript - Publish-Remote Gate and Issue Triage Session 2026-09-01.md
**Typ:** Notes
## Zusammenfassung
Direkte Fortsetzung der Veröffentlichungssitzung: Torben bat um eine Remote-Allowlist für
`publish`, eine Bitte, vor dem Öffentlich-Schalten von Gitea zu warten und einen Spickzettel
dafür, und ein Kurz-Howto für die lokale Dev-Umgebung - dazu, nach eigenem Ermessen, Issues zu
pflegen. Gebaut wurde das **Publish-Remote-Gate**: Es prüft die aufgelöste Push-URL (nicht den
Remote-Namen, weil ein umgebogener `origin` sonst durchrutschen würde) gegen eine optionale,
gitignorete Allowlist-Datei und hat als einziges der drei Gates keinen Freigabe-Token - der Weg
daran vorbei ist ein bewusster Edit der Datei durch den Menschen. `instructions/private-instance.md`
beschreibt seither das Clone-mit-Upstream-Setup, mit dem Gate als Schritt vor dem ersten `publish`.
Sechs offene Issues wurden auf den Chemenu-Rename hin durchgesehen; mehrere trugen noch den
alten Paketpfad. Drei neue Issues entstanden aus Punkten, die im Tagesverlauf entschieden und
dann zurückgestellt worden waren (Handbuch-Vorbedingung, Demo-vs-Testbett-Konflikt, veraltete
Issue-Texte). Nach dem Öffentlich-Schalten wurde anonym end-to-end geprüft (Klon, Release-Feed,
Distributionsweg), `INSTALL.md` von "Repo ist privat" auf den öffentlichen Zustand umgestellt,
und auf Bitte des Nutzers die Gitea-Actions-Run-Historie über die REST-API entfernt, nachdem
sich herausstellte, dass weder das MCP-Werkzeug noch eine sichtbare UI-Schaltfläche das können.
## Kernaussagen
- Ein Allowlist-Gate muss die **aufgelöste Push-URL** prüfen, nicht den Remote-Namen - sonst
schützt es nicht vor einem umbenannten oder umgebogenen Remote.
- Ein Gate, dessen Frage eine stehende Eigenschaft des Checkouts ist (nicht ein einzelnes
Changeset), braucht keinen Freigabe-Token - der Mensch löst es durch einen bewussten
Datei-Edit, nie ein Agent durch einen Bypass.
- Ein Werkzeugvertrag (`tools/CONTRACT.md`) muss jeden Fehlerfall eines Kommandos nennen; ein
neuer Exit-42-Pfad, der dort fehlt, ist eine Lücke, die kein automatischer Check findet.
- Ein MCP-Server kann weniger können als die zugrunde liegende API - hier: Actions-Runs
anzeigen/erneut starten, aber nicht löschen, obwohl die REST-API die Route hat.
## Aufgaben
- [x] Publish-Remote-Gate, `private-instance.md`, Issue-Pflege in dieser Sitzung erledigt
- [ ] #4, #5 tragen laut #29 noch veraltete Pfade und sind noch nicht nachgezogen
## Nicht übernommen
- Der vollständige Wortlaut des Gitea-Spickzettels ist nicht auf diese Seite übernommen - er
steht im Transkript und in der Chat-Antwort an den Nutzer, ist aber keine dauerhafte
Wiki-Aussage, sondern eine einmalige Handlungsanweisung.
## Verwandte Entities
- [[Chemenu]]
- [[wikitool]]
## Verwandte Concepts
- [[Publish-Remote Gate]]
- [[Mass-Update Gate]]
- [[Issue Label Scheme]]
@@ -0,0 +1,75 @@
---
type: types/source.md
source_type: transcript
author: Torben Nehmer
raw_files: [raw/notes/Conversation Transcript - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02.md]
source_language: de
date: 2026-09-02
tags: []
entities: [wikitool, Chemenu]
concepts: [KB Stack Versioning]
summary: Sitzung, die die Versionsstelle als Kompatibilitaets- statt Migrationsfrage praezisiert und einen Freigabe-Ablauf fuer Breaking Changes in stack-dev einfuehrt
---
# Source: Version Part Nomenclature and Breaking Change Gate Session 2026-09-02
**Autor:** Torben Nehmer
**Datum:** 2026-09-02
**Raw-Dateien:** raw/notes/Conversation Transcript - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02.md
**Typ:** Notes
## Zusammenfassung
Umsetzung von Gitea-Issue #26: Die Doku des Stacks führte für die Wahl der Versionsstelle zwei
Fragen zusammen, die nicht dieselbe sind - ob der Korpus migriert werden muss, und ob der
Wechsel ein Drop-in-Ersatz ist. Nur `version bump --help` unterschied korrekt; die drei
prosaischen Stellen (`stack-dev`, `version.py`-Docstring, `INSTALL.md`) beschrieben MAJOR als
Migrationsfrage. Der `2.0.0`-Rebranding-Bump hatte genau daran zuerst `1.9.0` statt `--major`
angesetzt.
Der Nutzer schärfte die Regel während der Sitzung zu einem konkreten zweiseitigen Test nach:
"die neue version ist kein drop-in replacement. Sobald irgendwie Hand angelegt werden muss, sei
es durch den user oder durch ein Migrationsscript, ist es ein major version change. selbiges
gilt, wenn ein update nicht rückgängig gemacht werden kann [...] in allen Fällen muss bei einem
Major version change ein 'Breaking Change' vermerkt werden. breaking changes sind damit teuer.
passe stack-dev so an, dass in diesen Fällen zwingend der user informiert, Alternativen
aufgezeigt und eine freigabe eingeholt wird." Zwei Auswahlentscheidungen davor: Durchsetzung im
Code statt reiner Prosa (weil Prosa bereits einmal gedriftet war), und die Freigabe als
"Decision point" statt als Gate-Sprache, um die drei echten code-erzwungenen Gates nicht zu
verwässern.
## Kernaussagen
- Kompatibilität (Drop-in-Ersatz, vorwärts wie rückwärts) und Inhaltsmigration sind zwei
unabhängige Fragen; MAJOR beantwortet die erste, `--no-migration`/ein Migrationsdokument die
zweite.
- Ein Grenzübertritt kann `kb/` völlig unangetastet lassen und trotzdem MAJOR sein - Katalog:
Update-Pfad, Release-Artefaktname, Paket-Import-Name, ein umbenanntes Kommando/Flag/Envvar,
die Shape einer maschinengelesenen Datei.
- Ein Breaking Change ist teuer (jede bestehende Instanz zahlt einmal, von Hand) und deshalb
genehmigungspflichtig: Bruch, Handarbeit je Instanz und Alternativen (Shim, aufschieben und
bündeln, aufspalten mit Deprecation-Fenster) vorlegen, dann Freigabe abwarten.
- Reine Prosa-Regeln drifted - deshalb wurde `--breaking` als Pflichtflag samt zweiter, von der
Migrationsprüfung unabhängiger `docs verify`-Prüfung eingeführt, nicht nur eine Textänderung.
## Aufgaben
Keine offenen Aufgaben aus dieser Sitzung - Issue #26 wurde in derselben Sitzung geschlossen,
mit Verweis auf Commit `31662dc` (`2.5.0`).
## Nicht übernommen
- Die vollständige Katalog-Tabelle und der `2.0.0`-Fallbeispiel-Text aus
`instructions/dev/version-parts.md` werden hier nicht wiederholt - die Datei ist die
autoritative Quelle (Instruktions-Layer, `manual`-artig durch die `instructions/dev/`-Grenze),
diese Source-Seite fasst nur zusammen, was zur Entscheidung führte.
- Der genaue Wortlaut der Tool-Fehlermeldungen (`version bump`-Refusals) steht im Transkript
selbst; hier nur die Regel dahinter.
## Verwandte Entities
- [[wikitool]]
- [[Chemenu]]
## Verwandte Concepts
- [[KB Stack Versioning]]