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
+42 -1
View File
@@ -35,7 +35,7 @@ dev-checkout concern - readable here, never shipped as something to parse.
--- ---
## 4.8.0-beta.6 - 2026-09-08 - kb/concepts/ bekommt Areas: layout: fuer concept, Area-Titel aus jedem Type-Spec, Schwellen-Empfehlung im lint (schliesst #59) ## 4.8.0-beta.7 - 2026-09-08 - source_type: Default streichen, unclassified als sichtbares Fach, layout: fuer source (schliesst #66)
**Author:** Torben Nehmer **Author:** Torben Nehmer
@@ -47,6 +47,7 @@ dev-checkout concern - readable here, never shipped as something to parse.
- raw accept: Stem-Eindeutigkeit im Typverzeichnis erzwingen, --replaces als einziger Weg daran vorbei (schliesst #64) - raw accept: Stem-Eindeutigkeit im Typverzeichnis erzwingen, --replaces als einziger Weg daran vorbei (schliesst #64)
- update entity naming conventions to use singular form for consistency - update entity naming conventions to use singular form for consistency
- kb/concepts/ bekommt Areas: layout: fuer concept, Area-Titel aus jedem Type-Spec, Schwellen-Empfehlung im lint (schliesst #59) - kb/concepts/ bekommt Areas: layout: fuer concept, Area-Titel aus jedem Type-Spec, Schwellen-Empfehlung im lint (schliesst #59)
- source_type: Default streichen, unclassified als sichtbares Fach, layout: fuer source (schliesst #66)
<!-- /wikitool:bumps --> <!-- /wikitool:bumps -->
Das Label `status/incoming` gibt es seit heute in Gitea: der Mensch legt einen Das Label `status/incoming` gibt es seit heute in Gitea: der Mensch legt einen
@@ -377,6 +378,46 @@ Seiten des „not" identisch, also eine Regel ohne Fall, an dem sie greift.
`kb/CONVENTIONS.md` und `kb/entities/COLLECTION.md` hatten im selben Commit das `kb/CONVENTIONS.md` und `kb/entities/COLLECTION.md` hatten im selben Commit das
korrekte Paar bekommen; `README.md` zieht jetzt mit `HA Integrations.md` nach. korrekte Paar bekommen; `README.md` zieht jetzt mit `HA Integrations.md` nach.
`source_type` hatte in `types/source.schema.yaml` ein `default: notes` — der Compiler wählte
das Sammelbecken, sobald niemand widersprach, nicht ein Mensch. #59 hatte den Bestand deshalb
für lopsided gehalten (25 von 29 Seiten `notes`) und `source` bewusst flach gelassen; nachgezählt
nach dem, was die Seiten tatsächlich sind (Dateiname, `author:`, Rohdatei), waren es 16
Session-Transkripte, 4 LLM-Analysen, 2 Tracker-Exporte und nur 3 echte Notizen. Der Default war
der Fehler, nicht das Enum.
Umgesetzt: `default:` gestrichen, `wikitool new source` verweigert jetzt ohne expliziten Wert.
Enum neu: `transcript`, `analysis`, `article`, `document`, `notes`, `tracker`, `unclassified`
`spec` und `image` entfallen (null Seiten, nie am echten Material bewährt). `unclassified` ist
das neue, sichtbare Fach für eine Quelle, deren Kategorie noch nicht feststeht — eigene Area,
beratender `lint`-Befund (`unclassified_source_pages`), keine harte Fehlerklasse. `types/source.md`
deklariert jetzt ein `layout:` für alle sieben Werte.
Auf dieser Instanz angewendet, in einem eigenen `work/reclassify-source-types/`-Lauf: 22 der 29
Source-Seiten per `wikitool touch --set source_type=<wert>` auf ihren tatsächlichen Wert
korrigiert (16 transcript, 4 analysis, 2 tracker), 7 unverändert. `wikitool move --reconcile` hat
alle 29 danach in ihre Area gezogen (transcripts 16, analyses 4, articles 3, notes 3, trackers 2,
documents 1, unclassified 0). `migrate verify --from HEAD` bestätigt `182 compared, 0 added,
0 removed, 29 moved, 22 findings` — die 22 sind exakt die beabsichtigten `source_type`-Änderungen,
kein Titel, kein Body, keine Wikilink- oder Zitatzahl angefasst. `lint --fail-on-error` grün,
insbesondere ohne *Misplaced Pages*, *Nested Pages* oder den neuen *Unclassified Source Pages*.
Geändert: `types/source.schema.yaml` (Enum, kein Default), `types/source.md` (`layout:`),
`types/type-spec.md` (`source` als Beispiel für ein bewusst fehlendes `layout:` ersetzt —
ein lopsided Feld wird repariert, nicht dauerhaft flach gelassen), `tools/chemenu/lint_core.py`
(`unclassified_source_pages`, neu), `tools/CONTRACT.md`, `instructions/wiki-ingest/SKILL.md`
(`--set source_type=`, `unclassified` als Ausweg), `instructions/dev/corpus-policy.md`
(Floor-Ausnahme für `unclassified`), `kb/sources/COLLECTION.md` (Areas, Autorschaft trennt
`analysis` von `document`), fünf Tests umgehängt (davon einer auf einen neuen
Fixture-Type-Spec, weil `source` als „hat Subtype-Feld, kein `layout:`"-Beispiel wegfällt),
sowie die 29 bewegten und 22 reklassifizierten Seiten unter `kb/sources/`.
**MINOR**, geprüft am Drop-in-Test: eine bestehende Instanz besitzt ihr eigenes
`types/source.md` (Auslieferung nur als `.template`), kopiert `tools/`/`types/`/`instructions/`
über sich und bleibt unverändert funktionsfähig — kein Downgrade-Bruch, kein umgeschriebenes
maschinengelesenes Format. Kein `--breaking`, kein Migrationsdokument.
Schließt #66.
--- ---
## 4.7.4 - 2026-09-04 - bootstrap.md nennt den session-id-WARN nach frischem Bootstrap explizit als erwartet ## 4.7.4 - 2026-09-04 - bootstrap.md nennt den session-id-WARN nach frischem Bootstrap explizit als erwartet
+1 -1
View File
@@ -1 +1 @@
4.8.0-beta.6 4.8.0-beta.7
+1 -1
View File
@@ -28,7 +28,7 @@ think, not a number to defend for its own sake.
| Floor | Check | Why this number | | Floor | Check | Why this number |
|---|---|---| |---|---|---|
| Every page type has ≥1 page | `wikitool search --field type=types/<t>.md` | A type with zero pages means its schema, its collection contract and its lint rules are unexercised | | Every page type has ≥1 page | `wikitool search --field type=types/<t>.md` | A type with zero pages means its schema, its collection contract and its lint rules are unexercised |
| Every declared subtype has ≥1 page | `wikitool search --field <x>_type=<v>` | Same reasoning, one level down - `entity_type`, `concept_type`, `source_type` | | Every declared subtype has ≥1 page | `wikitool search --field <x>_type=<v>` | Same reasoning, one level down - `entity_type`, `concept_type`, `source_type`. **Exception:** `source_type: unclassified` (Gitea #66) may sit at zero - it is a visible catalog slot for an unclear source, not a value the corpus is expected to exercise, and a page manufactured just to fill it would violate invariant 3 the same as any other unsourced page |
| ≥5 pages corpus-wide with ≥3 `sources:` entries | one-off script, see below | Provenance fan-in - multiple sources backing one claim - is a real case only a handful of pages exercise; fewer than 5 and a provenance-index bug can hide | | ≥5 pages corpus-wide with ≥3 `sources:` entries | one-off script, see below | Provenance fan-in - multiple sources backing one claim - is a real case only a handful of pages exercise; fewer than 5 and a provenance-index bug can hide |
| Orphan pages (no inbound link) between 1 and 10 | `wikitool lint` | Zero orphans makes orphan detection itself unobservable; more than 10 means the corpus stopped being curated | | Orphan pages (no inbound link) between 1 and 10 | `wikitool lint` | Zero orphans makes orphan detection itself unobservable; more than 10 means the corpus stopped being curated |
| Average outbound wikilinks per page ≥4 | one-off script, see below | Below this, ranking and graph-traversal work has too little structure to exercise | | Average outbound wikilinks per page ≥4 | one-off script, see below | Below this, ranking and graph-traversal work has too little structure to exercise |
+9
View File
@@ -71,11 +71,20 @@ pages should never have cost the concept contract. Field-level requirements alwa
```bash ```bash
tools/wikitool new source --name "<Title>" \ tools/wikitool new source --name "<Title>" \
--set source_type=<category> \
--set raw_files=<path1>,<path2>,... \ --set raw_files=<path1>,<path2>,... \
--set source_language=<ISO 639-1 code of the raw material> \ --set source_language=<ISO 639-1 code of the raw material> \
--set entities=A,B,C --set concepts=D,E --set entities=A,B,C --set concepts=D,E
``` ```
`source_type` has no default - `new source` refuses without it (Gitea #66). Pick from what
`tools/wikitool types describe source` lists, based on what the material *is*, not what it is
about: a session transcript is `transcript` regardless of subject, an LLM's own analysis is
`analysis` even when it reads like an article. Genuinely unclear after reading the source?
Set `unclassified` rather than guessing - it is a visible catalog slot with its own advisory
`lint` finding, not a silent default, and `wikitool touch --set source_type=<value>` corrects
it later without moving or renaming the page.
List **every** raw file this ingest covers - a folder of related documents becomes one List **every** raw file this ingest covers - a folder of related documents becomes one
source page with all its files in `raw_files:`, not one page per file. For an external source page with all its files in `raw_files:`, not one page per file. For an external
article also pass `--set source_url=<upstream URL>`; `raw_files:` must still point at the article also pass `--set source_url=<upstream URL>`; `raw_files:` must still point at the
+11
View File
@@ -52,6 +52,17 @@ The page tables live in a generated `INDEX.md` inside each collection, linked be
| Technologien | 20 | [entities/INDEX.md#technologien](entities/INDEX.md#technologien) | | Technologien | 20 | [entities/INDEX.md#technologien](entities/INDEX.md#technologien) |
| Werkzeuge | 31 | [entities/INDEX.md#werkzeuge](entities/INDEX.md#werkzeuge) | | Werkzeuge | 31 | [entities/INDEX.md#werkzeuge](entities/INDEX.md#werkzeuge) |
### sources/
| Area | Pages | Index |
|------|------:|-------|
| Analysen | 4 | [sources/INDEX.md#analysen](sources/INDEX.md#analysen) |
| Artikel | 3 | [sources/INDEX.md#artikel](sources/INDEX.md#artikel) |
| Dokumente | 1 | [sources/INDEX.md#dokumente](sources/INDEX.md#dokumente) |
| Notizen | 3 | [sources/INDEX.md#notizen](sources/INDEX.md#notizen) |
| Tracker-Exporte | 2 | [sources/INDEX.md#tracker-exporte](sources/INDEX.md#tracker-exporte) |
| Transkripte | 16 | [sources/INDEX.md#transkripte](sources/INDEX.md#transkripte) |
--- ---
## Notes ## Notes
+6
View File
@@ -161,3 +161,9 @@ wikitool move --reconcile hat die drei nach kb/entities/projects/{kfchou,vanilla
types/concept.md deklariert ein layout: fuer alle sechs concept_type-Werte; wikitool move --reconcile hat daraufhin alle 80 Seiten aus kb/concepts/ in ihre Area gezogen (architectures 20, patterns 17, protocols 3, workflows 28, decisions 7, problems 5). Kein Titel, kein Body, kein Frontmatter-Feld angefasst: migrate verify --from HEAD bestaetigt compared=182, added=0, removed=0, 80 moved, 0 findings. index rebuild erzeugt sechs Areas, keine ueber der Shard-Schwelle von 50, also kein eigener Shard - die Schwelle wirkt wieder als Schwelle statt als toter Wert. lint meldet danach weder misplaced_pages noch den neuen unsharded_collections-Befund. types/concept.md deklariert ein layout: fuer alle sechs concept_type-Werte; wikitool move --reconcile hat daraufhin alle 80 Seiten aus kb/concepts/ in ihre Area gezogen (architectures 20, patterns 17, protocols 3, workflows 28, decisions 7, problems 5). Kein Titel, kein Body, kein Frontmatter-Feld angefasst: migrate verify --from HEAD bestaetigt compared=182, added=0, removed=0, 80 moved, 0 findings. index rebuild erzeugt sechs Areas, keine ueber der Shard-Schwelle von 50, also kein eigener Shard - die Schwelle wirkt wieder als Schwelle statt als toter Wert. lint meldet danach weder misplaced_pages noch den neuen unsharded_collections-Befund.
--- ---
## [2026-09-08] move | source_type: Default gestrichen, 22 Seiten reklassifiziert, 6 Areas (#66)
types/source.schema.yaml hat kein default: mehr auf source_type; das Enum lautet transcript, analysis, article, document, notes, tracker, unclassified (spec und image entfallen). 22 der 29 Source-Seiten trugen notes nur, weil der Compiler es im Zweifel setzte - per touch --set source_type=<wert> auf ihren tatsaechlichen Wert korrigiert (16 transcript, 4 analysis, 2 tracker), 7 unveraendert (3 article, 3 notes, 1 document). types/source.md deklariert jetzt ein layout: fuer alle sieben Werte; wikitool move --reconcile hat daraufhin alle 29 Seiten in ihre Area gezogen. migrate verify --from HEAD bestaetigt compared=182, added=0, removed=0, 29 moved, 22 findings - alle 22 sind die beabsichtigten source_type-Aenderungen, keine anderen Felder oder Wikilink-/Zitatzahlen betroffen. index rebuild erzeugt sechs Areas (unclassified bleibt bei 0, wie vorgesehen), keine ueber der Shard-Schwelle. lint meldet danach weder misplaced_pages noch nested_pages noch unclassified_source_pages.
---
+31 -1
View File
@@ -26,7 +26,37 @@ renamed or dropped - its authoring rules below are the instance's, its existence
## Types offered ## Types offered
`source` (`tools/wikitool types describe source`). Page titles carry the `Source - ` prefix, `source` (`tools/wikitool types describe source`). Page titles carry the `Source - ` prefix,
applied automatically by `wikitool new source`. applied automatically by `wikitool new source`. Das Feld `source_type:` wählt die Area - **ohne
Default** (Gitea #66): `wikitool new source` verweigert ohne einen expliziten Wert.
| Area | Hält |
|------|------|
| `transcripts/` | Session-Transkripte: mitgeschriebener Dialog zwischen Mensch und Agent, oder zwischen Menschen |
| `analyses/` | Analyse-Output eines Modells über einen Gegenstand - kein Dialog, kein Protokoll, sondern eine eigenständige Einschätzung |
| `articles/` | Externe Artikel und Blogposts, mit `source_url:` |
| `documents/` | Eingelesene Dokumente, Handbücher, Spezifikationen |
| `notes/` | Echte eigene Notizen ohne Dialogform - Cheat Sheets, Merkzettel |
| `trackers/` | Exporte aus einem Issue-Tracker oder vergleichbaren System |
| `unclassified/` | Sichtbares Fach für eine Quelle, deren Kategorie noch nicht feststeht - beratender `lint`-Befund, kein Sammelbecken |
Das sind Areas, keine Collections: sie erben diesen Contract und tragen keine eigene
`COLLECTION.md`. Die Zuordnung trifft niemand von Hand - sie steht als `layout:` in
`types/source.md`, und `wikitool new` legt eine neue Seite direkt dort ab. Eine Seite, die
anderswo liegt, meldet `wikitool lint` als *misplaced*; `wikitool move --page "<Titel>"` bringt
sie an ihren berechneten Ort.
**`analysis` gegen `document`:** die Unterscheidung läuft über die Autorschaft, nicht über den
Inhalt. Ein Modell, das über einen Gegenstand urteilt oder ihn zusammenfasst, ohne dass ein
Mensch oder eine Organisation dafür geradesteht, ist `analysis` - unabhängig davon, wie
artikelförmig der Text wirkt. Ein Handbuch, eine Spezifikation, eine Herstellerdoku ist
`document`, auch wenn ein Werkzeug sie generiert hat, solange eine Organisation die Aussage
verantwortet. Die Frage ist also "wer haftet für die Behauptung", nicht "wie liest sich der
Text".
Vor #66 fiel fast alles hierher in `notes/`, weil `types/source.schema.yaml` `notes` als
`default:` gesetzt hatte - der Compiler wählte das Sammelbecken, sobald niemand widersprach.
22 der 29 damaligen Seiten waren tatsächlich Transkripte, Analysen oder Tracker-Exporte und
wurden per `wikitool touch --set source_type=…` umklassifiziert, bevor die Areas entstanden.
## Provenance rules ## Provenance rules
+50 -25
View File
@@ -4,37 +4,62 @@
29 page(s). Regenerated by `wikitool index rebuild`. 29 page(s). Regenerated by `wikitool index rebuild`.
## All ## Analysen
| Page | Type | Summary | Last Modified |
|------|------|---------|----------------|
| [[Source - Copilot Skill Restructure Instructions]] | analysis | Anweisungssatz zur Aufteilung der monolithischen AGENTS.md in einzelne plattformübergreifende Agent-Skills | 2026-08-03 |
| [[Source - LLM Improvements Codex Analysis]] | analysis | Codex-Analyse, die AGENTS.md und wikitool mit awesome-llm-wiki und Farzas Gist vergleicht und 7 aussichtsreiche Verbesserungen sowie zu vermeidende Anti-Muster benennt. Hinweis: eine Sonnet-Analyse zum Vergleich ist vorgesehen. | 2026-08-03 |
| [[Source - LLM Improvements Production Agent Gaps 2026]] | analysis | Externe Kritik (dzone, 2026) am Fehlen harter Iterations- und Kostengrenzen sowie eines Loop-Breakers; umgesetzt als Iteration Budget Gate in wikitool. | 2026-08-07 |
| [[Source - LLM Improvements Sonnet Analysis]] | analysis | Sonnet-Analyse, die AGENTS.md und wikitool mit Farzas Gist und awesome-llm-wiki vergleicht und die Codex-Analyse um konkrete Empfehlungen zu Qualitätsschwellen, Stilrichtlinie, Auditrhythmus und Skalierung ergänzt | 2026-08-03 |
## Artikel
| Page | Type | Summary | Last Modified | | Page | Type | Summary | Last Modified |
|------|------|---------|----------------| |------|------|---------|----------------|
| [[Source - AMD Powermanagement CPU]] | article | Heise.de-Artikel über den amd-pstate-Treiber in Linux-Kernel 5.17 für das Power Management von AMD-CPUs über CPPC. | 2022-03-20 | | [[Source - AMD Powermanagement CPU]] | article | Heise.de-Artikel über den amd-pstate-Treiber in Linux-Kernel 5.17 für das Power Management von AMD-CPUs über CPPC. | 2022-03-20 |
| [[Source - Arch Linux Cheat Sheet]] | notes | Persönliche Arch-Linux-Referenz zu AUR-Builds, GPG-Schlüsselverwaltung, dm-crypt- und LVM-Operationen sowie Benutzerverwaltung. | 2026-07-31 |
| [[Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04]] | notes | 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 | 2026-08-04 |
| [[Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31]] | notes | 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 | 2026-08-31 |
| [[Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31]] | notes | 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) | 2026-08-31 |
| [[Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31]] | notes | Sitzung, die ENVIRONMENT.md als optionales drittes Root-Dokument einfuehrt: gitignored, doctor meldet aber scheitert nie, Kontext ohne Autoritaet (1.8.0, Issue #24) | 2026-08-31 |
| [[Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31]] | notes | 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) | 2026-08-31 |
| [[Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31]] | notes | 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 | 2026-08-31 |
| [[Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31]] | notes | 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) | 2026-08-31 |
| [[Source - Conversation - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31]] | notes | 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 | 2026-08-31 |
| [[Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31]] | notes | 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 | 2026-08-31 |
| [[Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30]] | notes | 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 | 2026-08-30 |
| [[Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31]] | notes | 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) | 2026-08-31 |
| [[Source - Copilot Skill Restructure Instructions]] | notes | Anweisungssatz zur Aufteilung der monolithischen AGENTS.md in einzelne plattformübergreifende Agent-Skills | 2026-08-03 |
| [[Source - Docker Cheatsheet]] | notes | Praktisches Bash-Skript zur Fehlersuche bei Docker-Volumes und Overlay2, um den Container zu einem Verzeichnis im Dateisystem zu ermitteln. | 2026-07-31 |
| [[Source - Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02]] | notes | Threadkopie zu Gitea-Issue #41: vier Pflicht-Label-Achsen statt zwei, zwei optionale status/-Flags, und der Issue-Body als aktuelle Wahrheit statt als Ursprungstext | 2026-09-02 |
| [[Source - Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04]] | notes | Threadkopie zu Gitea-Issues #62/#63: das dritte status/-Flag status/incoming (Stubs werden nie so umgesetzt wie sie dastehen, es setzt die vier Pflichtachsen aus statt sie zu qualifizieren), plus die dadurch veraltete kb-Seite (17 statt 16 Labels) | 2026-09-04 |
| [[Source - LLM Improvements Codex Analysis]] | notes | Codex-Analyse, die AGENTS.md und wikitool mit awesome-llm-wiki und Farzas Gist vergleicht und 7 aussichtsreiche Verbesserungen sowie zu vermeidende Anti-Muster benennt. Hinweis: eine Sonnet-Analyse zum Vergleich ist vorgesehen. | 2026-08-03 |
| [[Source - LLM Improvements Production Agent Gaps 2026]] | notes | Externe Kritik (dzone, 2026) am Fehlen harter Iterations- und Kostengrenzen sowie eines Loop-Breakers; umgesetzt als Iteration Budget Gate in wikitool. | 2026-08-07 |
| [[Source - LLM Improvements Sonnet Analysis]] | notes | Sonnet-Analyse, die AGENTS.md und wikitool mit Farzas Gist und awesome-llm-wiki vergleicht und die Codex-Analyse um konkrete Empfehlungen zu Qualitätsschwellen, Stilrichtlinie, Auditrhythmus und Skalierung ergänzt | 2026-08-03 |
| [[Source - LLM Wiki Pattern]] | article | Grundlegendes Muster für persönliche Wissensbasen mit LLMs: ein dauerhaftes Wiki schrittweise pflegen, statt es aus den Quellen neu herzuleiten. | 2026-07-26 | | [[Source - LLM Wiki Pattern]] | article | Grundlegendes Muster für persönliche Wissensbasen mit LLMs: ein dauerhaftes Wiki schrittweise pflegen, statt es aus den Quellen neu herzuleiten. | 2026-07-26 |
| [[Source - LLM Wiki v2]] | article | Erweitertes LLM-Wiki-Muster mit Praxiserfahrungen aus agentmemory zu Memory Lifecycle, Confidence Scoring, Wissensgraph und Automatisierung. | 2026-07-26 | | [[Source - LLM Wiki v2]] | article | Erweitertes LLM-Wiki-Muster mit Praxiserfahrungen aus agentmemory zu Memory Lifecycle, Confidence Scoring, Wissensgraph und Automatisierung. | 2026-07-26 |
| [[Source - MCP Read Server Implementation Session 2026-09-02]] | notes | 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. | 2026-09-02 |
| [[Source - Private-Instance Merge Correction and Issue 30 Session 2026-09-01]] | notes | 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. | 2026-09-01 | ## Dokumente
| [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]] | notes | Sitzung, die den Chemenu-Stack von einer privaten Testinstanz in ein oeffentliches Repo ueberfuehrt: Korpus geloescht statt anonymisiert, Git-History auf einen Commit gesquashed, AGPL-3.0/CC-BY-4.0-Dual-Lizenz gewaehlt, dist export um einen Leak-Canary gehaertet. | 2026-09-01 |
| [[Source - Publish-Remote Gate and Issue Triage Session 2026-09-01]] | notes | 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. | 2026-09-01 | | Page | Type | Summary | Last Modified |
|------|------|---------|----------------|
| [[Source - qmd - GitHub Repository]] | document | GitHub-API-Metadaten, package.json und README-Auszuege von tobi/qmd: TypeScript/Node/Bun statt Go oder Rust, BM25 (SQLite FTS5) plus Vektor-Suche (sqlite-vec) plus LLM-Reranking ueber node-llama-cpp. | 2026-09-02 | | [[Source - qmd - GitHub Repository]] | document | GitHub-API-Metadaten, package.json und README-Auszuege von tobi/qmd: TypeScript/Node/Bun statt Go oder Rust, BM25 (SQLite FTS5) plus Vektor-Suche (sqlite-vec) plus LLM-Reranking ueber node-llama-cpp. | 2026-09-02 |
| [[Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02]] | notes | Sitzung, die die Versionsstelle als Kompatibilitaets- statt Migrationsfrage praezisiert und einen Freigabe-Ablauf fuer Breaking Changes in stack-dev einfuehrt | 2026-09-02 |
## Notizen
| Page | Type | Summary | Last Modified |
|------|------|---------|----------------|
| [[Source - Arch Linux Cheat Sheet]] | notes | Persönliche Arch-Linux-Referenz zu AUR-Builds, GPG-Schlüsselverwaltung, dm-crypt- und LVM-Operationen sowie Benutzerverwaltung. | 2026-07-31 |
| [[Source - Docker Cheatsheet]] | notes | Praktisches Bash-Skript zur Fehlersuche bei Docker-Volumes und Overlay2, um den Container zu einem Verzeichnis im Dateisystem zu ermitteln. | 2026-07-31 |
| [[Source - Wine]] | notes | Wine-Konfiguration für Arch Linux: pacman-NoExtract-Einstellungen und Bottles-Runtime-Optionen einschließlich Proton- und Lutris-Varianten. | 2026-08-01 | | [[Source - Wine]] | notes | Wine-Konfiguration für Arch Linux: pacman-NoExtract-Einstellungen und Bottles-Runtime-Optionen einschließlich Proton- und Lutris-Varianten. | 2026-08-01 |
## Tracker-Exporte
| Page | Type | Summary | Last Modified |
|------|------|---------|----------------|
| [[Source - Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02]] | tracker | Threadkopie zu Gitea-Issue #41: vier Pflicht-Label-Achsen statt zwei, zwei optionale status/-Flags, und der Issue-Body als aktuelle Wahrheit statt als Ursprungstext | 2026-09-02 |
| [[Source - Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04]] | tracker | Threadkopie zu Gitea-Issues #62/#63: das dritte status/-Flag status/incoming (Stubs werden nie so umgesetzt wie sie dastehen, es setzt die vier Pflichtachsen aus statt sie zu qualifizieren), plus die dadurch veraltete kb-Seite (17 statt 16 Labels) | 2026-09-04 |
## Transkripte
| Page | Type | Summary | Last Modified |
|------|------|---------|----------------|
| [[Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04]] | transcript | 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 | 2026-08-04 |
| [[Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31]] | transcript | 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 | 2026-08-31 |
| [[Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31]] | transcript | 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) | 2026-08-31 |
| [[Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31]] | transcript | Sitzung, die ENVIRONMENT.md als optionales drittes Root-Dokument einfuehrt: gitignored, doctor meldet aber scheitert nie, Kontext ohne Autoritaet (1.8.0, Issue #24) | 2026-08-31 |
| [[Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31]] | transcript | 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) | 2026-08-31 |
| [[Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31]] | transcript | 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 | 2026-08-31 |
| [[Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31]] | transcript | 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) | 2026-08-31 |
| [[Source - Conversation - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31]] | transcript | 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 | 2026-08-31 |
| [[Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31]] | transcript | 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 | 2026-08-31 |
| [[Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30]] | transcript | 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 | 2026-08-30 |
| [[Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31]] | transcript | 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) | 2026-08-31 |
| [[Source - MCP Read Server Implementation Session 2026-09-02]] | transcript | 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. | 2026-09-02 |
| [[Source - Private-Instance Merge Correction and Issue 30 Session 2026-09-01]] | transcript | 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. | 2026-09-01 |
| [[Source - Public Release, Corpus Purge and History Squash Session 2026-09-01]] | transcript | Sitzung, die den Chemenu-Stack von einer privaten Testinstanz in ein oeffentliches Repo ueberfuehrt: Korpus geloescht statt anonymisiert, Git-History auf einen Commit gesquashed, AGPL-3.0/CC-BY-4.0-Dual-Lizenz gewaehlt, dist export um einen Leak-Canary gehaertet. | 2026-09-01 |
| [[Source - Publish-Remote Gate and Issue Triage Session 2026-09-01]] | transcript | 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. | 2026-09-01 |
| [[Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02]] | transcript | Sitzung, die die Versionsstelle als Kompatibilitaets- statt Migrationsfrage praezisiert und einen Freigabe-Ablauf fuer Breaking Changes in stack-dev einfuehrt | 2026-09-02 |
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: analysis
author: Torben author: Torben
raw_files: [raw/notes/copilot-skill-restructure-instructions.md] raw_files: [raw/notes/copilot-skill-restructure-instructions.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: analysis
author: Codex LLM author: Codex LLM
raw_files: [raw/notes/llm-improvements-codex.md] raw_files: [raw/notes/llm-improvements-codex.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: analysis
author: Torben author: Torben
raw_files: [raw/notes/llm-improvements-production-agent-gaps.md] raw_files: [raw/notes/llm-improvements-production-agent-gaps.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: analysis
author: Sonnet LLM author: Sonnet LLM
raw_files: [raw/notes/llm-improvements-sonnet.md] raw_files: [raw/notes/llm-improvements-sonnet.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: tracker
author: Torben Nehmer author: Torben Nehmer
raw_files: [raw/notes/Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02.md] raw_files: [raw/notes/Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02.md]
source_language: de source_language: de
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: tracker
author: Torben Nehmer author: Torben Nehmer
raw_files: [raw/notes/Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04.md] raw_files: [raw/notes/Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04.md]
source_language: de source_language: de
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: GitHub Copilot (Claude Sonnet 5) author: GitHub Copilot (Claude Sonnet 5)
raw_files: [raw/notes/Conversation Transcript - AGENTS.md Skill Restructuring Session 2026-08-04.md] raw_files: [raw/notes/Conversation Transcript - AGENTS.md Skill Restructuring Session 2026-08-04.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Claude Code (claude-opus-5) author: Claude Code (claude-opus-5)
raw_files: [raw/notes/Conversation Transcript - Auto Mode and Tool Choice Session 2026-08-31.md] raw_files: [raw/notes/Conversation Transcript - Auto Mode and Tool Choice Session 2026-08-31.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Claude Code (claude-opus-5) 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'] raw_files: ['raw/notes/Conversation Transcript - Comma Bug, Budget Refund and Lint Report Path Session 2026-08-31.md']
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Torben Nehmer author: Torben Nehmer
raw_files: [raw/notes/Conversation Transcript - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31.md] raw_files: [raw/notes/Conversation Transcript - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Claude Code (claude-opus-5) author: Claude Code (claude-opus-5)
raw_files: [raw/notes/Conversation Transcript - Gate Counting and Measured Calibration Session 2026-08-31.md] raw_files: [raw/notes/Conversation Transcript - Gate Counting and Measured Calibration Session 2026-08-31.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Torben author: Torben
raw_files: [raw/notes/Conversation Transcript - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31.md] raw_files: [raw/notes/Conversation Transcript - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Claude Code (claude-opus-5) author: Claude Code (claude-opus-5)
raw_files: ['raw/notes/Conversation Transcript - Issue Triage, Labels and TODO Retirement Session 2026-08-31.md'] raw_files: ['raw/notes/Conversation Transcript - Issue Triage, Labels and TODO Retirement Session 2026-08-31.md']
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Claude Code (claude-opus-5) 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] raw_files: [raw/notes/Conversation Transcript - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Claude Code (claude-opus-5) 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] raw_files: [raw/notes/Conversation Transcript - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Claude Code (claude-opus-5) author: Claude Code (claude-opus-5)
raw_files: ['raw/notes/Conversation Transcript - Versioning, CI-CD and Content Migration Session 2026-08-30.md'] raw_files: ['raw/notes/Conversation Transcript - Versioning, CI-CD and Content Migration Session 2026-08-30.md']
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Claude Code (claude-opus-5) author: Claude Code (claude-opus-5)
raw_files: [raw/notes/Conversation Transcript - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md] raw_files: [raw/notes/Conversation Transcript - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md]
source_language: en source_language: en
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Torben author: Torben
raw_files: [raw/notes/Conversation Transcript - MCP Read Server Implementation Session 2026-09-02.md] raw_files: [raw/notes/Conversation Transcript - MCP Read Server Implementation Session 2026-09-02.md]
source_language: de source_language: de
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Torben author: Torben
raw_files: [raw/notes/Conversation Transcript - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md] raw_files: [raw/notes/Conversation Transcript - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md]
source_language: de source_language: de
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Torben author: Torben
raw_files: ['raw/notes/Conversation Transcript - Public Release, Corpus Purge and History Squash Session 2026-09-01.md'] raw_files: ['raw/notes/Conversation Transcript - Public Release, Corpus Purge and History Squash Session 2026-09-01.md']
source_language: de source_language: de
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Torben author: Torben
raw_files: [raw/notes/Conversation Transcript - Publish-Remote Gate and Issue Triage Session 2026-09-01.md] raw_files: [raw/notes/Conversation Transcript - Publish-Remote Gate and Issue Triage Session 2026-09-01.md]
source_language: de source_language: de
@@ -1,6 +1,6 @@
--- ---
type: types/source.md type: types/source.md
source_type: notes source_type: transcript
author: Torben Nehmer author: Torben Nehmer
raw_files: [raw/notes/Conversation Transcript - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02.md] raw_files: [raw/notes/Conversation Transcript - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02.md]
source_language: de source_language: de
+1 -1
View File
@@ -51,7 +51,7 @@ tools/wikitool <command> --help
| `index rebuild [--dry-run]` | Regenerate the catalog from every page's frontmatter: `kb/index.md` becomes a map (statistics, one row per collection and per area, links to the shards) and the page tables are written to a generated `INDEX.md` in each collection. An area past 50 rows gets its own shard. Stale shards from removed collections/areas are deleted in the same pass | | `index rebuild [--dry-run]` | Regenerate the catalog from every page's frontmatter: `kb/index.md` becomes a map (statistics, one row per collection and per area, links to the shards) and the page tables are written to a generated `INDEX.md` in each collection. An area past 50 rows gets its own shard. Stale shards from removed collections/areas are deleted in the same pass |
| `log append --op ingest\|query\|lint\|create\|update\|delete\|rename\|move --title "..." [--body "..."\|--body-file path]` | Append a formatted entry to `kb/log.md` | | `log append --op ingest\|query\|lint\|create\|update\|delete\|rename\|move --title "..." [--body "..."\|--body-file path]` | Append a formatted entry to `kb/log.md` |
| `log status` | Read-only: count `ingest` entries logged since the last `lint` entry - the deterministic trigger behind the Maintenance Schedule's "every 10 sources" full-lint cadence | | `log status` | Read-only: count `ingest` entries logged since the last `lint` entry - the deterministic trigger behind the Maintenance Schedule's "every 10 sources" full-lint cadence |
| `lint [--json] [--markdown out.md] [--full] [--fail-on-error]` | Structural + provenance checks: broken wikilinks, dangling frontmatter references, orphan pages, index drift, schema gaps, duplicate titles, title mismatches, pages nested more than one directory below their collection (hard - the generated catalog folds these into their area silently rather than merely reading it, see #57), uncovered raw files, broken `raw_files:` refs, raw files claimed by more than one source page, unmarked provenance, citation/frontmatter drift, unbalanced generated-region markers, edges whose label is missing or not authorised by the source collection's `outbound:` (both hard once `kb_version` has reached the release that introduced labelled edges - advisory below it, so a corpus mid-migration is not refused by the check measuring it), `see-also` edges whose reverse direction already carries a specific label (advisory only - redundant rather than wrong, and never migration-gated, since no version turns the redundancy into an error), a collection past the catalog's per-area shard threshold that has no areas to shard (advisory only - sharding is automatic but per *area*, so a collection nobody gave areas keeps one table however large it grows, #59; reported with the split its subtype field would produce, and only when that split puts every resulting area at or under the threshold, so a lopsided or small collection stays silent), quote-limit overages (>2 blockquoted lines/page, advisory only). Prints only the sections that found something and always writes the full report to `reports/Lint Report <date>.md` (or `--markdown`), naming the path - `--full` prints everything, `--json` prints the findings and writes nothing | | `lint [--json] [--markdown out.md] [--full] [--fail-on-error]` | Structural + provenance checks: broken wikilinks, dangling frontmatter references, orphan pages, index drift, schema gaps, duplicate titles, title mismatches, pages nested more than one directory below their collection (hard - the generated catalog folds these into their area silently rather than merely reading it, see #57), uncovered raw files, broken `raw_files:` refs, raw files claimed by more than one source page, unmarked provenance, citation/frontmatter drift, unbalanced generated-region markers, edges whose label is missing or not authorised by the source collection's `outbound:` (both hard once `kb_version` has reached the release that introduced labelled edges - advisory below it, so a corpus mid-migration is not refused by the check measuring it), `see-also` edges whose reverse direction already carries a specific label (advisory only - redundant rather than wrong, and never migration-gated, since no version turns the redundancy into an error), a collection past the catalog's per-area shard threshold that has no areas to shard (advisory only - sharding is automatic but per *area*, so a collection nobody gave areas keeps one table however large it grows, #59; reported with the split its subtype field would produce, and only when that split puts every resulting area at or under the threshold, so a lopsided or small collection stays silent), source pages sitting in the `unclassified` catalog slot (advisory only - `unclassified` is the visible fallback for a genuinely unclear source, #66, not a defect), quote-limit overages (>2 blockquoted lines/page, advisory only). Prints only the sections that found something and always writes the full report to `reports/Lint Report <date>.md` (or `--markdown`), naming the path - `--full` prints everything, `--json` prints the findings and writes nothing |
| `search ["<text>"] [--field <predicate> ...] [--kind/--subtype/--collection/--tag <v>] [--regex] [--limit N] [--sort [-]<field>] [--backend <name>] [--matches] [--json]` | Find pages in `kb/` without reading the index. Text search runs through a pluggable backend (`rg` today); `--field` predicates are evaluated on frontmatter - `f=v`, `f~substring`, `'f>=v'`, `'f:*'` (present), `'!f'` (absent), repeatable and ANDed. With no text this is a pure structured query. Results carry kind/summary/confidence so a hit can be judged without opening the page. A page whose frontmatter does not parse can match no positive predicate, so it is **named** rather than dropped: `--json` always carries an `unreadable` list of `{path, reason}` (usually empty), and the table form writes the same lines to stderr. `--regex` is applied by `rg` alone, whose engine is linear; the ranking boosts for title and summary are literal-containment only, so a non-literal pattern is ranked by match count. `rg` is killed after 30 s and reported as a failure. Read-only, and **exempt from the Iteration Budget Gate** | | `search ["<text>"] [--field <predicate> ...] [--kind/--subtype/--collection/--tag <v>] [--regex] [--limit N] [--sort [-]<field>] [--backend <name>] [--matches] [--json]` | Find pages in `kb/` without reading the index. Text search runs through a pluggable backend (`rg` today); `--field` predicates are evaluated on frontmatter - `f=v`, `f~substring`, `'f>=v'`, `'f:*'` (present), `'!f'` (absent), repeatable and ANDed. With no text this is a pure structured query. Results carry kind/summary/confidence so a hit can be judged without opening the page. A page whose frontmatter does not parse can match no positive predicate, so it is **named** rather than dropped: `--json` always carries an `unreadable` list of `{path, reason}` (usually empty), and the table form writes the same lines to stderr. `--regex` is applied by `rg` alone, whose engine is linear; the ranking boosts for title and summary are literal-containment only, so a non-literal pattern is ranked by match count. `rg` is killed after 30 s and reported as a failure. Read-only, and **exempt from the Iteration Budget Gate** |
| `confidence decay [--apply]` | Recompute every page's derived `confidence` as `confidence_base * (1 - 0.01/month)`, floored at 0.2; dry-run by default | | `confidence decay [--apply]` | Recompute every page's derived `confidence` as `confidence_base * (1 - 0.01/month)`, floored at 0.2; dry-run by default |
| `confidence init-base [--apply]` | One-time backfill: set `confidence_base` from the current `confidence` on pages that predate the derived-confidence model | | `confidence init-base [--apply]` | One-time backfill: set `confidence_base` from the current `confidence` on pages that predate the derived-confidence model |
+29
View File
@@ -127,6 +127,22 @@ def misplaced_pages(pages: dict[str, Page]) -> list[dict]:
] ]
def unclassified_source_pages(pages: dict[str, Page]) -> list[dict]:
"""Source pages sitting in the `unclassified` catalog slot.
Advisory, like `misplaced_pages` above: `unclassified` is the visible
fallback for a genuinely unclear source (Gitea #66, replacing the old
silent `default: notes`), not a broken state - a page there is exactly as
valid as one anywhere else, only waiting for someone to look at it and
pick a real category with `wikitool touch --set source_type=<value>`."""
return [
{"page": title}
for title, page in sorted(pages.items())
if page.frontmatter.get("type") == "types/source.md"
and page.frontmatter.get("source_type") == "unclassified"
]
def nested_pages(kb_dir: Path, pages: dict[str, Page]) -> list[dict]: def nested_pages(kb_dir: Path, pages: dict[str, Page]) -> list[dict]:
"""Report form of `find_nested_pages`: `{"page", "at", "depth"}` per """Report form of `find_nested_pages`: `{"page", "at", "depth"}` per
finding. finding.
@@ -474,6 +490,7 @@ def run_lint(kb_dir: Path) -> dict:
"misplaced_pages": misplaced, "misplaced_pages": misplaced,
"nested_pages": nested, "nested_pages": nested,
"unsharded_collections": unsharded_collections(kb_dir, pages), "unsharded_collections": unsharded_collections(kb_dir, pages),
"unclassified_source_pages": unclassified_source_pages(pages),
"uncovered_raw_files": find_uncovered_raw_files(config.RAW_DIR, pages), "uncovered_raw_files": find_uncovered_raw_files(config.RAW_DIR, pages),
"broken_raw_refs": find_broken_raw_refs(pages), "broken_raw_refs": find_broken_raw_refs(pages),
"duplicate_raw_file_owners": find_duplicate_raw_file_owners(pages), "duplicate_raw_file_owners": find_duplicate_raw_file_owners(pages),
@@ -567,6 +584,12 @@ def render_markdown(report: dict) -> str:
"`wikitool move --reconcile` and `wikitool index rebuild`" "`wikitool move --reconcile` and `wikitool index rebuild`"
), ),
) )
_section(
lines, "Unclassified Source Pages (source_type: unclassified) - recommendation, not an error",
report.get("unclassified_source_pages", []),
lambda i: f"[[{i['page']}]] - `wikitool touch --set source_type=<value>` once its "
"category is known",
)
_section( _section(
lines, "Uncovered Raw Files (no source page)", report["uncovered_raw_files"], lines, "Uncovered Raw Files (no source page)", report["uncovered_raw_files"],
lambda i: f"`{i}`", lambda i: f"`{i}`",
@@ -728,6 +751,12 @@ def default_report_path(report: dict) -> Path:
# Failing on it would also make `lint` red on a corpus that is entirely # Failing on it would also make `lint` red on a corpus that is entirely
# self-consistent, which is the state the recommendation is asking to improve. # self-consistent, which is the state the recommendation is asking to improve.
# #
# `unclassified_source_pages` is advisory for the same reason `misplaced_pages`
# is: `unclassified` (Gitea #66) is a deliberately visible catalog slot for a
# source whose category is genuinely unclear, not a defect - failing on it
# would penalise the honest "I don't know yet" that the slot exists to allow,
# where the old silent `default: notes` hid the same uncertainty for free.
#
# `malformed_edges` and `unbalanced_markers` are hard from the start: neither # `malformed_edges` and `unbalanced_markers` are hard from the start: neither
# describes an unconverted page, only a broken one. # describes an unconverted page, only a broken one.
# #
+1 -1
View File
@@ -311,7 +311,7 @@ def kb_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
"\n# Modbus\n\n## Definition\n\nIndustrial protocol.\n", "\n# Modbus\n\n## Definition\n\nIndustrial protocol.\n",
) )
write_page( write_page(
kb / "sources/Source - Aurora.md", kb / "sources/notes/Source - Aurora.md",
{ {
"type": "types/source.md", "source_type": "notes", "author": "Torben", "type": "types/source.md", "source_type": "notes", "author": "Torben",
"source": "raw/notes/Aurora.md", "date": "2026-08-02", "source": "raw/notes/Aurora.md", "date": "2026-08-02",
+58 -11
View File
@@ -1,9 +1,11 @@
import json import json
import shutil
from datetime import date from datetime import date
import pytest import pytest
from chemenu import config, kb_state from chemenu import config, kb_state
from chemenu.type_resolver import resolver
from chemenu.commands.lint import ( from chemenu.commands.lint import (
HARD_ERROR_KEYS, HARD_ERROR_KEYS,
hard_error_keys, hard_error_keys,
@@ -98,7 +100,7 @@ def test_lint_detects_dangling_source_page_entity_ref(kb_dir):
"""Source pages declare `entities:`/`concepts:`, not `related:`/`sources:` - """Source pages declare `entities:`/`concepts:`, not `related:`/`sources:` -
the field list comes from each type-spec's own `page_ref_fields:`.""" the field list comes from each type-spec's own `page_ref_fields:`."""
write_page( write_page(
kb_dir / "sources/Source - Aurora.md", kb_dir / "sources/notes/Source - Aurora.md",
{"type": "types/source.md", "source_type": "notes", "author": "Torben", {"type": "types/source.md", "source_type": "notes", "author": "Torben",
"source": "raw/notes/Aurora.md", "date": "2026-08-02", "tags": [], "source": "raw/notes/Aurora.md", "date": "2026-08-02", "tags": [],
"entities": ["aurora", "ghost-entity"], "concepts": []}, "entities": ["aurora", "ghost-entity"], "concepts": []},
@@ -293,16 +295,59 @@ def test_lint_recommends_areas_for_a_collection_past_the_threshold(kb_dir):
assert finding["layout_declared"] is True assert finding["layout_declared"] is True
def test_the_area_recommendation_says_the_layout_is_missing_when_it_is(kb_dir): def test_the_area_recommendation_says_the_layout_is_missing_when_it_is(kb_dir, tmp_path, monkeypatch):
"""`types/source.md` deliberately declares no `layout:`, so a sources """A collection whose type has a `subtype_field:` but no `layout:` has
collection that grew past the threshold has nothing for `move` to compute a nothing for `move` to compute a destination from - the fix starts one step
destination from - the fix starts one step earlier, and the report says so.""" earlier, and the report says so.
`types/source.md` used to be the worked example, but Gitea #66 gave it a
`layout:` covering every enum value, and `comparison` (the other type with
no `layout:`) has no `subtype_field:` at all to exercise this branch with.
So this is now the one place in the suite that still needs the
"has a subtype axis, hasn't been given a layout" shape, which is a fixture
type-spec, copied in beside the real ones so every other fixture page
(entities, concepts, sources, comparisons) keeps resolving normally.
Filled into `comparisons/` rather than `sources/`: the fixture wiki's own
source page now lives correctly under `sources/notes/`, and reusing that
directory here would mix its real `types/source.md` pages into this
fixture type's counts - `comparisons/` stays empty in the base fixture,
so filling it is self-contained."""
types_dir = tmp_path / "types"
shutil.copytree(config._PACKAGE_ROOT / "types", types_dir)
(types_dir / "badtype.md").write_text(
"---\n"
"type: types/type-spec.md\n"
"name: badtype\n"
"description: fixture type with a subtype field and no layout\n"
"schema: types/badtype.schema.yaml\n"
"subtype_field: bad_type\n"
"base_dir: badthings\n"
"---\n\n# badtype\n",
encoding="utf-8",
)
(types_dir / "badtype.schema.yaml").write_text(
"type: object\n"
"properties:\n"
" type: {type: string, const: 'types/badtype.md'}\n"
" bad_type: {type: string}\n"
" created: {type: string, format: date}\n"
" modified: {type: string, format: date}\n"
" provenance: {type: string, enum: [sourced, general, mixed]}\n"
" summary: {type: string}\n"
"required: [type, bad_type, created, modified, provenance, summary]\n"
"additionalProperties: false\n",
encoding="utf-8",
)
monkeypatch.setattr(config, "TYPES_DIR", types_dir)
monkeypatch.setattr(resolver, "_repo_root", tmp_path)
_fill_collection( _fill_collection(
kb_dir, "sources", "types/source.md", "source_type", kb_dir, "comparisons", "types/badtype.md", "bad_type",
{"notes": 30, "article": 21}, {"notes": 30, "article": 21},
) )
report = run_lint(kb_dir) report = run_lint(kb_dir)
finding = next(i for i in report["unsharded_collections"] if i["collection"] == "sources") finding = next(i for i in report["unsharded_collections"] if i["collection"] == "comparisons")
assert finding["layout_declared"] is False assert finding["layout_declared"] is False
assert "Declare a `layout:`" in render_markdown(report) assert "Declare a `layout:`" in render_markdown(report)
@@ -323,10 +368,12 @@ def test_the_area_recommendation_is_not_a_failure(kb_dir):
def test_lint_is_silent_about_a_collection_under_the_threshold(kb_dir): def test_lint_is_silent_about_a_collection_under_the_threshold(kb_dir):
"""The sources shape: 29 pages, lopsided across `source_type` - and under """The pre-#66 sources shape: 29 pages, lopsided across `source_type`
the threshold anyway, so it never fires. That is what keeps the bad split because the schema handed out `notes` as a default whenever nobody chose
(one area of 25 plus four splinters) from ever being recommended, without a value - and under the threshold anyway, so it never fires regardless.
the check needing to know anything about sources.""" That is what kept the bad split (one area of 25 plus four splinters) from
ever being recommended while the default still existed, without the check
needing to know anything about sources."""
_fill_collection( _fill_collection(
kb_dir, "sources", "types/source.md", "source_type", kb_dir, "sources", "types/source.md", "source_type",
{"notes": 25, "article": 3, "document": 1}, {"notes": 25, "article": 3, "document": 1},
+32 -6
View File
@@ -43,8 +43,11 @@ def test_page_subdir_falls_back_for_unmapped_subtype():
def test_page_subdir_is_none_for_types_without_layout(): def test_page_subdir_is_none_for_types_without_layout():
assert _page_subdir(None, "types/source.md") is None # `comparison` has no `layout:` at all (and no `subtype_field:` to have one
assert _page_subdir("anything", "types/source.md") is None # for) - `types/source.md` no longer qualifies, since Gitea #66 gave it a
# `layout:` covering every enum value.
assert _page_subdir(None, "types/comparison.md") is None
assert _page_subdir("anything", "types/comparison.md") is None
def test_coerce_set_value_uses_declared_schema_type(): def test_coerce_set_value_uses_declared_schema_type():
@@ -190,21 +193,42 @@ def test_new_source_prefixes_title_and_prefills_related_entities(monkeypatch, kb
_fixture_raw_file(monkeypatch, kb_dir, "raw/notes/gateway.example.net.md") _fixture_raw_file(monkeypatch, kb_dir, "raw/notes/gateway.example.net.md")
result = _invoke_new(monkeypatch, kb_dir, [ result = _invoke_new(monkeypatch, kb_dir, [
"new", "source", "--name", "gateway.example.net", "new", "source", "--name", "gateway.example.net",
"--set", "source_type=notes",
"--set", "raw_files=raw/notes/gateway.example.net.md", "--set", "raw_files=raw/notes/gateway.example.net.md",
"--set", "entities=aurora,Borealis", "--set", "entities=aurora,Borealis",
]) ])
assert result.exit_code == 0, result.output assert result.exit_code == 0, result.output
path = kb_dir / "sources/Source - gateway.example.net.md" # Gitea #66: `types/source.md` now declares a `layout:`, so `source_type:
# notes` lands in its area - the same placement rule an entity or concept
# already follows.
path = kb_dir / "sources/notes/Source - gateway.example.net.md"
assert path.exists() assert path.exists()
fm, body = read_page(path) fm, body = read_page(path)
assert fm["type"] == "types/source.md" assert fm["type"] == "types/source.md"
assert fm["entities"] == ["aurora", "Borealis"] assert fm["entities"] == ["aurora", "Borealis"]
assert fm["author"] == "Torben" # WIKI_AUTHOR override assert fm["author"] == "Torben" # WIKI_AUTHOR override
assert fm["source_type"] == "notes" # schema default assert fm["source_type"] == "notes"
assert "[[aurora]]" in body assert "[[aurora]]" in body
assert "[[Borealis]]" in body assert "[[Borealis]]" in body
def test_new_source_rejects_missing_source_type(monkeypatch, kb_dir):
"""Gitea #66: `source_type` lost its `default: notes` - `new` must refuse
rather than silently picking a value, and must not write a file or create
a directory while refusing."""
monkeypatch.setenv("WIKI_AUTHOR", "Torben") # isolate the refusal from the author check
_fixture_raw_file(monkeypatch, kb_dir, "raw/notes/gateway.example.net.md")
result = _invoke_new(monkeypatch, kb_dir, [
"new", "source", "--name", "no-source-type",
"--set", "raw_files=raw/notes/gateway.example.net.md",
])
assert result.exit_code != 0
assert "source_type" in result.output
# No page written anywhere under sources/ - not even into an area that
# legitimately pre-exists (the fixture wiki's own `sources/notes/`).
assert not list(kb_dir.glob("sources/**/Source - no-source-type.md"))
def test_new_source_author_falls_back_to_git_config(monkeypatch, kb_dir): def test_new_source_author_falls_back_to_git_config(monkeypatch, kb_dir):
"""No WIKI_AUTHOR set - default_author() falls back to `git config """No WIKI_AUTHOR set - default_author() falls back to `git config
user.name`, run with cwd=config.ROOT. user.name`, run with cwd=config.ROOT.
@@ -225,10 +249,11 @@ def test_new_source_author_falls_back_to_git_config(monkeypatch, kb_dir):
_fixture_raw_file(monkeypatch, kb_dir, "raw/notes/gateway.example.net.md") _fixture_raw_file(monkeypatch, kb_dir, "raw/notes/gateway.example.net.md")
result = _invoke_new(monkeypatch, kb_dir, [ result = _invoke_new(monkeypatch, kb_dir, [
"new", "source", "--name", "git-config-author", "new", "source", "--name", "git-config-author",
"--set", "source_type=notes",
"--set", "raw_files=raw/notes/gateway.example.net.md", "--set", "raw_files=raw/notes/gateway.example.net.md",
]) ])
assert result.exit_code == 0, result.output assert result.exit_code == 0, result.output
fm, _body = read_page(kb_dir / "sources/Source - git-config-author.md") fm, _body = read_page(kb_dir / "sources/notes/Source - git-config-author.md")
assert fm["author"] == "Fixture Author" assert fm["author"] == "Fixture Author"
@@ -336,6 +361,7 @@ def test_raw_files_error_points_at_the_comma_split(monkeypatch, kb_dir, raw_dir)
monkeypatch.setattr(config, "ROOT", kb_dir.parent) monkeypatch.setattr(config, "ROOT", kb_dir.parent)
result = _invoke_new(monkeypatch, kb_dir, [ result = _invoke_new(monkeypatch, kb_dir, [
"new", "source", "--name", "Split Path", "new", "source", "--name", "Split Path",
"--set", "source_type=notes",
"--set", "raw_files=raw/notes/Versioning, CI-CD.md", "--set", "raw_files=raw/notes/Versioning, CI-CD.md",
]) ])
assert result.exit_code == 1 assert result.exit_code == 1
@@ -358,5 +384,5 @@ def test_source_page_accepts_a_raw_file_whose_name_has_a_comma(monkeypatch, kb_d
"--set", "source_type=notes", "--set", "source_type=notes",
]) ])
assert result.exit_code == 0, result.output assert result.exit_code == 0, result.output
frontmatter, _ = read_page(kb_dir / "sources/Source - Comma Source.md") frontmatter, _ = read_page(kb_dir / "sources/notes/Source - Comma Source.md")
assert frontmatter["raw_files"] == ["raw/notes/Versioning, CI-CD.md"] assert frontmatter["raw_files"] == ["raw/notes/Versioning, CI-CD.md"]
+3 -2
View File
@@ -400,10 +400,11 @@ def test_new_source_with_multiple_raw_files(kb_dir, raw_dir, monkeypatch):
result = runner.invoke(app, [ result = runner.invoke(app, [
"new", "source", "--name", "Multi", "new", "source", "--name", "Multi",
"--set", "source_type=notes",
"--set", "raw_files=raw/notes/Aurora.md,raw/notes/Second.md", "--set", "raw_files=raw/notes/Aurora.md,raw/notes/Second.md",
]) ])
assert result.exit_code == 0, result.output assert result.exit_code == 0, result.output
fm, _body = read_page(kb_dir / "sources/Source - Multi.md") fm, _body = read_page(kb_dir / "sources/notes/Source - Multi.md")
assert fm["raw_files"] == ["raw/notes/Aurora.md", "raw/notes/Second.md"] assert fm["raw_files"] == ["raw/notes/Aurora.md", "raw/notes/Second.md"]
@@ -483,7 +484,7 @@ def test_lint_does_not_flag_source_page_self_citation(kb_dir, raw_dir, monkeypat
refs, block = _footnote_block(("Source - Aurora", "Aurora.md")) refs, block = _footnote_block(("Source - Aurora", "Aurora.md"))
write_page( write_page(
kb_dir / "sources/Source - Aurora.md", kb_dir / "sources/notes/Source - Aurora.md",
{ {
"type": "source", "source_type": "notes", "author": "Torben", "type": "source", "source_type": "notes", "author": "Torben",
"raw_files": ["raw/notes/Aurora.md"], "date": "2026-08-02", "raw_files": ["raw/notes/Aurora.md"], "date": "2026-08-02",
+4 -4
View File
@@ -82,7 +82,7 @@ def test_touch_uses_date_field_for_source_pages(touch_wiki):
"""Source pages declare `date:`, not `modified:` - the field comes from """Source pages declare `date:`, not `modified:` - the field comes from
the type's schema rather than a hardcoded name.""" the type's schema rather than a hardcoded name."""
_touch(page_title="Source - Aurora", date="2026-08-13") _touch(page_title="Source - Aurora", date="2026-08-13")
frontmatter, _ = read_page(touch_wiki / "sources/Source - Aurora.md") frontmatter, _ = read_page(touch_wiki / "sources/notes/Source - Aurora.md")
assert str(frontmatter["date"]) == "2026-08-13" assert str(frontmatter["date"]) == "2026-08-13"
assert "modified" not in frontmatter assert "modified" not in frontmatter
@@ -92,9 +92,9 @@ def test_touch_leaves_a_sources_publication_date_alone(touch_wiki):
record of when the page was last edited. Auto-bumping it to today replaced a record of when the page was last edited. Auto-bumping it to today replaced a
fact about the world and left the page contradicting the date printed in its fact about the world and left the page contradicting the date printed in its
own body - so it moves only on an explicit --date.""" own body - so it moves only on an explicit --date."""
before, _ = read_page(touch_wiki / "sources/Source - Aurora.md") before, _ = read_page(touch_wiki / "sources/notes/Source - Aurora.md")
_touch(page_title="Source - Aurora", summary="Neue Zusammenfassung") _touch(page_title="Source - Aurora", summary="Neue Zusammenfassung")
frontmatter, _ = read_page(touch_wiki / "sources/Source - Aurora.md") frontmatter, _ = read_page(touch_wiki / "sources/notes/Source - Aurora.md")
assert frontmatter["summary"] == "Neue Zusammenfassung" assert frontmatter["summary"] == "Neue Zusammenfassung"
assert str(frontmatter["date"]) == str(before["date"]) assert str(frontmatter["date"]) == str(before["date"])
@@ -221,7 +221,7 @@ def test_set_raw_files_accepts_an_existing_path_with_a_comma(touch_wiki, raw_dir
page_title="Source - Aurora", page_title="Source - Aurora",
set_fields=[r"raw_files=raw/notes/Versioning\, CI-CD.md"], set_fields=[r"raw_files=raw/notes/Versioning\, CI-CD.md"],
) )
frontmatter, _ = read_page(touch_wiki / "sources/Source - Aurora.md") frontmatter, _ = read_page(touch_wiki / "sources/notes/Source - Aurora.md")
assert frontmatter["raw_files"] == ["raw/notes/Versioning, CI-CD.md"] assert frontmatter["raw_files"] == ["raw/notes/Versioning, CI-CD.md"]
+30 -8
View File
@@ -108,13 +108,33 @@ def test_concept_layout_covers_every_declared_concept_type():
assert all(spec.get("title") for spec in layout.values()) assert all(spec.get("title") for spec in layout.values())
def test_source_layout_covers_every_declared_source_type():
"""Gitea #66: `source_type` had a silent `default: notes` that made the
collection lopsided (25 of 29 pages), which is what made #59 leave
`source` flat. Removing the default and reclassifying by what the pages
actually are turned it into six real areas - this is the concept-layout
test's counterpart for `source`, checking the same enum/layout agreement."""
layout = resolver.get_layout("types/source.md")
assert layout is not None
assert set(layout) == set(resolver.get_enum("types/source.md", "source_type"))
assert {key: spec["dir"] for key, spec in layout.items()} == {
"transcript": "transcripts",
"analysis": "analyses",
"article": "articles",
"document": "documents",
"notes": "notes",
"tracker": "trackers",
"unclassified": "unclassified",
}
assert all(spec.get("title") for spec in layout.values())
def test_get_layout_is_none_for_types_without_one(): def test_get_layout_is_none_for_types_without_one():
"""`comparison` has no subtype field at all; `source` has one and """`comparison` has no subtype field at all, so there is nothing a
deliberately declares no `layout:` anyway - 25 of its 29 pages carry the `layout:` could key on - the worked example for a type that stays flat
same `source_type`, so splitting on it would make one area and four because the axis itself doesn't exist (as opposed to `source` pre-#66,
splinters (Gitea #59). Having a subtype axis is not a reason to use it.""" which had the axis but a lopsided distribution - see #59)."""
assert resolver.get_layout("types/comparison.md") is None assert resolver.get_layout("types/comparison.md") is None
assert resolver.get_layout("types/source.md") is None
def test_get_layout_rejects_a_dir_with_a_path_separator(tmp_path): def test_get_layout_rejects_a_dir_with_a_path_separator(tmp_path):
@@ -262,7 +282,9 @@ def test_subtype_dir_falls_back_for_unmapped_subtype():
def test_subtype_dir_is_none_without_layout_or_subtype(): def test_subtype_dir_is_none_without_layout_or_subtype():
assert resolver.subtype_dir("types/source.md", "notes") is None # `comparison` has no `layout:` (and no `subtype_field:` to have one for)
# - the value passed is arbitrary, since the type has no subtype axis at all.
assert resolver.subtype_dir("types/comparison.md", "whatever") is None
assert resolver.subtype_dir("types/entity.md", None) is None assert resolver.subtype_dir("types/entity.md", None) is None
@@ -272,8 +294,8 @@ def test_compute_target_dir_applies_layout_subdirectory():
def test_compute_target_dir_is_flat_for_a_type_without_layout(): def test_compute_target_dir_is_flat_for_a_type_without_layout():
target = resolver.compute_target_dir("types/source.md", {"source_type": "notes"}) target = resolver.compute_target_dir("types/comparison.md", {})
assert target == config.KB_DIR / "sources" assert target == config.KB_DIR / "comparisons"
def test_compute_target_dir_resolves_against_repo_root_for_root_repo_types(): def test_compute_target_dir_resolves_against_repo_root_for_root_repo_types():
+2 -2
View File
@@ -426,7 +426,7 @@ def test_xref_remove_clears_an_undeclared_leftover_field(kb_dir):
page that already carries one is a dead end.""" page that already carries one is a dead end."""
from chemenu.frontmatter_io import write_page from chemenu.frontmatter_io import write_page
path = kb_dir / "sources/Source - Aurora.md" path = kb_dir / "sources/notes/Source - Aurora.md"
frontmatter, body = read_page(path) frontmatter, body = read_page(path)
frontmatter["related"] = ["aurora"] frontmatter["related"] = ["aurora"]
write_page(path, frontmatter, body) write_page(path, frontmatter, body)
@@ -472,7 +472,7 @@ def test_xref_link_source_is_idempotent_on_the_source_page(kb_dir):
def test_xref_link_source_dry_run_leaves_the_source_page_alone(kb_dir): def test_xref_link_source_dry_run_leaves_the_source_page_alone(kb_dir):
runner, app = _runner_env(kb_dir) runner, app = _runner_env(kb_dir)
path = kb_dir / "sources/Source - Aurora.md" path = kb_dir / "sources/notes/Source - Aurora.md"
before = path.read_text(encoding="utf-8") before = path.read_text(encoding="utf-8")
runner.invoke( runner.invoke(
app, app,
+10 -1
View File
@@ -7,6 +7,14 @@ subtype_field: source_type
base_dir: sources base_dir: sources
title_prefix: "Source - " title_prefix: "Source - "
page_ref_fields: [entities, concepts] page_ref_fields: [entities, concepts]
layout:
transcript: {dir: transcripts, title: Transkripte}
analysis: {dir: analyses, title: Analysen}
article: {dir: articles, title: Artikel}
document: {dir: documents, title: Dokumente}
notes: {dir: notes, title: Notizen}
tracker: {dir: trackers, title: Tracker-Exporte}
unclassified: {dir: unclassified, title: Unklassifiziert}
--- ---
# Source # Source
@@ -31,7 +39,7 @@ page_ref_fields: [entities, concepts]
| Feld | Pflicht | Verwendung | | Feld | Pflicht | Verwendung |
|---|---:|---| |---|---:|---|
| `type` | Ja | `types/source.md` | | `type` | Ja | `types/source.md` |
| `source_type` | Ja | Eines von: article, document, notes, spec, image | | `source_type` | Ja | Eines von: transcript, analysis, article, document, notes, tracker, unclassified - kein Default, siehe unten |
| `author` | Ja | Urheber des Quellmaterials | | `author` | Ja | Urheber des Quellmaterials |
| `raw_files` | Ja | Raw-Dateipfade, die diese Quelle **besitzt** - siehe "Eine Raw-Datei, ein Besitzer" unten | | `raw_files` | Ja | Raw-Dateipfade, die diese Quelle **besitzt** - siehe "Eine Raw-Datei, ein Besitzer" unten |
| `source_url` | Nein | Ursprungs-URL bei externen Quellen | | `source_url` | Nein | Ursprungs-URL bei externen Quellen |
@@ -45,6 +53,7 @@ page_ref_fields: [entities, concepts]
## Autorenanweisungen ## Autorenanweisungen
- Der Titel beginnt mit "Source - ", gefolgt vom Namen der Quelle - Der Titel beginnt mit "Source - ", gefolgt vom Namen der Quelle
- `source_type` hat **keinen Default** - `wikitool new source` verweigert ohne einen expliziten Wert. Ist die Kategorie unklar, `unclassified` setzen statt zu raten; das ist ein sichtbares Katalogfach mit beratendem `lint`-Befund, kein Sammelbecken. Was `analysis` von `document` trennt und welche Area welchen Wert hält: [kb/sources/COLLECTION.md](../kb/sources/COLLECTION.md)
- `raw_files` listet jede Raw-Datei, die diese Quelle abdeckt (eine Source-Seite pro logischer Quelle, nicht pro Datei) - `raw_files` listet jede Raw-Datei, die diese Quelle abdeckt (eine Source-Seite pro logischer Quelle, nicht pro Datei)
- Bei externen Artikeln immer `source_url` auf die Ursprungs-URL setzen - Bei externen Artikeln immer `source_url` auf die Ursprungs-URL setzen
- `source_language` auf die Sprache des Rohmaterials setzen, nicht auf die der Seite - `source_language` auf die Sprache des Rohmaterials setzen, nicht auf die der Seite
+6 -3
View File
@@ -7,9 +7,12 @@ properties:
description: Must reference the source type-spec description: Must reference the source type-spec
source_type: source_type:
type: string type: string
enum: [article, document, notes, spec, image] enum: [transcript, analysis, article, document, notes, tracker, unclassified]
default: notes description: >-
description: The category of source material The category of source material. No default - the machine must not pick
the vaguest value on the author's behalf (Gitea #66). Use `unclassified`
when the category is genuinely unclear; it is a visible, advisory-lint
catalog slot, not a silent fallback.
author: author:
type: string type: string
description: Author of the source material description: Author of the source material
+20 -6
View File
@@ -102,12 +102,26 @@ under `instructions/`, outside the `raw/` -> `kb/` provenance rules entirely.
`layout` is what turns a subtype field into areas, and it is optional in both directions on `layout` is what turns a subtype field into areas, and it is optional in both directions on
purpose. Declaring one makes every instance land in a directory named by its subtype and gives purpose. Declaring one makes every instance land in a directory named by its subtype and gives
that directory its index title; leaving it off keeps the collection flat, however many subtypes that directory its index title; leaving it off keeps the collection flat, however many subtypes
the schema allows. The choice is whether the split *helps* - the catalog shards per area, so the schema allows (`comparison` is the worked example - it has no `subtype_field` at all, so
areas are how a large collection stays readable, but a subtype whose values are lopsided there is nothing for a `layout` to key on). The choice for a type that *does* carry a subtype
produces one big area and a handful of splinters and is better left flat (`source` is the worked field is whether the split *helps*: the catalog shards per area, so areas are how a large
example, `concept` the opposite one). `wikitool lint` will say which case a collection is in collection stays readable, but a field whose values are lopsided - one dominant value plus a
once it grows past the shard threshold; a `dir:` must be a single path segment, because an area handful of rare ones - would produce one big area and a scatter of splinters, which is not an
is as deep as a page goes. improvement. `wikitool lint`'s `unsharded_collections` finding says which case a collection is
in once it grows past the shard threshold, and whether a `layout:` is already declared for the
split it recommends.
A lopsided field is a reason to fix the field, not a reason to leave `layout` off forever -
`source` was exactly this case (Gitea #66): 25 of 29 pages carried one value because the schema
handed out that value as a *default* whenever nobody chose one, not because the material was
genuinely that uniform. Once the default was removed and the pages reclassified by what they
actually were, the field split into six areas with none of them small. Declare `layout` for
*every* enum value once it does: a value missing from it still gets a directory (`subtype_dir`
falls back to naively pluralizing the value's own name), but that directory carries no title in
`wiki/index.md`, which is a silent gap rather than a deliberate flat collection. Leaving a whole
type's `layout` off is for the case in the paragraph above - no subtype field to key on at all
- not for a subtype field one has simply not gotten around to mapping. A `dir:` must be a single
path segment, because an area is as deep as a page goes.
A type-spec **without `base_dir` is a contract only** and cannot be instantiated; A type-spec **without `base_dir` is a contract only** and cannot be instantiated;
`wikitool new <name>` refuses it. `lint-report` is the worked example: its artifacts are `wikitool new <name>` refuses it. `lint-report` is the worked example: its artifacts are
+35
View File
@@ -0,0 +1,35 @@
# Workshop: reclassify-source-types
- **Run key:** `reclassify-source-types` (this directory's name - there is no other identifier)
- **Input:** none - this run is not an ingest
- **Started:** 2026-09-08
- **Session id form:** `WIKITOOL_SESSION_ID="reclassify-source-types/u<N>"`, one per unit
## Goal
Reclassify the 22 `kb/sources/` pages that were catalogued as `source_type: notes` only
because the schema's `default: notes` picked that value whenever nobody chose one (Gitea #66),
then move every source page into the area its real `source_type` computes, and verify nothing
else moved. This is the corpus half of #66 - the code half (schema, `layout:`, lint finding,
tests, prose) is already published.
## Closes when
- All 22 pages listed in `plan.md`'s unit are reclassified to their real `source_type`.
- `wikitool move --reconcile` has placed every source page in its computed area.
- `wikitool index rebuild` has regenerated `kb/sources/INDEX.md` with the new areas.
- `wikitool migrate verify --from HEAD` reports `added == 0, removed == 0` for every source page
(only `moved` and `modified`, per Gitea #66's acceptance criteria).
- `wikitool lint` is green: no misplaced or nested source pages, and the expected distribution
(transcript 16, analysis 4, article 3, notes 3, tracker 2, document 1, unclassified 0) holds.
- The changeset is published via `wikitool publish`.
## Checklist
- [ ] u1 reclassify - `touch --set source_type=<value>` on all 22 pages, `move --reconcile`,
`index rebuild`, `migrate verify --from HEAD`, `lint`, publish
## Open decisions
- None. The mapping (file -> value) was fixed and checked against the tree while preparing
Gitea #66's issue body; see `plan.md`.
+63
View File
@@ -0,0 +1,63 @@
# Plan: reclassify-source-types
Cut the work into units. One unit is one session id and one `publish`, so it has to fit inside
the 60-call iteration budget on its own - count the `wikitool` calls the unit needs before
committing to its size.
One unit is enough: 22 `touch` calls + `move --reconcile` + `index rebuild` +
`migrate verify --from HEAD` + `lint` is ~26 calls, well under the budget.
## u1 - reclassify all 22 lopsided pages, then place and verify
**Job:** `wikitool touch --page "<title>" --set source_type=<value>` for every row below whose
`New` column differs from `Old`, then `wikitool move --reconcile`, `wikitool index rebuild`,
`wikitool migrate verify --from HEAD --fail-on-error`, `wikitool lint --fail-on-error`.
**Done when:** every row's page carries its `New` value, every source page sits under the area
its `source_type` computes, `migrate verify` reports zero added/removed, and `lint` is green.
The mapping was fixed by reading each page's title, `author:` and its raw source while preparing
Gitea #66's issue body, not derived mechanically - each row is still checked against the actual
page before its `touch`, per AGENTS.md invariant 3 (nothing here is filed sight-unseen).
| # | Page | Old | New |
|---|------|-----|-----|
| 1 | Source - AMD Powermanagement CPU | article | article (unchanged) |
| 2 | Source - Arch Linux Cheat Sheet | notes | notes (unchanged) |
| 3 | Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04 | notes | transcript |
| 4 | Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31 | notes | transcript |
| 5 | Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31 | notes | transcript |
| 6 | Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31 | notes | transcript |
| 7 | Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31 | notes | transcript |
| 8 | Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31 | notes | transcript |
| 9 | Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31 | notes | transcript |
| 10 | Source - Conversation - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31 | notes | transcript |
| 11 | Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31 | notes | transcript |
| 12 | Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30 | notes | transcript |
| 13 | Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31 | notes | transcript |
| 14 | Source - Copilot Skill Restructure Instructions | notes | analysis |
| 15 | Source - Docker Cheatsheet | notes | notes (unchanged) |
| 16 | Source - Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02 | notes | tracker |
| 17 | Source - Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04 | notes | tracker |
| 18 | Source - LLM Improvements Codex Analysis | notes | analysis |
| 19 | Source - LLM Improvements Production Agent Gaps 2026 | notes | analysis |
| 20 | Source - LLM Improvements Sonnet Analysis | notes | analysis |
| 21 | Source - LLM Wiki Pattern | article | article (unchanged) |
| 22 | Source - LLM Wiki v2 | article | article (unchanged) |
| 23 | Source - MCP Read Server Implementation Session 2026-09-02 | notes | transcript |
| 24 | Source - Private-Instance Merge Correction and Issue 30 Session 2026-09-01 | notes | transcript |
| 25 | Source - Public Release, Corpus Purge and History Squash Session 2026-09-01 | notes | transcript |
| 26 | Source - Publish-Remote Gate and Issue Triage Session 2026-09-01 | notes | transcript |
| 27 | Source - qmd - GitHub Repository | document | document (unchanged) |
| 28 | Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02 | notes | transcript |
| 29 | Source - Wine | notes | notes (unchanged) |
Expected end distribution: transcript 16, analysis 4, article 3, notes 3, tracker 2, document 1,
unclassified 0 - matches Gitea #66's acceptance criteria.
## Deliberately excluded from this run
- `fidelity`/`authority` backfill (Gitea #67) - separate schema fields, separate issue, will run
its own sweep over the same 31 pages later.
- `raw/CONTRACT.md`'s routing table (also #67) - not touched here.
- Any page outside `kb/sources/` - this run is a `source_type` reclassification only.