| name | lok-numbering-article-review |
| description | Two-phase Locobox article JSON review plus optional auto-fix: (0) on request, apply whitelisted splits (prefer Python helpers under utils/agents/lok-numbering-article-review/scripts/, especially autofix_model_type_number_split.py for type/number splitting), livery/era fixes, and same-rule fixes to sibling variant articles when present in repo (per manufacturer rules in skill docs); country only when unambiguous. (1) full pass with findings, (2) one file at a time user resolves (skip / ignore). Read-only unless auto-fix or explicit edit order. Re-review of ignored items only when user explicitly asks. Use for Loknummer review or when this skill is attached. |
| disable-model-invocation | true |
Loknummerierung: Parsing, Split, PlausibilitÀt (zwei Phasen)
Hauptziel
- Parsen und splitten: Aus
model.type (und bei Bedarf description, source.url, model.number) Baureihe/Reihe vs laufende Nummer ableiten.
- PlausibilitÀt: Abgleich mit Operator, Land, Stromsystem (
model.electricSystem vs. Beschreibung und vs. Schwester-Varianten derselben Baureihe laut Hersteller-Logik, siehe unten), scale (Schema: u. a. H0, nicht h0), Kategorien vs. Baureihe (z. B. Diesellok vs. elektrolokomotive), Fliesstext, internen Kurzreferenzen (EVN vs. Wagen nicht verwechseln, siehe reference-evn-uic.md). Optional: id / articleNumber, setNumber, decoderInterface nur bei Widerspruch zur Beschreibung oder offensichtlichem Parserfehler.
- Livery und Sondernamen: Beim Splitten prĂŒfen, ob neben Baureihe und Nummer noch Taufname, Sonderfolierung, Piercer-/Marketing- oder Zug-/Produktname (oft in AnfĂŒhrungszeichen im Roh-Import) vorkam. Wenn ja: Finding, falls
model.livery noch generisch (SBB, OBB, âŠ), null ist oder ein Import-Mischstring (z. B. halber Satz statt Lackname). Empfehlung: kurz und konkret in model.livery ablegen, Details optional im Fliesstext; nicht stillschweigend verlieren. Details: internal/field-parsing-model.md («Livery nach Split»).
AusfĂŒhrung in zwei Phasen (Pass 1, Phase 2), optional davor oder dazwischen Auto-Fix (siehe unten). Standard: keine JSON-Schreibzugriffe ohne expliziten Auto-Fix oder andere Schreibbeauftragung.
Hard rules
- Scope: Nur geÀnderte oder vom User genannte
articles/**/*.json auf dem aktuellen Branch (Git wie unten), oder nur genannte Pfade unter articles/.
- Read-only: Pass 1 und Phase 2 sind inhaltlich Review-first. Artikel-JSON nur schreiben, wenn (a) der User Auto-Fix ausdrĂŒcklich wĂŒnscht (siehe Abschnitt «Auto-Fix») und nur gemĂ€ss der dortigen Allowlist, oder (b) der User eine konkrete Ănderung pro Datei oder global beauftragt (dann ausserhalb dieses Skills die ĂŒblichen Projektregeln).
- Ehrlichkeit: Mehrere Lesarten klar trennen. Nicht raten ohne Kennzeichnung. Auto-Fix kein Raten: nur Regeln aus der Allowlist, sonst Finding und Datei unverÀndert lassen.
Git: welche JSON-Dateien
Vor dem Review (Repo-Root). Fallback nutzen, weil viele Repos master statt main fĂŒhren:
git fetch origin main 2>/dev/null || true
git fetch origin master 2>/dev/null || true
BASE=$(
git merge-base HEAD origin/main 2>/dev/null \
|| git merge-base HEAD main 2>/dev/null \
|| git merge-base HEAD origin/master 2>/dev/null \
|| git merge-base HEAD master 2>/dev/null \
|| echo ""
)
if [ -n "$BASE" ]; then
git diff --name-only "$BASE"...HEAD -- 'articles/**/*.json'
else
git diff --name-only HEAD -- 'articles/**/*.json'
fi
- User nennt Pfade: nur diese Dateien.
- Keine Diff-Dateien: User fragen (gesamter
articles/-Baum oder Teilpfade).
Auto-Fix (optional, mechanisch)
Auslöser: Nur wenn der User das klar verlangt (z. B. «mit Auto-Fix», «Auto-Fix auf dem Scope», «bekannte Parserfehler automatisch»). Ohne diesen Wunsch keinen Auto-Fix ausfĂŒhren.
Reihenfolge: Scope wie unter «Git» ermitteln â Arbeitsatz erweitern (Schwesterartikel, siehe unten) â Auto-Fix-Pass auf dem erweiterten Satz â Pass 1 (Findings; bereits korrigierte Felder kurz als «Auto-Fix erledigt» markieren) â Phase 2 unverĂ€ndert.
Repo-Skripte (Python, Auto-Fix)
Alle Hilfsskripte zu diesem Skill liegen im Repo unter utils/agents/lok-numbering-article-review/scripts/ (vom Repo-Root aus ansprechen). Dort unter anderem:
autofix_model_type_number_split.py â mechanischer Split model.type / model.number (Allowlist, Ă€ndert keine description).
autofix_description_ocr.py â optionale OCR-/Encoding-Ersetzungen nur in description.
autofill_categories_from_roco_url.py â wenn categories leer sind und source.url eindeutig Roco ist (âŠ/dampf-|diesel-|elektrolokomotiven/âŠ, âŠ/triebzuge/âŠ, oder âŠ/home-neuheiten/⊠mit passendem Slug): setzt lokomotive plus passende Kategorie (sonst kein Schreiben).
autofix_model_country.py â setzt model.country, wenn null und der Fall zur Skill-Allowlist (K.P.E.V., SĂŒdbahn+AT-Kontext), zur OperatorâISO-Map im Skript (u. a. DB, ÄSD als CS, VSM, GTS Rail, SBW) oder zur konservativen DR-Epochen-Heuristik (IV â DD, reine IâIII â DE) passt.
test_autofix_model_type_number_split.py â Unit-Tests zum Split-Skript.
test_autofix_model_country.py â Unit-Tests zum Country-Skript.
Die folgenden Abschnitte nennen konkrete Kommandozeilen; Pfade sind immer relativ zum Repo-Root, ausser beim cd fĂŒr unittest.
Mechanischer Split (model.type / model.number)
Wenn der User Auto-Fix fĂŒr zusammengezogene Typ-/Nummer-Felder will und der Pfad-Scope klar ist, zuerst das Repo-Skript utils/agents/lok-numbering-article-review/scripts/autofix_model_type_number_split.py einsetzen (Allowlist dort codiert; description wird nicht geĂ€ndert). Gleiche manuelle Regex-Arbeit nur, wenn das Skript den Fall nicht abdeckt oder der User explizit nur EinzelfĂ€lle ohne Skript will.
- Trockenlauf (Pflicht vor Schreiben): im Repo-Root
python3 utils/agents/lok-numbering-article-review/scripts/autofix_model_type_number_split.py <Pfad(e) oder Verzeichnis(se)>
Ausgabe: eine Zeile pro betroffener Datei (Regel-KĂŒrzel, alt â neu).
- Schreiben: dieselbe Zeile mit
--apply (z. B. python3 utils/agents/lok-numbering-article-review/scripts/autofix_model_type_number_split.py --apply articles/roco).
- Optional:
--include-br splittet BR 110-artige Werte in BR + Ziffernblock; standardmÀssig aus, siehe Skript-Hilfe.
- Tests:
cd utils/agents/lok-numbering-article-review/scripts && python3 -m unittest test_autofix_model_type_number_split -v
- Protokoll: Skript-Ausgabe ins Chat ĂŒbernehmen (keine stillen MassenĂ€nderungen).
Pflichtprotokoll: FĂŒr jede geĂ€nderte Datei eine Zeile im Chat (oder kurze Tabelle): Pfad, Feld, alt â neu. Keine stillen MassenĂ€nderungen.
Schwesterartikel (Variantengruppen, herstellerneutral)
Vor dem eigentlichen Auto-Fix den Arbeitsatz aus dem Git-Scope wie folgt ergÀnzen:
- Variantengruppe definieren ĂŒber
manufacturer, articleNumber / id und im Projekt dokumentierte Regeln (z. B. in field-parsing-model.md oder einem internal/wiki-*.md zum Hersteller): welche Artikel gelten als dieselbe Modellfamilie (Analog/Digital/AC, Sonderlack, Set-Teil A/B)?
- Alle im Repo vorhandenen JSON-Dateien derselben Gruppe unter
articles/<hersteller>/ in den Auto-Fix-Arbeitsatz aufnehmen, auch wenn sie nicht im Git-Diff stehen, sobald mindestens ein Gruppenmitglied im Scope liegt.
- Gleiche Korrektur nur, wenn die Allowlist-Bedingung fĂŒr jede Schwester einzeln erfĂŒllt ist (z. B. identisches Livery-Artefakt). Nicht Werte von einer Variante auf eine andere blind kopieren, wenn sich die AusprĂ€gung unterscheidet (z. B. Wechselstrom vs. Gleichstrom, andere Epoche): nur anpassen, wenn dieselbe Regel dort eindeutig zutrifft.
- Ohne dokumentierte Regel keine automatische Scope-Erweiterung; stattdessen Pass 1-Finding («vermutlich Schwester von âŠ, Regel fehlt»).
Beispiel (nur falls im Repo weiterhin zutreffend): Roco-Neuheiten mit siebenstelliger Nummer 73 + eine Variantenziffer + gemeinsamer vierstelliger Kern: Schwesterdateien articles/roco/73{d}{kern}.json mit d â {0,1,2}. Bedeutung der Ziffer d und Stromsystem aus Hersteller-/Shop-Konvention ableiten, nicht global raten.
Protokoll: Schwester-Korrekturen explizit markieren (z. B. «Schwester-Variante, gleiche Gruppe wie articles/<hersteller>/<kern>.json»).
Allowlist: Splitting (model.type / model.number)
Die implementierte mechanische Allowlist (Regex plus Dampf-Slug-Regel) liegt im Skript utils/agents/lok-numbering-article-review/scripts/autofix_model_type_number_split.py. Bei Auto-Fix-Wunsch fĂŒr Splits dieses Skript verwenden; die folgenden Bulletpoints bleiben die inhaltliche Referenz fĂŒr Review und fĂŒr FĂ€lle ausserhalb des Skripts.
Optional (nur description, OCR-Ersetzungen): utils/agents/lok-numbering-article-review/scripts/autofix_description_ocr.py (Dry-Run ohne --apply, Schreiben mit --apply). Kein Ersatz fĂŒr inhaltliches Review.
Nur bekannte, im Projekt oder in internal/field-parsing-model.md dokumentierte Muster, wenn alle zutreffen:
- VollstÀndige Betriebsnummer steht nur in
model.type (z. B. Dampf-PrĂ€fix «39 1052-8», «38 2566-8»), model.number ist null, und Baureihe plus Rest sind eindeutig splittbar. Beleg: mindestens eine eindeutige Quelle unter description (sachliche erste Zeile), source.url (Pfadsegment / Slug, z. B. Roco âŠ-dampflokomotive-38-3713-âŠ) oder URL erster Zeile ohne Widerspruch zwischen diesen Quellen. OCR in der Beschreibung allein blockiert den Auto-Fix nicht, wenn der URL-Slug dieselbe Nummernaufteilung trĂ€gt.
- Dampflok, zweistellig + vier Ziffern (ohne PrĂŒfziffer im Titel):
model.type exakt im Muster ^\d{2} \d{4}$ (Leerzeichen genau eines), model.number ist null, categories enthĂ€lt dampflokomotive, und source.url enthĂ€lt die gleiche Paarung als {Baureihe}-{Viererblock} (z. B. 38-3713, 50-1751) â model.type = zweistellige Baureihe, model.number = Viererblock. (HĂ€ufiger Shop-/Parserrest; siehe Tabelle in field-parsing-model.md.)
Nicht Auto-Fix: model.electricSystem (nie aus Marketing-/Fliesstext, Artikelnummer-Heuristik oder Schwesterdatei ableiten; Shops nutzen oft dieselbe Beschreibungsbaustelle fĂŒr mehrere Varianten â Pass 1-Finding oder explizite User-Anweisung pro Datei). Ausserdem: jede neue Baureihe raten, SNCF/PKP-MischfĂ€lle, Triebzug- und Set-Artikel ohne eindeutige Einzel-Lok-Nummer (langer model.type, model.number null, keine splittbare Betriebsnummer in URL erster Zeile), kein konsistenter Nummernbeleg in description und kein passender Slug in source.url. Diese FĂ€lle in Pass 1 als Finding («Set/Serie, Schwester ggf. prĂŒfen»), nicht raten.
Allowlist: model.livery
Nur offensichtliche Import-Artefakte bereinigen:
- Platzhalter wie «Info: ~», «a a», Fragmente wie «= Li: Oo» â auf
null setzen (oder ein Wort aus der ersten sauberen Kurzzeile der description, wenn dort ein eindeutiger Lack-/Zustandsname steht und nichts anderes passt).
livery beginnt mit Ziffer oder «4» plus abgeschnittener deutscher Marketingphrase («4AusfĂŒhrung âŠÂ», «4Variante âŠÂ») â null oder eine kurze, aus dem vollen Satz eindeutig ableitbare Bezeichnung (max. ein kurzer Begriff); wenn nicht eindeutig â kein Schreiben, Finding in Pass 1.
- Lange OCR-/FliesssÀtze in
livery (mehr als ca. 40 Zeichen oder Satzzeichen wie «â» mitten im «Lack») â auf null kĂŒrzen, nicht durch erfundenen Marketingtext ersetzen.
Allowlist: model.era
Nur wenn eindeutig aus description (erste sachliche Zeile) oder URL und ohne Widerspruch zu bestehendem model.era:
model.era ist null oder offensichtlicher Tippfehler gegenĂŒber der ersten Beschreibungszeile (z. B. «Epoche VI» vs. null) â auf den kanonischen Epochen-String aus dem Schema setzen (Projektkonvention: römische Ziffern, Kombinationen wie «III-IV» wie im Datensatz ĂŒblich).
Kein Auto-Fix, wenn Epoche im Fliesstext widersprĂŒchlich oder nur im Marketingkörper genannt.
Allowlist: model.country (sehr konservativ)
Nur wenn die Zuordnung praktisch alternativlos ist:
country null und operator «K.P.E.V.» oder gleichwertig klar Deutsches Kaiserreich (historisch) â DE.
country null und operator «SĂŒdbahn» (k. k. SĂŒdbahn) mit AT-Kontext in description/categories â AT.
- Mechanisch zusĂ€tzlich (siehe Skript): OperatorâISO (z. B. DB â DE, ÄSD als CS wie andere ÄSD-Artikel, VSM â NL, GTS Rail â IT, SBW â AT) sowie DR:
IV in model.era â DD; reine I / II / III (ohne IV) â DE; fehlende Epoche oder andere Schreibweisen â DD (Default fĂŒr Roco-DDR-FĂ€lle).
Nicht per Skript raten: Grenzverkehr, Vermietung (MRCE, Railpool, âŠ), SNCB/SĆœ-Mischungen. Dort Findings oder Map im Skript erweitern.
Skript: utils/agents/lok-numbering-article-review/scripts/autofix_model_country.py (Dry-Run ohne --apply). Tests: cd ⊠scripts && python3 -m unittest test_autofix_model_country.
Nach Auto-Fix
- In Pass 1 bei betroffenen Dateien kurz vermerken: «Auto-Fix: âŠÂ» (Felder), damit Phase 2 nicht dieselben Punkte erneut als offen fĂŒhrt, ausser der User wĂŒnscht RĂŒcknahme.
Phasen-Workflow (Pflicht)
Phase 1: Erstpass ĂŒber alles
- Jede Datei im Scope mindestens kurz anfassen (kein Ăberspringen im Stillen).
- Ausgabe ein zusammenhĂ€ngendes Dokument âPass 1â mit:
- Liste aller Dateien (oder Gruppierung nur, wenn der User vorher explizit Gruppierung gleicher Muster wĂŒnscht, sonst lieber pro Datei eine Zeile Minimum).
- Pro Datei: klar ok (ein Kurzsatz) oder Findings (nummeriert pro Datei:
F1, F2, âŠ) und alles Unklare (Parsing-Zweifel, WidersprĂŒche, fehlende Felder).
- Keine RĂŒckfrage an den User in Phase 1, ausser Scope unklar.
- Ende Phase 1: kurze Statistik (Anzahl Dateien, Anzahl mit Findings/Unklarem, hÀufige Muster).
Phase 2: Datei fĂŒr Datei
- Genau eine JSON-Datei pro Agent-Turn bearbeiten (RĂŒckfrage-Runde).
- Nur die Unklarheiten und Findings dieser Datei aus Pass 1 vorlegen (mit IDs
F1, F2, âŠ).
- Eine klare Frage: was soll mit welchem Punkt passieren (z. B. Split A wÀhlen, Text spÀter anpassen, ignorieren)?
- User-Antworten in dieser Phase:
skip: keine weiteren Entscheidungen zu dieser Datei in Phase 2; sofort nĂ€chste Datei mit offenen Punkten wĂ€hlen. Offene Punkte dieser Datei in die Schlussliste als âskipped (User)â ĂŒbernehmen.
ignore: der User bezieht sich auf ein genanntes Finding (ignore F2) oder auf alle offenen Punkte dieser Datei (ignore all). Diese Punkte gelten fĂŒr diesen Review-Durchlauf als ignoriert (nicht nacharbeiten, nicht nochmals fragen in Phase 2). In der Schlussliste als âignored (this pass)â fĂŒhren.
- Konkrete Anweisung (z. B. âSplit Aâ, âcountry AT setzenâ): Agent notiert als entschieden in der laufenden Findings-Liste. Schreiben in die JSON nur, wenn der User danach explizit editieren lĂ€sst oder Auto-Fix/Ănderungslauf dafĂŒr schon beauftragt ist.
- Nach jeder User-Antwort: entweder nÀchstes Finding derselben Datei fragen oder nÀchste Datei, bis keine Datei mehr mit nicht
skip/ignore behandelten offenen Punkten ĂŒbrig ist (oder User Session beendet).
Datei in der Antwort (Pflicht, Phase 2)
- Sobald eine konkrete
articles/**/*.json in Phase 2 im Fokus steht: in derselben Antwort immer den vollen Repo-relativen Pfad nennen (eine Zeile, z. B. articles/roco/70078.json oder articles/<hersteller>/âŠ.json). Kein vollstĂ€ndiger Dateiinhalt in der Antwort, ausser der User verlangt ausdrĂŒcklich den Inhalt oder einen Ausschnitt.
- Pass 1: keine Pflicht, alle Pfade einzeln aufzuzÀhlen; bei Phase 2 pro Fokusdatei der Pfad reicht.
Ignorierte und erneuter Review
- Findings oder Dateien, die in Phase 2 als
ignore markiert wurden, nicht von alleine in einem spÀteren Turn derselben Session wieder aufrollen.
- Erneutes PrĂŒfen zuvor ignorierten Inhalts nur, wenn der User explizit verlangt (z. B. âzweiter Pass, diesmal inklusive ignorierteâ oder namentlich Dateien nennen).
Domain-Wissen (progressive disclosure)
Vor dem Review: contracts/article.schema.json kurz ansehen.
internal/wiki-*.md: Inhalt ist komprimiertes Validierungswissen (LÀnder, Operatoren, Stromsysteme, typische Baureihen, Kategoriechecks). Ausnahme: wiki-baureihen-schemata-uebersicht.md ist absichtlich ein Link-Index; einige LÀnderdateien haben ausserdem einen PrimÀrlink unter dem Titel (deutsche Wikipedia als Korrektur). Sonst: keine langen Linklisten im Fliesstext; Herkunft weiterhin unter «Provenienz» je Datei.
Inhalt pro Datei (Pass 1 und als Referenz in Phase 2)
Pro Datei mindestens:
- Roh:
model.type, model.number, model.livery, model.electricSystem, model.scale, model.era, categories (wenn fĂŒr den Fehler relevant)
- Parsing / Split: sicher / wahrscheinlich / unklar, ggf. Vorschlag A/B
- PlausibilitĂ€t: ok / unklar / widersprĂŒchlich, Stichpunkte (inkl. Livery vs Sondername aus Roh-
type oder Beschreibung; Stromsystem vs. Text und vs. Schwester-Variante derselben dokumentierten Modellfamilie; Kategorie vs. Antrieb; Triebzug/Set mit number null und langem type ohne EVN-Split; description / source.url bei OCR-MĂŒll oder deutschsprachigem Fliesstext vs. auslĂ€ndischem Vorbild)
- Findings mit IDs
F1, F2, ⊠fĂŒr Phase 2
Schlussliste (Ende Phase 2 oder bei Abbruch)
Ein Abschnitt âFindings-Ăbersichtâ:
- Auto-Fix (falls gelaufen): kurze Liste
Pfad + geĂ€nderte Felder (kann mit «Erledigt» ĂŒberlappen).
- Erledigt / entschieden (kurz, mit Dateipfad und Finding-ID).
- Offen (skipped ohne Resolution).
- Ignored (this pass) (Pfad + ID oder âwhole fileâ).
Sprache: Deutsch, Schweizer Rechtschreibung (Umlaute, kein Eszett).