kb/concepts/ bekommt Areas: layout: fuer concept, Area-Titel aus jedem Type-Spec, Schwellen-Empfehlung im lint (schliesst #59)
CI / verify (push) Successful in 52s
Release / release (push) Successful in 36s

Files changed:
- CHANGES.md
- README.md
- VERSION
- kb/concepts/Ambient Environment Dependency.md
- kb/concepts/Anti-Cramming Heuristic.md
- kb/concepts/Audit Trail.md
- kb/concepts/BM25.md
- kb/concepts/Bulk Operations.md
- kb/concepts/CI Integration.md
- kb/concepts/COLLECTION.md
- kb/concepts/CPPC.md
- kb/concepts/Checkpoint Audit.md
- kb/concepts/Claude Code Auto Mode.md
- kb/concepts/Command Round-Trip Integrity.md
- kb/concepts/Confidence Scoring.md
- kb/concepts/Consolidation Tiers.md
- kb/concepts/Content Quality Control.md
- kb/concepts/Context Isolation.md
- kb/concepts/Contradiction Resolution.md
- kb/concepts/Cross-platform Agent Skills.md
- kb/concepts/Crystallization.md
- kb/concepts/Delete Rather Than Anonymize.md
- kb/concepts/Denylist over Allowlist.md
- kb/concepts/Detect-Repair Asymmetry.md
- kb/concepts/Diff-Reviewable Agent Edits.md
- kb/concepts/Dual Licensing by File Plan.md
- kb/concepts/Entity Extraction.md
- kb/concepts/Episodic Memory.md
- kb/concepts/Event-Driven Automation.md
- kb/concepts/Filter on Ingest.md
- kb/concepts/Forgetting.md
- kb/concepts/Graph Traversal.md
- kb/concepts/Green Suite Blind Spot.md
- kb/concepts/Hooks.md
- kb/concepts/Hybrid Search.md
- kb/concepts/INDEX.md
- kb/concepts/Implementation Spectrum.md
- kb/concepts/Index Scaling.md
- kb/concepts/Issue Label Scheme.md
- kb/concepts/Iteration and Cost Limits.md
- kb/concepts/KB Migration.md
- kb/concepts/KB Stack Versioning.md
- kb/concepts/Knowledge Compounding.md
- kb/concepts/Knowledge Graph.md
- kb/concepts/LLM Wiki Pattern.md
- kb/concepts/Lint Workflow.md
- kb/concepts/MCP-Leseserver.md
- kb/concepts/Mass-Update Gate.md
- kb/concepts/Memory Lifecycle.md
- kb/concepts/Mesh Sync.md
- kb/concepts/Modbus.md
- kb/concepts/Multi-Agent Collaboration.md
- kb/concepts/Naming Convention Conflict.md
- kb/concepts/OKF Compatibility.md
- kb/concepts/Optional Instance Context File.md
- kb/concepts/Personalization Plane.md
- kb/concepts/Privacy and Governance.md
- kb/concepts/Procedural Memory.md
- kb/concepts/Publish-Remote Gate.md
- kb/concepts/Quality Scoring.md
- kb/concepts/Quality and Self-Correction.md
- kb/concepts/RAG.md
- kb/concepts/Reciprocal Rank Fusion.md
- kb/concepts/SSD TRIM.md
- kb/concepts/Scale Ceiling.md
- kb/concepts/Self-Healing.md
- kb/concepts/Semantic Lint Automation.md
- kb/concepts/Semantic Memory.md
- kb/concepts/Session Orientation.md
- kb/concepts/Shared vs Private.md
- kb/concepts/Split Merge Reclassify.md
- kb/concepts/Split Threshold.md
- kb/concepts/Structural Enforcement over Documented Rule.md
- kb/concepts/Stub Threshold.md
- kb/concepts/Supersession.md
- kb/concepts/Three-Layer Architecture.md
- kb/concepts/Token Economics.md
- kb/concepts/Typed Relationships.md
- kb/concepts/User Management.md
- kb/concepts/Vector Search.md
- kb/concepts/Work Coordination.md
- kb/concepts/Workflow Extraction.md
- kb/concepts/Workflow Orchestration.md
- kb/concepts/Working Memory.md
- kb/concepts/Write-Once Frontmatter Fields.md
- kb/concepts/architectures/Consolidation Tiers.md
- kb/concepts/architectures/Context Isolation.md
- kb/concepts/architectures/Cross-platform Agent Skills.md
- kb/concepts/architectures/Episodic Memory.md
- kb/concepts/architectures/Hybrid Search.md
- kb/concepts/architectures/Implementation Spectrum.md
- kb/concepts/architectures/Knowledge Graph.md
- kb/concepts/architectures/LLM Wiki Pattern.md
- kb/concepts/architectures/MCP-Leseserver.md
- kb/concepts/architectures/Memory Lifecycle.md
- kb/concepts/architectures/OKF Compatibility.md
- kb/concepts/architectures/Optional Instance Context File.md
- kb/concepts/architectures/Personalization Plane.md
- kb/concepts/architectures/Procedural Memory.md
- kb/concepts/architectures/RAG.md
- kb/concepts/architectures/Scale Ceiling.md
- kb/concepts/architectures/Semantic Memory.md
- kb/concepts/architectures/Three-Layer Architecture.md
- kb/concepts/architectures/Token Economics.md
- kb/concepts/architectures/Working Memory.md
- kb/concepts/decisions/Delete Rather Than Anonymize.md
- kb/concepts/decisions/Denylist over Allowlist.md
- kb/concepts/decisions/Diff-Reviewable Agent Edits.md
- kb/concepts/decisions/Dual Licensing by File Plan.md
- kb/concepts/decisions/Issue Label Scheme.md
- kb/concepts/decisions/KB Stack Versioning.md
- kb/concepts/decisions/Structural Enforcement over Documented Rule.md
- kb/concepts/patterns/Audit Trail.md
- kb/concepts/patterns/BM25.md
- kb/concepts/patterns/Command Round-Trip Integrity.md
- kb/concepts/patterns/Confidence Scoring.md
- kb/concepts/patterns/Contradiction Resolution.md
- kb/concepts/patterns/Entity Extraction.md
- kb/concepts/patterns/Filter on Ingest.md
- kb/concepts/patterns/Forgetting.md
- kb/concepts/patterns/Graph Traversal.md
- kb/concepts/patterns/Mesh Sync.md
- kb/concepts/patterns/Quality Scoring.md
- kb/concepts/patterns/Reciprocal Rank Fusion.md
- kb/concepts/patterns/Self-Healing.md
- kb/concepts/patterns/Shared vs Private.md
- kb/concepts/patterns/Typed Relationships.md
- kb/concepts/patterns/Vector Search.md
- kb/concepts/patterns/Work Coordination.md
- kb/concepts/problems/Ambient Environment Dependency.md
- kb/concepts/problems/Detect-Repair Asymmetry.md
- kb/concepts/problems/Green Suite Blind Spot.md
- kb/concepts/problems/Naming Convention Conflict.md
- kb/concepts/problems/Write-Once Frontmatter Fields.md
- kb/concepts/protocols/CPPC.md
- kb/concepts/protocols/Modbus.md
- kb/concepts/protocols/SSD TRIM.md
- kb/concepts/workflows/Anti-Cramming Heuristic.md
- kb/concepts/workflows/Bulk Operations.md
- kb/concepts/workflows/CI Integration.md
- kb/concepts/workflows/Checkpoint Audit.md
- kb/concepts/workflows/Claude Code Auto Mode.md
- kb/concepts/workflows/Content Quality Control.md
- kb/concepts/workflows/Crystallization.md
- kb/concepts/workflows/Event-Driven Automation.md
- kb/concepts/workflows/Hooks.md
- kb/concepts/workflows/Index Scaling.md
- kb/concepts/workflows/Iteration and Cost Limits.md
- kb/concepts/workflows/KB Migration.md
- kb/concepts/workflows/Knowledge Compounding.md
- kb/concepts/workflows/Lint Workflow.md
- kb/concepts/workflows/Mass-Update Gate.md
- kb/concepts/workflows/Multi-Agent Collaboration.md
- kb/concepts/workflows/Privacy and Governance.md
- kb/concepts/workflows/Publish-Remote Gate.md
- kb/concepts/workflows/Quality and Self-Correction.md
- kb/concepts/workflows/Semantic Lint Automation.md
- kb/concepts/workflows/Session Orientation.md
- kb/concepts/workflows/Split Merge Reclassify.md
- kb/concepts/workflows/Split Threshold.md
- kb/concepts/workflows/Stub Threshold.md
- kb/concepts/workflows/Supersession.md
- kb/concepts/workflows/User Management.md
- kb/concepts/workflows/Workflow Extraction.md
- kb/concepts/workflows/Workflow Orchestration.md
- kb/index.md
- kb/log.md
- tools/CONTRACT.md
- tools/README.md
- tools/chemenu/catalog.py
- tools/chemenu/commands/index_build.py
- tools/chemenu/lint_core.py
- tools/chemenu/tests/conftest.py
- tools/chemenu/tests/test_cite_cmd.py
- tools/chemenu/tests/test_git_publish.py
- tools/chemenu/tests/test_index_build.py
- tools/chemenu/tests/test_lint.py
- tools/chemenu/tests/test_new_page.py
- tools/chemenu/tests/test_provenance.py
- tools/chemenu/tests/test_type_resolver.py
- tools/chemenu/tests/test_xref.py
- types/concept.md
- types/type-spec.md
This commit is contained in:
2026-09-08 10:07:46 +02:00
parent 63b4bb82d9
commit 7f74303a00
103 changed files with 703 additions and 180 deletions
@@ -0,0 +1,76 @@
---
type: types/concept.md
concept_type: decision
tags: []
created: 2026-09-01
modified: 2026-09-01
related:
- operates-on: Chemenu
sources: ['Source - Public Release, Corpus Purge and History Squash Session 2026-09-01', Source - Private-Instance Merge Correction and Issue 30 Session 2026-09-01]
confidence: 0.70
confidence_base: 0.70
provenance: sourced
summary: 'Private Korpusinhalte per Loeschung entfernen statt zu anonymisieren: ein Seitentitel ist der einzige Identifier eines Wikis, Umbenennen ist die volle page-lifecycle-Prozedur je Seite, Loeschen ist ein unterstuetztes Kommando.'
---
# Delete Rather Than Anonymize
**Typ:** Decision
## Definition
Wenn private oder sensible Inhalte aus einem Wiki entfernt werden müssen, ist Löschen einer
zugehörigen Seite in der Regel dem Anonymisieren (Umbenennen, Ersetzen sensibler Details bei
sonst unverändertem Inhalt) vorzuziehen - wenn ein unterstütztes Löschkommando existiert.
## Kernpunkte
- Ein Seitentitel ist in einem verlinkten Wiki oft der **einzige Identifier** einer Seite: Er
lebt in Wikilinks, Zitatmarkern und Frontmatter-Arrays jeder referenzierenden Seite. Ihn zu
ändern (Anonymisieren durch Umbenennen) verlangt deshalb eine vollständige Rename-Prozedur pro
betroffener Seite - bei mehreren zusammenhängenden Seiten multipliziert sich der Aufwand.
- Löschen dagegen ist ein einzelner, unterstützter Vorgang, der eine Seite mechanisch aus dem
Rest des Wikis de-linkt (bekannte Referenzarten: Frontmatter-Felder, ganzzeilige
Verweis-Aufzählungen). Er ist damit für strukturelle Bereinigung **schneller und weniger
fehleranfällig** als Anonymisierung.
- Bei Inhalten, die eine reale Topologie beschreiben (z. B. eine Infrastrukturdokumentation),
entschärft Anonymisieren einzelner Bezeichner (Hostnamen, IP-Adressen) die eigentliche
Preisgabe nicht: Die Struktur - welche Systeme wie zusammenhängen - bleibt erhalten, auch wenn
die Namen ausgetauscht sind.
- **Grenze der Methode:** Ein mechanisches Löschkommando entfernt typischerweise nur
strukturelle Referenzen (Frontmatter, Aufzählungen), nicht zwingend Erwähnungen im Fließtext
einer anderen Seite. Nach der Löschung ist eine gezielte Nachkontrolle nötig, ob der entfernte
Name noch im Klartext irgendwo im Wiki steht.
## Wann zu verwenden
- Der zu entfernende Inhalt ist als eigenständige Seite oder eigenständige Seitengruppe
abgrenzbar.
- Ein Löschkommando existiert, das Referenzen mechanisch bereinigt (nicht ein bloßes Entfernen
der Datei, das tote Links hinterlässt).
- Der Inhalt beschreibt eine reale, zusammenhängende Struktur (Infrastruktur, ein Netzwerk, eine
Organisation), bei der einzelne Bezeichner austauschen die eigentliche Preisgabe nicht behebt.
## Wann NICHT zu verwenden
- Wenn nur ein einzelner sensibler Wert innerhalb einer sonst wertvollen, generischen Seite
steht (z. B. ein Firmenname als Beispiel in einer sonst allgemeingültigen Anleitung) - dort ist
gezieltes Redigieren der Seite treffender als sie komplett zu verwerfen.
- Wenn die Seite Beziehungen trägt, die für sich genommen wertvoll und nicht sensibel sind - dann
kann eine Neufassung mit generischem Beispiel sinnvoller sein als Löschung.
## Verwandte Concepts
- [[Mass-Update Gate]]
## Beziehungen
## Siehe auch
- [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]]
- [[Source - Private-Instance Merge Correction and Issue 30 Session 2026-09-01]]
<!-- wikitool:links -->
## Beziehungen
- **operates-on:** [[Chemenu]]
<!-- /wikitool:links -->
@@ -0,0 +1,105 @@
---
type: types/concept.md
concept_type: decision
tags: [schema, tooling, cli, design-rule]
created: 2026-08-31
modified: 2026-08-31
related:
- mechanism: wikitool
- grounds: Write-Once Frontmatter Fields
- see-also: Green Suite Blind Spot
sources: [Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31, Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31]
confidence: 0.70
confidence_base: 0.70
provenance: sourced
summary: Entscheidung, schreibbare Felder als Schema minus kurzer Sperrliste zu bestimmen statt als gepflegte Positivliste, weil die Positivliste eine zweite Kopie des Schemas waere
---
# Denylist over Allowlist
**Typ:** Decision
## Definition
Wenn ein Befehl entscheiden muss, welche Felder er schreiben darf, wird die Menge als **Schema
minus kurzer Sperrliste** bestimmt, nicht als gepflegte Positivliste. Die Sperrliste nennt zu
jedem Eintrag den Befehl, dem das Feld stattdessen gehört.
## Kontext
`touch --set` brauchte eine Antwort auf die Frage, welche Frontmatter-Felder es schreiben darf.
Torben wurden drei Varianten mit ihren Folgen vorgelegt: Denylist, Allowlist, und eine Denylist,
die zusätzlich die Felder sperrt, für die es bereits eigene Optionen gibt
(`summary`, `provenance`, `confidence_base`)[^s-conversation-write-once-frontmatter-fields-and-touch-set-session-2026-08-31].
## Entscheidung
Denylist. 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 im
Code[^s-conversation-write-once-frontmatter-fields-and-touch-set-session-2026-08-31].
Gesperrt sind in [[wikitool]] vier Gruppen, jede mit einer Zuständigkeit als Begründung:
- `type:` - ändert Schema *und* Verzeichnis der Seite; das ist der Seiten-Lebenszyklus, kein
Feldschreibvorgang.
- `confidence:` - aus `confidence_base` durch Decay abgeleitet, nicht autorisiert.
- `related:`, `sources:`, `entities:`, `concepts:` - gehören `xref`, das auch die Gegenrichtung
und die Body-Bullets pflegt; ein blanker Frontmatter-Schreibvorgang ließe die andere Hälfte
stehen.
Die dritte Variante - zusätzlich `summary`, `provenance` und `confidence_base` zu sperren, damit
es für eine Sache nur einen Weg gibt - wurde nicht gewählt: die Ersparnis wäre eine
Verweigerung, die für den Nutzer überraschend
aussieht[^s-conversation-write-once-frontmatter-fields-and-touch-set-session-2026-08-31].
## Konsequenzen
- **Ein neues Schema-Feld ist sofort schreibbar,** ohne Codeänderung. Das ist der Zweck der
Entscheidung und zugleich ihr Risiko: ein Feld, das eigentlich einen eigenen Befehl bräuchte,
wird schreibbar ausgeliefert, wenn niemand daran denkt, es zu sperren.
- **Die Sperrliste muss ihre Gründe mitführen.** Jeder Eintrag nennt den zuständigen Befehl,
weil die Ablehnung sonst nur "nein" sagt statt zu routen. Eine gesperrte Zuständigkeit ist
ein Routing-Problem; ein unbekanntes Feld dagegen ist ein Tippfehler, und die Meldung listet
dort auf, welche Felder die Seite tatsächlich hat.
- **Der Verweis in einer Ablehnung ist eine Behauptung über ein anderes Kommando.** Die
Sperrliste aus `1.4.0` lehnte die Seiten-Referenz-Felder mit dem Hinweis auf `xref add` und
`xref remove` ab. Die Sperre war richtig, das Verweisziel nicht: für die `entities:` und
`concepts:` einer Source-Seite konnte `xref add` gar nicht schreiben, und was es dort
schrieb, bekam `xref remove` nicht wieder weg. Eine Ablehnung, die weiterroutet, gehört
deshalb mit einem Test ausgeliefert, der zeigt, dass das genannte Kommando den Fall
abdeckt - andernfalls schickt sie den Aufrufer in eine Sackgasse und sieht dabei aus wie
Hilfe. Behoben mit `1.6.0` (Gitea-Issue #18), nicht durch eine Änderung an der
Sperrliste[^s-conversation-two-round-trip-defects-found-by-an-ingest-session-2026-08-31]
- **Der Ansatz überträgt sich auf jeden schemagetriebenen Befehl,** nicht nur auf `touch`. Wo
eine Positivliste dieselbe Information ein zweites Mal aufschreiben würde, ist die Sperrliste
die kleinere Kopie.
- **Er ist kein Sicherheitsmuster.** Für eine Vertrauensgrenze gilt fail-closed, also die
Allowlist. Diese Entscheidung betrifft eine Zuständigkeitsverteilung innerhalb eines
Werkzeugs, das ohnehin alle Felder schreiben kann.
## Status
Angenommen (2026-08-31) mit Stack-Version `1.4.0`, Commit
`dbe2f73`[^s-conversation-write-once-frontmatter-fields-and-touch-set-session-2026-08-31].
## Verwandte Concepts
## Beziehungen
## Siehe auch
- [[Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31]]
- [[Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31]]
## Fußnoten
[^s-conversation-write-once-frontmatter-fields-and-touch-set-session-2026-08-31]: [[Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31]]
[^s-conversation-two-round-trip-defects-found-by-an-ingest-session-2026-08-31]: [[Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31]]
<!-- wikitool:links -->
## Beziehungen
- **mechanism:** [[wikitool]]
- **grounds:** [[Write-Once Frontmatter Fields]]
- **see-also:** [[Green Suite Blind Spot]]
<!-- /wikitool:links -->
@@ -0,0 +1,95 @@
---
type: types/concept.md
concept_type: decision
tags: [agent-workflow, context-engineering, tooling]
created: 2026-08-31
modified: 2026-08-31
related:
- see-also: Claude Code Auto Mode
- operates-on: Claude Code
- derived-from: Write-Once Frontmatter Fields
sources: [Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31]
confidence: 0.70
confidence_base: 0.70
provenance: sourced
summary: Entscheidung, Dateiaenderungen ueber Edit/Write statt ueber Shell-Heredocs zu fahren, weil nur das erste eine pruefbare Diff hinterlaesst
---
# Diff-Reviewable Agent Edits
**Typ:** Decision
## Definition
Ein Agent ändert Dateien über die dedizierten Werkzeuge `Edit` und `Write`, nicht über
Shell-Konstrukte wie `sed -i`, Heredocs oder eingebettete Skripte. Die Shell bleibt für alles
zuständig, was keine Datei umschreibt: `git`, `pytest`, [[wikitool]], `grep`, `find`, und Lesen
mit `cat` oder `sed -n`.
## Kontext
Der aktive Berechtigungsmodus [[Claude Code Auto Mode]] injiziert eine Anweisung in die Sitzung,
die genau das Gegenteil verlangt: Arbeit möglichst über das Bash-Werkzeug erledigen und auf ein
dediziertes Werkzeug erst zurückfallen, wenn Bash die Aufgabe nicht bewältigt. 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[^s-conversation-auto-mode-and-tool-choice-session-2026-08-31]. Torben hat das
abgestellt:
*"Warum verwendest du seit neuestem immer die Shell um Dateien zu editieren anstelle der file
edit Tools? Das macht die Session schwer nachvollziehbar."*
## Entscheidung
`Edit`/`Write` für Dateiänderungen, Bash für Prozesse. Die Regel wurde in das dauerhafte
Gedächtnis des Assistenten geschrieben, damit sie die Sitzung
überdauert[^s-conversation-auto-mode-and-tool-choice-session-2026-08-31].
Zwei Gründe tragen sie, und der zweite ist der belastbarere:
1. **Die ausdrückliche Anweisung des Nutzers rangiert über einer Modus-Voreinstellung.**
2. **Die Anweisung des Modus schlägt sich selbst.** Ihr Qualifikator lautet *"wherever it can
accomplish the job"*. Ein `s.replace(old, new)` in einem Heredoc zeigt dem Leser zwei
String-Literale und keine Änderungsansicht: was vorher in der Datei stand und was jetzt darin
steht, ist nicht sichtbar. Ein Edit, dessen Diff niemand prüfen kann, erfüllt die Aufgabe
nicht - also greift der Vorrang der Shell an dieser Stelle gar nicht erst.
## Konsequenzen
- Die Grenze verläuft zwischen **Lesen** und **Schreiben**, nicht zwischen Shell und Werkzeug.
`cat`, `head`, `sed -n`, `grep` und `find` bleiben unverändert zulässig.
- Sie verläuft nicht bei jeder Änderung gleich scharf: bei einem einzeiligen `sed` ist der
Unterschied unerheblich, beim Mehrblock-Umbau eines Compiler-Moduls nicht. Die Regel wird
trotzdem einheitlich angewandt, weil die Einschätzung "das ist klein genug" genau die ist, die
im Zweifelsfall zugunsten der Bequemlichkeit ausfällt.
- Der Modus lässt sich nicht so einstellen, dass nur diese Präferenz entfällt; es wurde keine
solche Einstellung
gefunden[^s-conversation-auto-mode-and-tool-choice-session-2026-08-31]. Die Regel muss also
als Verhaltensregel getragen werden, nicht als Konfiguration.
- In diesem Repository fällt die Entscheidung mit den Interessen des Stacks zusammen: was
`wikitool` erzeugt, wird ohnehin nie von Hand geschrieben, und was von Hand geschrieben wird,
soll im Publish-Diff nachlesbar sein.
## Status
Angenommen (2026-08-31), auf Anweisung des Nutzers, für Sitzungen an diesem Repository.
## Verwandte Concepts
- [[Claude Code Auto Mode]]
## Beziehungen
## Siehe auch
- [[Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31]]
## Fußnoten
[^s-conversation-auto-mode-and-tool-choice-session-2026-08-31]: [[Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31]]
<!-- wikitool:links -->
## Beziehungen
- **see-also:** [[Claude Code Auto Mode]]
- **operates-on:** [[Claude Code]]
- **derived-from:** [[Write-Once Frontmatter Fields]]
<!-- /wikitool:links -->
@@ -0,0 +1,70 @@
---
type: types/concept.md
concept_type: decision
tags: []
created: 2026-09-01
modified: 2026-09-01
related:
- operates-on: Chemenu
sources: ['Source - Public Release, Corpus Purge and History Squash Session 2026-09-01']
confidence: 0.70
confidence_base: 0.70
provenance: sourced
summary: Ein Repo mit Code- und Inhaltsanteil erhaelt zwei Lizenzen; die Grenze zwischen ihnen ist kein zweiter, gepflegter Pfadkatalog, sondern der ohnehin vorhandene Dateiplan des Distributionswerkzeugs.
---
# Dual Licensing by File Plan
**Typ:** Decision
## Definition
Ein Repository, das sowohl Werkzeug-Code als auch inhaltliches Material (Dokumentation, Daten,
kompiliertes Wissen) enthält, bekommt zwei Lizenzdateien statt einer - eine für den Code, eine
für den Inhalt. Welche Datei zu welcher Lizenz gehört, wird nicht in einer eigenen, zweiten
Liste festgehalten, sondern aus dem Dateiplan abgeleitet, den ein vorhandenes
Distributions-/Build-Werkzeug ohnehin pflegt.
## Kernpunkte
- Der naheliegende Fehler ist, die Grenze zwischen „Code" und „Inhalt" als eigene, gepflegte
Aufzählung von Pfaden in der Lizenzdatei selbst festzuschreiben. Das ist eine zweite Kopie
einer Regel, die bereits an anderer Stelle existiert (dem Dateiplan des Build-/
Distributionswerkzeugs) - und die Kopie, die driftet, wenn sich Verzeichnisse verschieben.
- Stattdessen verweist die Lizenz-Notiz auf den bestehenden Plan (z. B. eine Funktion, die
berechnet, was in eine Distribution exportiert wird und was nicht) als **einzige** Quelle der
Wahrheit für die Grenze.
- Welche der beiden Lizenzen den generischen Dateinamen `LICENSE` trägt, ist keine
Nebensächlichkeit: Es sollte die Lizenz sein, die ein Code-Hosting-Dienst (Forge) für das
Repository insgesamt meldet - typischerweise die restriktivere/Copyleft-Lizenz. Ein Leser, der
eine Copyleft-Pflicht übersieht, wird dadurch geschädigt; wer eine Pflicht zu viel annimmt,
nicht.
- Ein Distributions-Export, der Code unter einer Copyleft-Lizenz ausliefert, muss die
zugehörige Lizenzdatei zwingend mitliefern (nicht optional, nicht still übersprungen, wenn sie
fehlt) - sonst ist die exportierte Instanz eine Lizenzverletzung, sobald sie veröffentlicht
wird.
## Wann zu verwenden
- Ein Repository trägt sowohl Software-/Werkzeugcode als auch Inhalt mit eigenem
Urheberrechtscharakter (Dokumentation, Wissensbasis, Daten), für die unterschiedliche Lizenzen
angemessen sind.
- Es existiert bereits ein Werkzeug, das programmatisch entscheidet, welche Dateien zu welcher
Kategorie gehören (z. B. für einen Export- oder Build-Schritt).
## Wann NICHT zu verwenden
- Bei einem Repository, dessen Inhalt untrennbar mit dem Code verwoben ist und für das keine
separate, maschinell nachvollziehbare Grenze existiert - dort wäre die Lizenz-Zuordnung selbst
wieder eine unabhängige, drift-anfällige Liste.
## Beziehungen
## Siehe auch
- [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]]
<!-- wikitool:links -->
## Beziehungen
- **operates-on:** [[Chemenu]]
<!-- /wikitool:links -->
+214
View File
@@ -0,0 +1,214 @@
---
type: types/concept.md
concept_type: decision
tags: [issues, gitea, triage, labels, backlog]
created: 2026-08-31
modified: 2026-09-04
related:
- operates-on: Chemenu
- mechanism: Gitea MCP Server
- see-also: KB Stack Versioning
- see-also: Detect-Repair Asymmetry
sources: [Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31, Source - Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02, Source - Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04]
confidence: 0.70
confidence_base: 0.85
provenance: sourced
summary: 'Pflicht-Labelschema fuer das Gitea-Board: vier Achsen (area/kind/prio/size) plus seit 2026-09-04 drei optionale status/-Flags, darunter status/incoming fuer unausgearbeitete Stubs, die die Vier-Achsen-Pflicht aussetzen statt sie zu ergaenzen; die Regel liegt in instructions/dev/, weil sie keine ausgelieferte Instanz erreichen darf'
---
# Issue Label Scheme
**Typ:** Decision
## Definition
Issue Label Scheme ist die Entscheidung, offene Arbeit an diesem Stack ausschließlich als
Gitea-Issues zu führen und jedes offene Issue mit vier Pflicht-Labels zu versehen: einem
Bereich `area/`, einer Art `kind/`, einer Priorität `prio/` und einer Größe `size/`. Dazu
kommen drei optionale `status/`-Flags. Getroffen wurde die Entscheidung in dieser Form am
2026-09-02[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02]; sie ersetzt das
zweiachsige Schema vom 2026-08-31 (siehe [Historie](#historie)). Am 2026-09-04 kam das dritte
`status/`-Flag,
`status/incoming`, dazu[^s-gitea-issues-62-63-status-incoming-label-introduction-2026-09-04].
| `area/` | Bedeutung |
|---|---|
| `area/kb` | `kb/`-Schema, Contract, Confidence, Lint - die Wissensbasis als System. |
| `area/distribution` | Auslieferung, Upgrade und Versionierung einer Instanz. |
| `area/corpus` | Inhalt und Umfang von `kb/` in dieser Instanz, samt Demo-/Testbett-Frage. |
| `area/workflow` | Git, Merge, Branching, Publish, PRs. |
| `area/process` | Der Entwicklungsprozess selbst, nicht der Stack als Artefakt. |
| `kind/` | Bedeutung |
|---|---|
| `kind/decision` | Wartet auf eine Betreiberentscheidung. |
| `kind/build` | Spezifiziert, wartet nur noch auf Umsetzungszeit. |
| `kind/defect` | Befund: Doku und Realität, oder zwei Dokus, widersprechen sich. |
| `prio/` | Bedeutung |
|---|---|
| `prio/blocking` | Blockiert oder beschädigt laufende Arbeit. Als Nächstes. |
| `prio/planned` | Sammelt Zinsen. Eingeplant. |
| `prio/waiting` | Lohnend, wartet auf einen benannten Auslöser. |
| `size/` | Bedeutung |
|---|---|
| `size/S` | Eine Sitzung, ein Publish, ein klarer Schnitt. |
| `size/M` | Mehrere Dateien; eine Contract- oder Instruction-Änderung; eigener Testaufwand. |
| `size/L` | Mehrere Sitzungen, oder offene Entwurfsfragen vor dem ersten Commit. |
| `status/` (optional) | Bedeutung |
|---|---|
| `status/blocked` | Wartet auf ein anderes, noch offenes Issue - unabhängig vom `prio`-Wert nicht eigenständig bearbeitbar. |
| `status/unconfirmed` | Gemeldeter Verdacht, noch nicht gegen tatsächliches Verhalten geprüft; `size` und `prio` sind solange vorläufig. |
| `status/incoming` | Vom Menschen angelegter Stub - unvollständig, ohne Abnahmekriterien, ohne die vier Pflichtachsen. **Wird nie so umgesetzt, wie er dasteht:** erst Ausarbeitung und Triage gegen den Baum, dann Umsetzung[^s-gitea-issues-62-63-status-incoming-label-introduction-2026-09-04]. |
Siebzehn Labels stehen in Gitea; `prio/1`, `prio/2`, `prio/3` und `size/XS` existieren nicht
mehr[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02].
## Kernpunkte
- **Vier Achsen sind Pflicht, weil ihre Pflege maschinell läuft.** Der ursprüngliche Einwand
gegen eine dritte Achse war der Aufwand für einen einzelnen menschlichen Betreuer. Da
Body-Rewrites und Labelpflege über eine LLM-Sitzung laufen und ein Mensch in der Regel nur
Metadaten anfasst, trägt dieser Einwand
nicht mehr[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02].
- **Der Issue-Body ist die aktuelle Wahrheit, nicht der Ursprungstext.** Die Umsetzung eines
Issues zieht sich über mehrere, zeitlich getrennte Sitzungen, und der Body ist das einzige,
was sie verbindet: eine Sitzung muss allein aus ihm rekonstruieren können, was entschieden
und was offen ist. Er wird deshalb umgeschrieben statt
ergänzt[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02].
- **Ein Kommentar ist ein Changelog, keine Kopie.** Ein Volltext-Snapshot des alten Bodys pro
Revision zwingt einen Menschen zum Diffen zweier Fließtexte und ist damit keine lesbare
Historie, sondern nur eine weitere
Kopie[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02].
- **`area/` folgt der Systemgrenze, nicht dem Codeort.** Die Werte folgen der Stufenteilung aus
`AGENTS.md`. Ein `area/tools` gibt es bewusst nicht - Tooling wird nach der Domäne
einsortiert, die es
bedient[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02].
- **`kind/` darf sich im Lauf eines Issues ändern.** Der Wechsel von `decision` zu `build`,
sobald entschieden ist, ist erwünschtes Session-Memory-Verhalten und kein
Makel[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02].
- **Eine Priorität ohne Kosten ist eine halbe Entscheidung.** Größe ist Aufwand und nicht
Wichtigkeit, deshalb ist `prio/blocking size/S` das Beste, was auf einem Board stehen kann,
und `prio/waiting size/L` etwas, worüber gesprochen wird, bevor jemand anfängt.
- **`prio/waiting` ist kein Friedhof.** Der Auslöser muss im Issue benannt sein, sonst ist das
Label ein höfliches Nein[^s-conversation-issue-triage-labels-and-todo-retirement-session-2026-08-31].
- **Kein unbelegter Verdacht bleibt offen liegen.** Die Triage eines `status/unconfirmed`
endet entweder mit entferntem Flag und verbindlichen `size`/`prio`-Werten oder mit einem
geschlossenen Issue samt Begründung - die Prozessentsprechung zu Invariante 3 des
Stacks[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02].
- **Priorisiert wird nach Schaden, nicht nach Aufwand.** Das Kriterium der ersten Triage
lautete: was blockiert oder beschädigt laufende Arbeit. Ein Werkzeugfehler, der seinen
Benutzer gegen eine Invariante des Stacks drückt, rangiert deshalb vor einer fehlenden
Fähigkeit, so gut das Issue dazu auch geschrieben ist.
- **Ein Issue ohne Abnahmekriterium ist kein Arbeitspaket.** Beim Portieren der
Recherche-Notiz nach Issue #15 wurden Abnahmekriterien ergänzt, weil die Prosa-Notiz keine
hatte[^s-conversation-issue-triage-labels-and-todo-retirement-session-2026-08-31].
- **`TODO.md` wurde gelöscht statt gepflegt.** Ihr erster Abschnitt war ohnehin nur noch eine
Linkliste auf Issues; der zweite, die Recherche-Notiz, ging vollständig nach #15. Danach gab
es nichts mehr in der Datei, was nicht auf Gitea stand.
- **`status/incoming` setzt die Vier-Achsen-Pflicht aus, statt sie zu qualifizieren.** Bei den
beiden älteren `status/`-Flags gelten `area/`, `kind/`, `prio/` und `size/` weiterhin
zusätzlich; unter `status/incoming` sind sie nicht fällig, solange der Stub nicht ausgearbeitet
ist. Ein Stub auf Sicht durchzulabeln wäre der Fehler, nicht das
Weglassen[^s-gitea-issues-62-63-status-incoming-label-introduction-2026-09-04].
## Historie
Das ursprüngliche Schema vom 2026-08-31 hatte ~~genau zwei Pflicht-Labels, `prio/1..3` und
`size/XS..L`, und verzichtete ausdrücklich auf eine dritte Achse: Art, Bereich oder Status
wurden verworfen als der Punkt, ab dem eine Taxonomie eigene Pflege braucht, und das Board
habe einen einzigen Betreuer.~~ Sieben Labels wurden angelegt und auf alle zehn zu dem
Zeitpunkt offenen Issues
angewandt[^s-conversation-issue-triage-labels-and-todo-retirement-session-2026-08-31].
Was sich am 2026-09-02 geändert hat:
| Achse | Vorher | Jetzt |
|---|---|---|
| `prio/` | `1`, `2`, `3` | `blocking`, `planned`, `waiting` - reine Umbenennung, Bedeutung unverändert |
| `size/` | `XS`, `S`, `M`, `L` | `S`, `M`, `L` - `XS` entfällt, die übrigen unverändert |
| `area/` | - | fünf Werte, neu |
| `kind/` | - | drei Werte, neu |
| `status/` | - | zwei optionale Flags, neu |
Der Verzicht auf die dritte Achse fiel damit weg, nicht weil die Begründung falsch war,
sondern weil ihre Voraussetzung entfallen ist: gepflegt wird das Board nicht mehr von Hand.
Was sich am 2026-09-04 zusätzlich geändert
hat[^s-gitea-issues-62-63-status-incoming-label-introduction-2026-09-04]:
| Achse | Vorher | Jetzt |
|---|---|---|
| `status/` | zwei optionale Flags | drittes Flag `status/incoming` dazu - setzt, anders als die anderen beiden, die Vier-Achsen-Pflicht aus statt sie zu ergänzen |
## Wo die Regel liegt
Die Platzierung war die tragende Entscheidung, nicht das Schema selbst. `README.md` und
`AGENTS.md` gehen in jede über `wikitool dist export` ausgelieferte Instanz, und eine solche
Instanz hat kein Issue-Board auf `gitea.nehmer.net`. Eine dort mitgelieferte Label-Regel wäre
eine Anweisung ins Leere.
`instructions/dev/` ist der einzige Ort, der beides ist: von Agenten lesbar und nie
ausgeliefert, weil `dist export` das Verzeichnis vollständig ausschließt. Das Schema steht
deshalb in `instructions/dev/issue-tracking.md` und ist aus Schritt 2 des `stack-dev`-Skills
verlinkt[^s-conversation-issue-triage-labels-and-todo-retirement-session-2026-08-31].
Aus demselben Grund war der Release ein PATCH (`1.2.1`) und kein MINOR: für eine bestehende
Instanz ändert sich nichts. Das CI-Versions-Gate verlangte den Bump trotzdem, weil sein Muster
auf `instructions/` passt und `instructions/dev/` darunter liegt[^s-conversation-issue-triage-labels-and-todo-retirement-session-2026-08-31]. Siehe
[[KB Stack Versioning]].
Für die Erweiterung auf vier Achsen galt dieselbe Rechnung noch einmal: sie ging als `4.0.1`
und damit ebenfalls als PATCH
hinaus[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02]. Für das dritte
`status/`-Flag ein drittes Mal: `4.7.5-beta.1`, ebenfalls
PATCH[^s-gitea-issues-62-63-status-incoming-label-introduction-2026-09-04].
## Beispiele
- [[Chemenu]] - das Repository, dessen Board nach dem Schema geführt wird; siebzehn Labels
stehen dort, verteilt auf vier Pflicht- und eine optionale Familie
- [[Gitea MCP Server]] - der Weg, auf dem Issues und Labels gelesen und geschrieben werden
- [[Detect-Repair Asymmetry]] - Issue #14 ist der Fall, den dieses Concept beschreibt, und
trug in der ersten Triage `prio/2 size/S`, nach der Umbenennung also `prio/planned size/S`
## Wann zu verwenden
- Auf einem Board mit einem einzigen menschlichen Betreuer, dessen Labelpflege maschinell
läuft. Erst das macht mehr als zwei Achsen bezahlbar.
- Sobald offene Arbeit sonst in Prosa-Dateien wandert, die niemand als Board liest und die
gegen den Tracker driften.
- Sobald die Bearbeitung eines Issues sich über mehrere, zeitlich getrennte Sitzungen zieht -
dann trägt die Body-als-Wahrheit-Konvention den Kontext, den sonst ein Mensch jedes Mal neu
erzählen müsste.
## Wann NICHT zu verwenden
- Nicht dort, wo Labels von Hand gepflegt werden. Dann ist die ursprüngliche Zweiachsigkeit
die tragfähigere Wahl, und die Begründung von 2026-08-31 gilt unverändert.
- Nicht als Ersatz für die Abnahmekriterien im Issue-Text. Die Labels ordnen ein Issue ein; ob
es fertig ist, sagen sie nicht.
- Nicht mit umgeschriebenen Bodys dort, wo mehrere Menschen denselben Thread lesen und den
Verlauf brauchen. Die Konvention tauscht Historie gegen Aktualität und setzt voraus, dass
der Changelog-Kommentar als Historie genügt.
- Nicht in einer ausgelieferten Instanz. Das Schema beschreibt das Entwicklungs-Repository und
hat außerhalb davon keinen Gegenstand.
<!-- wikitool:links -->
## Beziehungen
- **operates-on:** [[Chemenu]]
- **mechanism:** [[Gitea MCP Server]]
- **see-also:** [[KB Stack Versioning]]
- **see-also:** [[Detect-Repair Asymmetry]]
<!-- /wikitool:links -->
<!-- wikitool:footnotes -->
## Fußnoten
[^s-gitea-issue-41-issue-management-and-label-scheme-2026-09-02]: [[Source - Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02]]
[^s-conversation-issue-triage-labels-and-todo-retirement-session-2026-08-31]: [[Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31]]
[^s-gitea-issues-62-63-status-incoming-label-introduction-2026-09-04]: [[Source - Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04]]
<!-- /wikitool:footnotes -->
@@ -0,0 +1,127 @@
---
type: types/concept.md
concept_type: decision
tags: [versioning, semver, release, stack]
created: 2026-08-30
modified: 2026-09-02
related:
- mechanism: wikitool
- see-also: Issue Label Scheme
- see-also: CI Integration
sources: [Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30, Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31, Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02]
confidence: 0.70
confidence_base: 0.70
provenance: sourced
summary: 'Semantische Versionierung des Wiki-Stacks: VERSION beschreibt die Maschinerie, Kompatibilitaet (Drop-in-Ersatz) und Inhaltsmigration sind seit 2.5.0 getrennte, unabhaengig geprueft Fragen'
---
# KB Stack Versioning
**Typ:** Decision
## Definition
KB Stack Versioning ist die Entscheidung, den Wiki-**Stack** semantisch zu versionieren und
diese Version strikt von der Form des Inhalts zu trennen. Die Stack-Version steht in der
Wurzeldatei `VERSION` und wird ausschließlich von `wikitool version bump`
geschrieben[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30]. Sie
beantwortet genau eine Frage: welche Maschinerie installiert ist.
Ein automatischer Bump aus Commit-Nachrichten wurde verworfen. `wikitool publish --message
"ingest: ..."` schreibt Content-Commits in dasselbe Repository, sodass eine
Conventional-Commit-Auswertung jeden Ingest zu einem Release
machte[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30]. Der Bump ist
deshalb eine ausdrückliche Handlung.
## Kernpunkte
- **Drei Fakten, drei Dateien.** `VERSION` trägt die Stack-Version und wird von `version bump`
geschrieben; `.wikitool-release.json` ist der Release-Stempel, den `dist export` in jeden
Export legt und der beantwortet, woher die Maschinerie stammt; `.wikitool-kb.json` trägt die
KB-Version und wird von `migrate done`
geschrieben[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30]. Die
Trennung ist keine Aufteilung aus Bequemlichkeit: Der Stempel ist erzeugt und darf nie von
Hand geändert werden, der KB-Zustand dagegen ist veränderlicher Instanzzustand.
- **Kompatibilität ist die linkeste Nicht-Null-Komponente** - dieselbe Regel, die Cargos
Caret-Ranges
verwenden[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30]. Sie gilt
einheitlich für `0.x` und `1.x`, sodass unter `0.x` der Schritt `0.1.x` -> `0.2.0` dasselbe
Signal trägt wie `MAJOR` ab `1.0.0`. Der Code für den `compat_key` ist deshalb einheitlich
formuliert und musste beim Wechsel auf `1.0.0` nicht angefasst
werden[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30].
- **Kompatibilität und Inhaltsmigration sind zwei unabhängige Fragen, seit `2.5.0` auch zwei
getrennte Marker.** Kompatibilität fragt, ob die neue Version ein Drop-in-Ersatz ist -
vorwärts ohne Handarbeit, rückwärts noch downgradebar; Inhaltsmigration fragt, ob `kb/` sich
bewegen muss. Ein Grenzübertritt kann `kb/` unangetastet lassen und trotzdem MAJOR sein - der
`2.0.0`-Rebranding-Bump ist das Beispiel: Update-Pfad, Release-Artefaktname und
Paket-Import-Name brachen, keine Seite tat es. `version bump` verlangt deshalb bei jedem
Grenzübertritt `--breaking "<was aufhört zu funktionieren>"`, unabhängig von
`--no-migration`/einem Migrationsdokument; beide Zeilen landen getrennt im
`CHANGES.md`-Eintrag[^s-version-part-nomenclature-and-breaking-change-gate-session-2026-09-02].
- **`x.y.z` ist die maximale Granularität. Keine Pre-Release-Suffixe.** Eine zweite
Ordnungsregel müsste vom Release-Feed, von der Migrationskette und von der
Kompatibilitätsprüfung gleichermaßen befolgt
werden[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30].
- **Der Einstieg bei `1.0.0` statt `0.1.0`** beseitigte einen Selbstwiderspruch: Die Anleitung
in `stack-dev/SKILL.md` wies `--minor` sowohl „neue Fähigkeit" als auch „erfordert Migration"
zu, was unter `0.x` nicht beides zugleich stimmen
kann[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30].
- **Aktualisierungserkennung über einen Stempel, nicht über eine Prüfsumme.**
`wikitool version check` darf als einziger Befehl einen Netzaufruf machen: eigener Befehl,
kein Schlüssel, Timeout, injizierbarer Fetch, damit Tests nie ein Netz
berühren[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30]. Der
Aktualisierungspfad selbst (`dist upgrade`) wurde bewusst zurückgestellt: erst Erkennung, dann
Ausführung.
- **CI wird nicht mitgeliefert.** `runs-on: linux-docker` ist ein standortspezifisches
Runner-Label und gehört nicht in eine verteilte
Instanz[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30].
- **Die Grenze wird an zwei Stellen erzwungen:** in `version bump` und in `docs verify`, ergänzt
um einen `kb-version`-Check in
`doctor`[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30]. Seit
`2.5.0` prüft `docs verify` dort zwei unabhängige Dinge - `check_migration_for_boundary` (hat
der Korpus sich bewegt) und `check_breaking_change_for_boundary` (wurde der Bruch benannt) -,
weil ein Grenzübertritt die eine Prüfung bestehen und an der anderen scheitern
kann[^s-version-part-nomenclature-and-breaking-change-gate-session-2026-09-02].
## Beispiele
- [[Chemenu]] - erste Instanz; `1.0.0` ist die Migrationsbasis, `1.0.1` das erste über
die Pipeline veröffentlichte Release.
- [[wikitool]] - trägt die Befehlsgruppen `version` und `migrate`, die die drei Dateien
schreiben und lesen.
## Wann zu verwenden
Sobald eine Wissensbasis als installierbares Artefakt an mehr als eine Stelle geht und
Aktualisierungen erkennbar sein müssen. Die Trennung von Stack- und Content-Version lohnt sich
ab dem Moment, in dem eine Instanz existiert, deren Inhalt hinter der Maschinerie zurückbleiben
kann.
## Wann NICHT zu verwenden
- Nicht für den Inhalt. Eine Version, die Stack und Content zugleich beschreibt, macht den
Zustand „Maschinerie `1.4.0`, Inhalt in `1.2.0`-Form" unabbildbar - und das ist der Zustand,
den jedes Upgrade
durchläuft[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30]. Dafür
ist [[KB Migration]] zuständig.
- Nicht als automatischer Bump aus Commit-Nachrichten, solange Content-Commits und
Stack-Commits im selben Repository liegen.
## Beziehungen
## Siehe auch
- [[Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31]]
- [[Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02]]
## Fußnoten
[^s-conversation-versioning-ci-cd-and-content-migration-session-2026-08-30]: [[Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30]]
[^s-version-part-nomenclature-and-breaking-change-gate-session-2026-09-02]: [[Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02]]
<!-- wikitool:links -->
## Beziehungen
- **mechanism:** [[wikitool]]
- **see-also:** [[Issue Label Scheme]]
- **see-also:** [[CI Integration]]
<!-- /wikitool:links -->
@@ -0,0 +1,118 @@
---
type: types/concept.md
concept_type: decision
tags: [quality, tooling, tests, governance]
created: 2026-08-31
modified: 2026-08-31
related:
- see-also: Ambient Environment Dependency
- mechanism: wikitool
- see-also: Iteration and Cost Limits
- see-also: Mass-Update Gate
sources: [Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31]
confidence: 0.50
confidence_base: 0.50
provenance: sourced
summary: Entscheidung, eine wiederkehrende Fehlerregel in die Ausfuehrung einzubauen statt sie aufzuschreiben - Rangfolge erzwingen vor melden vor erinnern, belegt an einer Regel, die gelesen wurde und nicht wirkte
---
# Structural Enforcement over Documented Rule
**Typ:** Decision
## Definition
Wo ein Fehler sich wiederholt, wird die Regel dagegen **in die Ausführung eingebaut**, statt sie
aufzuschreiben. Eine aufgeschriebene Regel wirkt nur, solange jemand sie liest, sie im richtigen
Moment erinnert und sie befolgt; eine strukturell durchgesetzte Regel macht den Fehler
unschreibbar oder bricht sichtbar ab.
Die Entscheidung ist nicht "Dokumentation ist wertlos". Sie ist eine Rangordnung für den Fall,
dass beides möglich wäre: **erst erzwingen, dann dokumentieren, warum erzwungen wird.** Die
Dokumentation erklärt die Regel und ihre Ausnahmen; sie trägt aber nicht die Durchsetzung.
## Kernpunkte
- **Der harte Beleg: eine gelesene Regel hat den Fehler nicht verhindert.** Bei Gitea-Issue #8
führten zwei neue Tests dieselbe Umgebungsabhängigkeit erneut ein - geschrieben von jemandem,
der das Issue vorher gelesen hatte[^s-conversation-hardening-the-test-suite-against-silent-environment-dependencies-session-2026-08-31]. Das ist kein Sorgfaltsmangel, sondern die Aussage über die
Wirksamkeit von Prosa in diesem Fall: sie wurde gelesen und wirkte nicht.
- **Der Stack wendet dasselbe Prinzip schon an anderer Stelle an.** Die Gates sind bewusst im
Code durchgesetzt und nicht als Anweisung formuliert - ein Prompt-Limit ist eines, an dem ein
Agent sich vorbeireden kann. Siehe [[Iteration and Cost Limits]] und [[Mass-Update Gate]].
Die Fixture-Entscheidung ist derselbe Grundsatz, angewandt auf die Testsuite.
- **Erzwingen schlägt Melden, und beides schlägt Erinnern.** Rangfolge: (1) den Fehler unmöglich
machen, (2) ihn beim Auftreten sichtbar abbrechen lassen, (3) ihn dokumentieren. Bei #8 war
Option 1 die Fixture (die Abhängigkeit kann nicht mehr entstehen), Option 2 der zweite
CI-Schritt (meldet nach dem Push), Option 3 der Satz im Issue - der bereits gescheitert war.
- **Ein Guard, der erst nach dem Push meldet, schützt nicht dort, wo die Fehler entstehen.** Der
verworfene zweite CI-Job hätte den Lauf des Entwicklers nie berührt. Geschrieben werden die
Fälle aber genau dort.
- **Ein Guard darf nicht auf einer zufälligen Eigenschaft seiner Umgebung beruhen.** Der
CI-Container galt als "Maschine ohne globale git-Konfiguration"; seit `actions/checkout@v7`
legt der Checkout selbst eine an[^s-conversation-hardening-the-test-suite-against-silent-environment-dependencies-session-2026-08-31]. Ein Guard mit dieser Voraussetzung hätte still aufgehört zu
greifen, ohne roten Lauf. Die strukturelle Variante hängt an nichts dergleichen.
- **Die Entscheidung wird begründet dort hinterlegt, wo jemand sie rückgängig machen würde.** Der
Kommentar am CI-Tests-Schritt hält fest, warum es beim einen Lauf bleibt - sonst rüstet
irgendwann jemand den zweiten aus dem alten Grund nach. Das ist die Rolle, die der
Dokumentation bleibt: nicht die Regel tragen, sondern ihre Aufhebung teuer machen.
- **Das Prinzip gilt rekursiv, und dort liegt seine offene Flanke.** Die Fixture aus `1.7.1`
pflegt ihre Variablenliste von Hand, und die Pflicht zum Nachtragen steht - in Prosa. Das ist
exakt dasselbe Muster eine Ebene höher und als Gitea-Issue #23 offen[^s-conversation-hardening-the-test-suite-against-silent-environment-dependencies-session-2026-08-31]. Wer dieses Concept
anwendet, sollte prüfen, ob sein Guard selbst nur durch eine Regel zusammengehalten wird.
- **Der Preis ist Aufwand vor dem Nutzen.** Erzwingen kostet Code, Tests für den Guard und einen
Nachweis, dass er greift. Aufschreiben kostet einen Absatz. Der Tausch lohnt sich, wenn der
Fehler wiederkehrt oder sein Schaden still ist - nicht bei jedem Einzelfall.
## Beispiele
- [[wikitool]] - die autouse-Fixture aus `1.7.1`, die die Umgebungsabhängigkeit unschreibbar
macht, statt in `instructions/dev/testing-conventions.md` davor zu warnen
- [[Iteration and Cost Limits]] - 60 Aufrufe je Session und der Loop-Breaker, im Code
durchgesetzt statt als Anweisung formuliert
- [[Mass-Update Gate]] - Exit 42 mit Freigabe-Token statt der Bitte, vorsichtig zu sein
- [[AGENTS.md]] - Invariante 8 ("eine Regel, ein Ort") ist die dokumentarische Hälfte desselben
Anliegens: eine Regel kann nur erzwungen werden, wenn sie genau eine Fassung hat
## Wann zu verwenden
- Ein Fehler ist zum zweiten Mal aufgetreten, besonders wenn der Verursacher die Regel dagegen
kannte.
- Der Fehler ist beim Entstehen unsichtbar und wird erst später und woanders sichtbar.
- Die Regel wäre in einem Dokument abgelegt, das im entscheidenden Moment niemand offen hat.
- Es gibt eine mechanische Prüfung, die den Fehler eindeutig erkennt - ohne die bleibt nur die
Dokumentation.
## Wann NICHT zu verwenden
- Für Urteilsfragen. Was auf eine Seite gehört, welcher Ton angemessen ist, ob ein Befund eine
eigene Seite verdient - dafür gibt es keine mechanische Prüfung, und eine erzwungene Näherung
wäre schlechter als eine gute Anleitung.
- Für Einzelfälle ohne Wiederholungsrisiko. Ein Guard, der nie greift, ist Code, der gewartet
werden muss und nichts trägt.
- Wenn die Durchsetzung mehr Fehlalarme produziert als Funde. Ein Guard, dessen Meldungen man
gewohnheitsmäßig überliest, hat den Schutz bereits verloren und kostet weiter.
- Als Ersatz für die Begründung. Ein erzwungener Check ohne erklärenden Kommentar wird beim
ersten Widerstand entfernt.
## Verwandte Concepts
- [[Green Suite Blind Spot]]
## Beziehungen
## Siehe auch
- [[Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31]]
## Fußnoten
[^s-conversation-hardening-the-test-suite-against-silent-environment-dependencies-session-2026-08-31]: [[Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31]]
<!-- wikitool:links -->
## Beziehungen
- **see-also:** [[Ambient Environment Dependency]]
- **mechanism:** [[wikitool]]
- **see-also:** [[Iteration and Cost Limits]]
- **see-also:** [[Mass-Update Gate]]
<!-- /wikitool:links -->