Anleitungsprosa aus dem Seiten-Type-Spec herausloesen: guidance stackeigen, Type-Spec bleibt instanzeigen #104
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Umgesetzt und veröffentlicht in
d49513b(Mechanik, Inhalt, Migration, Doku-Durchzug) und6eb3f84(Nachzug README-Typenbaum unddocs/language-boundaries.md), Version6.0.0-beta.6.Befund
Ein
root: kbType-Spec (types/entity.md,concept,source,comparison) hatte zweiPublika in einer Datei: Anleitungsprosa für den Agenten, der eine Seite schreibt, und
Seitenmaterial (
## Template-Block,layout:-Titel), das wörtlich zu Seitentext wird.Ownership gilt aber pro Datei (
chemenu/ownership.py,dist_cmd._plan_types()): weil dieSeitenhälfte instanzeigen sein muss, wurde die ganze Datei als
types/<name>.md.templateausgeliefert und nach der Adoption nie wieder angefasst.
Die Folge war still. Eine Instanz, die ihre Type-Specs beim Setup adoptiert hatte, bekam nie
wieder eine Verbesserung der Anleitungsprosa -
dist upgradeschrieb das.templateneben dieadoptierte Datei, nie die Datei selbst. Nichts brach, nichts meldete es; die Instanz las bis in
alle Zukunft die Anleitung vom Tag ihrer Erzeugung.
Welche Hälfte am Stack hing, war umgekehrt zur ersten Fassung dieses Issues. Gegen den Baum
geprüft:
instructions/setup-instance.mdSchritt 5.5 undinstructions/evolve-subtypes.mdSchritt 3weisen die Instanz an, den Enum in
types/<t>.schema.yamlund den passendenlayout:-Eintrag intypes/<t>.mdin derselben Änderung zu setzen. Dielayout:-Schlüsselsind die Enum-Werte dieser Instanz,
dir:sind ihre Areas,title_prefix: "Source - "istSeitentext.
type: types/<name>.md. Die Datei, die diesen Namenbehält, ist die, auf die der ganze Korpus zeigt.
types/source.mderklärte Capture-Fields,
raw accept --replaces, "one raw file, one owner" und die Begründungfür den Nicht-übernommen-Abschnitt.
instructions/ingest-large-tree.md- stackeigen, verbatimausgeliefert - zitiert diese Regel per
tools/wikitool types describe source: eine stackeigeneInstruktion hing an Prosa, die in einer instanzeigenen Datei stand.
Also nicht: Type-Spec zum Stack, Seitenmaterial heraus. Sondern: der Type-Spec blieb, wo er
war, und die Anleitungsprosa ist ausgezogen.
Entscheidung (umgesetzt)
Die vier offenen Designfragen wurden vor dem ersten Commit entschieden (Betreiber, 2026-09-15).
Wo lebt die stackeigene Hälfte, und in welcher Form? Eine Geschwisterdatei
types/<name>.guidance.mduntertypes/: stackeigen, verbatim ausgeliefert, englisch.Verknüpft über ein optionales
guidance:-Feld im Frontmatter des Type-Specs (repo-relativerPfad, wie
schema:), nicht über eine Namenskonvention - eine Konvention lieferte die Guidancesofort, aber doppelt, solange die adoptierte Datei die alte Prosa noch trägt. Sie hat einen
eigenen, nicht instanziierbaren Typ
types/type-guidance.md(keinbase_dir, wielint-report).tools/wikitool types describesetzt beide Hälften zusammen, der Agent machtweiter einen Aufruf.
Der Template-Pfad hat sich gar nicht bewegt:
type_resolver.extract_template()liestweiter den ersten ```markdown-Block aus
types/<name>.md.wikitool newhat keinen zweitenLadepfad bekommen, weil es seinen ersten behalten hat.
Verworfen: Guidance als Manual-Instruktion unter
instructions/- spart die neue Dateiart,kostet aber den zweiten Hop.
Was passiert mit den
layout:-Titeln? Sie sind geblieben, wo sie waren. Die Frage hat sichaufgelöst: geteilt wurde nur der Body, die Datei mit dem Frontmatter bleibt bei der Instanz.
Ein Typ, den eine Instanz komplett selbst schreibt?
guidance:ist optional; fehlt es,gibt es keine Stack-Hälfte und
describedruckt wie bisher nur den Body.Einmaliger Grenzübertritt oder Deprecation-Fenster? Keins von beidem - kein
Grenzübertritt. Drop-in in beide Richtungen, also
--minor. Die einmalige Adoption in einerbestehenden Instanz trägt ein Migrationsdokument mit
obligation: offered- der erste Gebrauchdieses Mechanismus, den
instructions/CONTRACT.mdseit 4.0.0 beschreibt und den bis hierherkein Dokument benutzt hat.
Schnittregel für die vier Bodies: Ein Satz, der wahr bleibt, wenn die Instanz ihre Subtypen
umbenennt, ihren Enum ändert oder ihr Template neu schreibt, gehört in die Guidance-Datei. Ein
Satz, der die Enum-Werte, Areas, Verzeichnisse, Überschriften oder Templatetexte dieser Instanz
benennt, bleibt im Type-Spec. Eine Ausnahme, die beim Aufteilen aufgefallen ist:
types/source.mdbehält den Bullet "The title starts with 'Source - '", weil er den instanzeigenen
title_prefix:-Wert wörtlich zitiert - eine andere Instanz wählt dort einen anderen Wert oderkeinen.
Was gebaut wurde
Mechanik
types/type-guidance.md+types/type-guidance.schema.yaml: stackeigener, nichtinstanziierbarer Typ.
types/type-spec.md: optionalesguidance:-Feld dokumentiert (§ Required Frontmatter);§§ "Who owns a type-spec" und "Anatomy of a type" auf den neuen Schnitt umgeschrieben - letzteres
sagt jetzt "at least two files, and a
root: kbtype may be three".type_resolver.get_guidance(): lädt die verlinkte Datei über denselbenload_type_spec-Pfad wieschema:, gibtNonezurück, wenn keinguidance:deklariert ist.types_core.describe_type(): neue Schlüsselguidanceundguidance_path;bodybehält seineBedeutung (additiv, der MCP-Wire-Contract bleibt für ältere Clients lesbar).
commands/types_cmd.py: rendert die Guidance-Hälfte vor dem Body, TOC-Region aus beidengestrippt.
dist_cmd._owned_type_stem(): ein gemeinsames Prädikat für_plan_types()undfind_leaks(). Beide rechneten vorhername.split(".", 1)[0]und hättenentity.guidance.mdals Stamm "entity" gelesen - die eine hätte sie als
.templateausgeliefert, die andere sie alsLeak gemeldet. Jetzt prüft eine Funktion die exakte Endung (
<stem>.mdoder<stem>.schema.yaml).Inhalt
types/entity.guidance.md,concept.guidance.md,source.guidance.md,comparison.guidance.md; die vier Type-Specs sind auf Frontmatter-Tabelle,## Templateundeinen Zeiger auf ihre Guidance-Datei zusammengeschnitten und tragen
guidance:.instructions/migrations/6.0.0-type-guidance-split.md,obligation: offered,migration_kind: assisted.Doku-Durchzug:
AGENTS.md§ File naming (neue Zeile fürtypes/<name>.guidance.md),types/type-spec.md,docs/ownership-and-templates.md(§ "Where the file boundary strains" →"Where the file boundary used to strain", beschreibt jetzt die Entscheidung statt eines Defekts),
tools/CONTRACT.md(types describe-Zeile),instructions/setup-instance.mdSchritt 5.1,README.md(Typenbaum),docs/language-boundaries.md(§ "Where the line runs inside one file" →"Where the line runs around a page type" - die Sprachachse hat sich nicht bewegt, die Dateigrenze
schon).
Akzeptanzkriterien
dist exportlieferttypes/<name>.guidance.mdverbatim aus, währendtypes/<name>.mdundtypes/<name>.schema.yamlweiter.templatetragen;find_leaks()meldet die Guidance-Dateinicht. (
test_guidance_file_ships_verbatim_beside_a_templated_type_spec, plustest_find_leaks_is_silent_on_a_clean_plan, dessen Fixture jetzt eine Guidance-Datei enthältund damit genau diesen Fall mitprüft.)
dist upgradegegen eine Fixture-Instanz, deren Guidance-Datei seit der Installationunverändert ist, schreibt eine verbesserte Anleitungsprosa tatsächlich hinein.
(
test_upgrade_writes_improved_guidance_prose_over_an_adopted_type_spec- prüft zusätzlich,dass der adoptierte Type-Spec selbst unangetastet bleibt, weil er in keinem Stamp steht.)
dist upgradegegen eine Instanz mit adoptiertem Type-Spec ohneguidance:istbeobachtbar folgenlos. (
test_types_describe_a_type_with_no_guidance_omits_it_cleanlyundtest_get_guidance_is_none_when_the_type_spec_declares_none; der Upgrade-Pfad selbst istunverändert, weil eine Datei ohne
guidance:keinen neuen Code erreicht.)wikitool newliest sein Template weiter austypes/<name>.md- kein zweiter Ladepfad.(
test_extract_template_reads_only_the_type_spec_never_the_guidance_file: ein ```markdown-Blockin der Guidance-Datei wird nachweislich nicht als Scaffold genommen.)
guidance:beschreibt wie bisher.types describe --jsonträgtguidanceundguidance_path,bodybleibt der Body desType-Specs. (
test_types_describe_entity_composes_guidance_and_body_separately,test_types_describe_composes_guidance_ahead_of_body_in_text_output.)obligation: offered:migrate statuslistet es separat("1 optional upgrade(s) available - none of them block"),
migrate done 6.0.0 --dry-runbestätigt "would record the optional ... Content stays at 5.0.0". Die
offered-Semantikselbst ist bereits durch die generischen
kb_state/migrate_cmd-Tests abgedeckt, deshalbhier kein zusätzlicher Test, sondern die Verifikation am realen Dokument.
version bump --minor, kein--breaking, keine Pflichtmigration. (6.0.0-beta.5→6.0.0-beta.6; der Kandidat stand bereits auf MAJOR, die Escalation ändert seine Basis alsonicht.)
auffielen (
README.md,docs/language-boundaries.md).tools/wikitool docs verify,tools/wikitool instructions verifyundpytestgrün: 1261Tests (8 neu),
doctorohne Befund außer dem üblichensession-id-WARN.Bewusst nicht Teil davon
types/<name>.schema.yamlbleibt instanzeigen. Der Enum gehört der Instanz(
evolve-subtypes.md).kb/CONVENTIONS.md(.template)§ Language braucht keine Änderung: die Sprachachse ist mit#103 entschieden und hat sich hier nicht bewegt. Stattdessen wurde
docs/language-boundaries.mdnachgezogen, das genau diesen Unterschied jetzt ausspricht.types/type-spec.schema.yaml(root:undcapture_fields:fehlen trotzadditionalProperties: false, und niemand merkt es, weil Type-Spec-Frontmatter nirgends gegendieses Schema validiert wird): eigenes Issue #105. Hier wurde nur das
guidance:-Feld in dieProsa von
types/type-spec.mdaufgenommen, nicht ins Schema - das wäre ohnehin wirkungslos,solange #105 offen ist.
_owned_type_stem()indist_cmd.py, nicht inownership.py. Dort leben ausschließlichPfade unter den Content-Stages (
kb/,raw/,work/,reports/);types/kennt das Modulgar nicht. Beide Aufrufstellen liegen in derselben Datei, die Anti-Drift-Eigenschaft ist also
erfüllt.
Woher das kam
Aufgefallen bei der Arbeit an #99 (TOC-Scope und Sprachregeln), als der Seiten-Type-Spec in beiden
Achsen gleichzeitig angefasst wurde. Dort wurde der Schnitt innerhalb der Datei dokumentiert,
weil die Dateigrenze nicht in derselben Sitzung zu verschieben war.
Die erste Fassung dieses Bodys nahm an, die Frontmatter-Konfiguration sei stackeigen und nur
Template und
layout:-Titel gehörten der Instanz. Die Prüfung gegensetup-instance.md,evolve-subtypes.mdund die 182type:-Verweise im Korpus hat das umgedreht.Seiten-Type-Spec am Publikum schneiden: Anleitung stackeigen, Seitenmaterial instanzeigento Anleitungsprosa aus dem Seiten-Type-Spec herausloesen: guidance stackeigen, Type-Spec bleibt instanzeigenChangelog: Schnittrichtung umgedreht und Body komplett neu geschrieben. Der alte Befund nahm an, Frontmatter-Konfiguration (
base_dir,layout,page_ref_fields, Enum) sei stackeigen;setup-instance.mdSchritt 5.5,evolve-subtypes.mdSchritt 3 und die 182type:-Verweise im Korpus zeigen das Gegenteil. Neu:types/<name>.mdbleibt instanzeigen, die maschinenabgeleitete Anleitungsprosa zieht in ein stackeigenestypes/<name>.guidance.md, verknüpft über ein optionalesguidance:-Frontmatterfeld und vontypes describezusammengesetzt.Designfragen 1-4 beantwortet (Richtungsentscheidung vom Betreiber, 2026-09-15): Geschwisterdatei mit eigenem Typ
type-guidance;layout:-Frage löst sich auf, weil kein Frontmatter geteilt wird; Split optional für selbstgeschriebene Typen; kein Grenzübertritt ---minorstatt--major, die einmalige Adoption trägt das ersteobligation: offeredMigrationsdokument dieses Repos.Alte Kriterien gestrichen mit Begründung im Body: verbatim-Auslieferung von
types/<name>.md, Migration der drei Eigenschaften als Pflichtmigration,--major/--breaking,kb/CONVENTIONS.md§ Language. Neu dazu: Drop-in-Nachweis als Test,find_leaks-Verhalten,offered-Semantik inmigrate status/migrate done, Doku-Durchzugsliste.kind/decision→kind/build.size/Lbleibt, bedeutet jetzt aber Volumen (zwei Schnitte: Mechanik, dann die vier Guidance-Dateien plus Durchzug), nicht offene Designfragen.Nebenbefund, als eigenes Issue abgelegt:
types/type-spec.schema.yamlkennt wederroot:nochcapture_fields:trotzadditionalProperties: false, und niemand merkt es, weil Type-Spec-Frontmatter nirgends gegen dieses Schema validiert wird.