source_type ist Instanzsache: Profilkatalog, Setup-Frage, evolve-subtypes-Instruction (schliesst #68)
CI / verify (push) Successful in 52s
Release / release (push) Successful in 34s

Files changed:
- CHANGES.md
- VERSION
- instructions/evolve-subtypes.md
- instructions/kb-profiles.md
- instructions/setup-instance.md
- kb/sources/COLLECTION.md
This commit is contained in:
2026-09-09 07:50:18 +02:00
parent 46dfee0ea9
commit 6b300aa782
6 changed files with 211 additions and 3 deletions
+53 -1
View File
@@ -35,7 +35,7 @@ dev-checkout concern - readable here, never shipped as something to parse.
--- ---
## 4.8.0-beta.8 - 2026-09-08 - raw accept: Datums-Shard statt Typverzeichnis, fidelity/authority am Drop-Punkt (schliesst #67) ## 4.8.0-beta.9 - 2026-09-09 - source_type ist Instanzsache: Profilkatalog, Setup-Frage, evolve-subtypes-Instruction (#68)
**Author:** Torben Nehmer **Author:** Torben Nehmer
@@ -49,6 +49,7 @@ dev-checkout concern - readable here, never shipped as something to parse.
- 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) - source_type: Default streichen, unclassified als sichtbares Fach, layout: fuer source (schliesst #66)
- raw accept: Datums-Shard statt Typverzeichnis, fidelity/authority am Drop-Punkt (schliesst #67) - raw accept: Datums-Shard statt Typverzeichnis, fidelity/authority am Drop-Punkt (schliesst #67)
- source_type ist Instanzsache: Profilkatalog, Setup-Frage, evolve-subtypes-Instruction (#68)
<!-- /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
@@ -527,6 +528,57 @@ hochgestuft, nur damit der Report leiser wird.
Schließt #67. Schließt #67.
**`source_type` ist Instanzsache: Profilkatalog, Setup-Frage, `evolve-subtypes`-Instruction**
(#68, Paket C von vier — A ist #66, B ist #67, D ist #69): reine Doku- und Instruction-Arbeit,
kein Korpus-Sweep.
Befund: `source_type`s sieben Werte (`transcript`, `analysis`, `article`, `document`, `notes`,
`tracker`, `unclassified`) beschreiben *diese* Instanz, nicht den Stack — gegen drei
hypothetische Zielinstanzen (Handball-Verein, Produktentwicklung, Pen-&-Paper) hat die Liste
fast nichts gemeinsam, während `fidelity`/`authority` (#67) in allen vieren dieselben Werte
bleiben. Architektonisch war das längst wahr (`types/source.md` trägt `root: kb`, `dist export`
liefert es nur als `.template`), nur stellte nichts die Frage: `instructions/kb-profiles.md`
riet im `entities`-Abschnitt „Adapt the area list first", sagte im `sources`-Abschnitt aber kein
Wort zu `source_type`. Zweiter Befund, aus #66 mitgenommen: das `unclassified`-Fach bekam einen
beratenden `lint`-Befund, aber nie eine Prozedur, es wieder zu leeren.
Umgesetzt:
- `kb-profiles.md`s `sources`-Abschnitt behandelt `source_type` jetzt wie `entities` seine Area-
Liste: als das, was zuerst anzupassen ist, mit zwei ausformulierten Domänenprofilen
(Handball-Verein, Pen-&-Paper) als Anschauung, und dem ausdrücklichen Gegenbeispiel
`fidelity`/`authority` — die sind Stack-Vokabular und stehen nicht zur Wahl.
- `instructions/setup-instance.md` Schritt 5 bekommt einen neuen Unterschritt: nach dem
Anwendungsgebiet fragen, `source_type`-Vorschlag ableiten, Enum und `layout:` in derselben
Bearbeitung setzen. Mit der Ansage, dass der Betreiber zum Setup-Zeitpunkt null Quellen hat und
seine Taxonomie vor jedem Material rät — das Ergebnis ist ein Startpunkt, keine Festlegung, und
`unclassified` bleibt in jedem Vorschlag erhalten.
- Neue Instruction `instructions/evolve-subtypes.md`, `manual: true`: benennt die
Weiterentwicklungsschleife, die werkzeugseitig schon vollständig existierte (Fach sehen →
Wert samt `layout:` ergänzen → `touch`/`move --reconcile``index rebuild`/`migrate verify`),
über alle drei Subtype-Achsen (`entity_type`, `concept_type`, `source_type` — alle drei tragen
`subtype_field:` **und** `layout:`; `comparison` keins von beidem). Zwei Regeln im Body: Wert
und Sweep sind untrennbar (ein deklarierter Wert ohne Seite lädt zum Raten ein — genau der
`notes`-Fall aus #66), und eine Aufnahmeschwelle von ≥3 Seiten, mit `spec`/`image` aus #66 als
Gegenbeispiel und einer benannten-Ausnahme-Klausel für Fälle wie `tracker` bei zwei Seiten.
`manual: true` verhindert, dass eine Taxonomie-Änderung in einen laufenden Ingest hineinstolpert
— erwähnt aus `kb-profiles.md`, `setup-instance.md` und `kb/sources/COLLECTION.md`, aus keinem
Skill, keiner AGENTS.md, keiner CLAUDE.md verlinkt.
- `kb/sources/COLLECTION.md` benennt `evolve-subtypes.md` an der `unclassified/`-Zeile.
Die vom Vorbereitungs-Body übernommene, ursprünglich vierte Maßnahme entfiel: die
`corpus-policy.md`-Floor-Ausnahme für `unclassified` steht dort bereits seit #66.
**MINOR**, geprüft gegen den Drop-in-Test: eine Instanz kopiert `instructions/` und `types/`
über sich, nichts wird umbenannt oder entfernt, kein Kommando, kein Flag, kein
maschinengelesenes Format. Kein `--breaking`, kein Migrationsdokument. `4.8.0-beta.9` desselben
Kandidaten.
Geändert: `instructions/kb-profiles.md`, `instructions/setup-instance.md`,
`instructions/evolve-subtypes.md` (neu), `kb/sources/COLLECTION.md`.
Schließt #68.
--- ---
## 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.8 4.8.0-beta.9
+114
View File
@@ -0,0 +1,114 @@
---
type: types/instruction.md
name: evolve-subtypes
description: Extend or drain a page type's subtype vocabulary - entity_type, concept_type, or source_type - once real material has outgrown it, and the invariants that keep the resulting values honest.
manual: true
---
# Extend a subtype vocabulary, or drain its catch-all
A subtype field (`entity_type`, `concept_type`, `source_type`) partitions one page type into
areas via that type-spec's `layout:` - `types/type-spec.md` has the anatomy. Every one of these
three enums is instance-owned content, not stack vocabulary: `entity.md`, `concept.md` and
`source.md` all carry `root: kb` and ship only as `.template`, so an instance's own list of
values is exactly as much its own decision as its collection contracts are
([kb-profiles.md](kb-profiles.md) is the palette that seeds it). This instruction is the
procedure for changing that list once it is running, not for choosing it the first time -
[setup-instance.md](setup-instance.md) does that.
The tooling for this loop already exists end to end; this file only names the sequence and the
two rules that keep it from repeating what created `kb/sources/`'s old `notes` catch-all in the
first place (Gitea #66): a schema `default:` that the compiler applied whenever nobody
disagreed, silently turning the least specific value into the collection point for everything
unclear.
## When to run
- A `wikitool lint` advisory finding reports pages sitting in a subtype's catch-all value (for
`source`, that is `unclassified` - visible in the catalog, carrying no default) and there are
now enough of them to warrant a real value.
- A real ingest keeps producing pages that do not fit any existing value for a subtype field,
and forcing them into the nearest existing one would misclassify them.
- The catch-all itself needs draining after a value was added, so it does not become a second,
quieter collection point.
Not for renaming or removing a value that pages already carry under - that moves pages and is a
corpus migration ([migrate-corpus.md](migrate-corpus.md)), not this loop. Not for the one-time
choice of an instance's starting vocabulary - that is
[setup-instance.md](setup-instance.md)'s KB-language step, seeded from
[kb-profiles.md](kb-profiles.md).
## Steps
1. **See what has actually collected in the catch-all**, before touching anything:
```bash
tools/wikitool lint
tools/wikitool search --field source_type=unclassified # or the equivalent <x>_type
```
Read every page the search returns. A count alone does not say whether the pages share one
real category or three - that judgment is the reason this step exists rather than being
folded into the next one.
2. **Apply the value-and-sweep rule: a new value is added and populated in the same pass, never
one without the other.** A declared value that no page carries yet is a category that invites
a guess the next time someone has to pick between it and the catch-all - which is exactly how
the old `notes` default absorbed 22 of 29 source pages before anyone noticed. So:
1. Count real candidates first: `tools/wikitool search --field <x>_type=<candidate-guess>`
will find nothing yet, so count by reading the catch-all's pages from step 1 instead.
2. **Apply the ≥3-page admission threshold.** A value is admitted *after* it has proven
itself against real material, never in expectation of some. `spec` and `image` are the
cautionary case: both were added to `source_type` ahead of any matching page, both sat at
zero for a year, and both were removed in Gitea #66. A smaller count is only ever an
operator's explicit, named exception (`tracker` at two pages in #66, kept because the
corpus was expected to grow into it from ongoing issue ingests) - never a reason to lower
the threshold itself.
3. Add the enum value in the type-spec's schema (`types/<t>.schema.yaml`) and its `layout:`
entry (`types/<t>.md`) in the same edit - a value with no `layout:` line has nowhere to be
moved to.
4. Reclassify every candidate page in the same pass:
```bash
tools/wikitool touch --page "<Title>" --set <x>_type=<new-value>
tools/wikitool move --reconcile
```
5. Rebuild and check:
```bash
tools/wikitool index rebuild
tools/wikitool migrate verify --from HEAD --fail-on-error
tools/wikitool lint --fail-on-error
```
`migrate verify` on a subtype sweep should report moved pages and zero findings - a
`<x>_type` change alone touches no wikilink, citation, footnote or H1.
3. **Draining the catch-all is the same loop, run without step 2.2's threshold** - a page
sitting in `unclassified` (or the equivalent) already has an intended home; the only question
is which existing value it belongs to, which step 1's read-through already answered. Skip
straight to reclassifying it (step 2.4) and rebuilding (step 2.5).
4. **Record it** with `tools/wikitool log append`, describing what moved and why, the same way
any other corpus change is logged.
## Decision points
- **The catch-all is empty and lint reports nothing?** Nothing to do - an empty catch-all is the
success state, not a problem this instruction exists to fix.
- **A candidate page could plausibly fit two existing values?** Resolve it by rereading the
collection's `COLLECTION.md` for the distinguishing rule (for `sources`, authorship decides
`analysis` vs. `document`) before inventing a third value - a genuine gap in the existing
values is rarer than an under-read contract.
- **More than one subtype field needs the same treatment?** Run this loop once per field; do not
try to batch an `entity_type` change and a `source_type` change into one pass, since their
admission thresholds are independent judgments about unrelated material.
## Scope
Covers `entity_type`, `concept_type` and `source_type` - the three subtype fields with both
`subtype_field:` and `layout:` declared. `comparison` has neither and is out of scope by
construction. Does not cover the stack-owned capture fields `fidelity`/`authority` on `source`
pages: those are fixed vocabulary the stack defines, not an instance's taxonomy - see
`types/source.md`.
+24
View File
@@ -152,6 +152,30 @@ against.
Not optional in the way the others are. An instance may rewrite its authoring rules and may not Not optional in the way the others are. An instance may rewrite its authoring rules and may not
rename or drop it. rename or drop it.
**`source_type` is a palette too, and the part most likely to be wrong for another domain -
adapt its value list first**, the same way `entities`' area list is called out above. This
repo's own list (`transcript, analysis, article, document, notes, tracker, unclassified`)
describes *what a private-projects instance ingests*; it says nothing about what a source is in
a different domain. Two worked lists, to show how little the values carry over:
| Instance | Plausible `source_type` values |
|---|---|
| Handball club and federation | `satzung` (bylaws), `protokoll` (minutes), `korrespondenz`, `spielbericht` (match report), `verbandsmitteilung` |
| Tabletop game master | `regelwerk` (rulebook), `abenteuermodul` (module), `sessionlog`, `handout`, `weltenbau` (worldbuilding) |
Adopting one means copying the value list into `types/source.schema.yaml`'s enum and giving each
value a `layout:` line in `types/source.md` - the same "copy the text in, do not point at this
page" rule as every other profile here. Keep the visible catch-all value (`unclassified` above)
in whatever list is adopted: a subtype field without one silently reintroduces the old
`default:`-driven collection point that Gitea #66 removed the moment nobody names an edge case.
Growing the list later, or draining the catch-all, is
[evolve-subtypes.md](evolve-subtypes.md).
**Not up for choice: `fidelity` and `authority`.** Unlike `source_type`, these two capture
fields are stack vocabulary - `types/source.md`'s `capture_fields:` - because they held the same
few values across every domain this catalogue tried, where `source_type` did not. An instance
adapts the *value list* above; it does not touch `fidelity`'s or `authority`'s enums.
### `comparisons` ### `comparisons`
Structured head-to-head evaluations of two or more things that already have pages. Structured head-to-head evaluations of two or more things that already have pages.
+18
View File
@@ -100,6 +100,24 @@ bereit für den ersten `Ingest`.
durch das eigene Vokabular ersetzen - sie ist Material des deutschen Profils, nicht des durch das eigene Vokabular ersetzen - sie ist Material des deutschen Profils, nicht des
Stacks. Stacks.
5. Den Nutzer nach dem Anwendungsgebiet fragen und daraus einen `source_type`-Vorschlag
ableiten. [kb-profiles.md](kb-profiles.md) hält dafür zwei ausformulierte Domänenprofile
als Anschauung bereit, neben dem Wert, den dieses Repo selbst nutzt. Der Vorschlag ist ein
**Startpunkt, keine Festlegung** - zum Setup-Zeitpunkt hat der Betreiber null Quellen und
rät seine Taxonomie, bevor er auch nur eine Datei gesehen hat, und das ist der
schlechteste Moment, ein Enum festzuzurren. Vorschlag umgesetzt heißt: das Enum in
`types/source.schema.yaml` **und** die passende `layout:`-Zeile je Wert in
`types/source.md` in derselben Bearbeitung setzen - eine ohne die andere lässt einen Wert
ohne Zielverzeichnis zurück. Der sichtbare Auffangwert (`unclassified`) bleibt in jedem
Vorschlag erhalten; er ist kein Sammelbecken, sondern das Fach für eine Quelle, deren
Kategorie noch nicht feststeht. Die Liste später erweitern oder das Fach leeren:
[evolve-subtypes.md](evolve-subtypes.md) - nicht Teil dieses Schritts, aber der Weg dahin,
sobald echtes Material vorliegt.
**Unverändert lassen:** `fidelity` und `authority` auf `source`-Seiten. Die sind
Stack-Vokabular, keine Instanzentscheidung - [kb-profiles.md](kb-profiles.md) sagt das im
selben Abschnitt.
**Vor dem ersten Ingest entscheiden.** Die `sections:`-Namen in `kb/CONVENTIONS.md` sind die **Vor dem ersten Ingest entscheiden.** Die `sections:`-Namen in `kb/CONVENTIONS.md` sind die
Überschriften, die `xref` und `cite` in jede Seite schreiben; sie danach zu ändern ist eine Überschriften, die `xref` und `cite` in jede Seite schreiben; sie danach zu ändern ist eine
Migration jeder vorhandenen Seite (`section_aliases:` trägt die alten Namen, siehe Migration jeder vorhandenen Seite (`section_aliases:` trägt die alten Namen, siehe
+1 -1
View File
@@ -37,7 +37,7 @@ Default** (Gitea #66): `wikitool new source` verweigert ohne einen expliziten We
| `documents/` | Eingelesene Dokumente, Handbücher, Spezifikationen | | `documents/` | Eingelesene Dokumente, Handbücher, Spezifikationen |
| `notes/` | Echte eigene Notizen ohne Dialogform - Cheat Sheets, Merkzettel | | `notes/` | Echte eigene Notizen ohne Dialogform - Cheat Sheets, Merkzettel |
| `trackers/` | Exporte aus einem Issue-Tracker oder vergleichbaren System | | `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 | | `unclassified/` | Sichtbares Fach für eine Quelle, deren Kategorie noch nicht feststeht - beratender `lint`-Befund, kein Sammelbecken. Es wieder zu leeren, oder das Enum um einen neuen Wert zu erweitern: [instructions/evolve-subtypes.md](../../instructions/evolve-subtypes.md) |
Das sind Areas, keine Collections: sie erben diesen Contract und tragen keine eigene 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 `COLLECTION.md`. Die Zuordnung trifft niemand von Hand - sie steht als `layout:` in