Ausgearbeitet aus einem status/incoming-Stub am 2026-10-09 (Stand 9.0.0, 7cfafd7), in der Design-Sitzung zu #87/#200. Der Stub steht wörtlich im ersten Kommentar. Entscheidungen des Betreibers vom 2026-10-10 sind eingearbeitet. Ausgelagert sind der Umfang (Modulindex mit Unterseiten, Stub-Punkt 2) nach #209 und die eigenen Handler der Instanz nach #210.
Erledigt (2026-10-11): gebaut in Version 10.0.0-beta.3 (--minor auf dem laufenden Kandidaten von 10.0.0), Commit 2213d68. Verifiziert durch pytest (2784 bestanden, 4 übersprungen), docs verify und instructions verify lokal sowie CI auf 2213d68: Läufe 657 und 658, beide success. Der Abschnitt „Entwurf“ beschreibt den gebauten Stand; wo er vom ursprünglichen Entwurf abweicht, steht es dort mit Grund.
Befund (gegen den Baum und die echte Seite geprüft, 2026-10-09 - Stand vor diesem Paket)
raw fetch leitete aus jedem HTML mit derselben Funktion ab (tools/chemenu/web_capture.py, content_root/derive_text), bewusst ohne Lesbarkeits-Heuristik, damit gleiche Bytes immer gleichen Text ergeben. Regeln pro Website gab es nicht.
web_capture.fetch + derive_text auf https://learn.microsoft.com/en-us/powershell/module/oslicense/?view=windowsserver2025-ps ergab vor der Überschrift:
Seitenbedienung: „Table of contents Exit editor mode“, „Ask Learn“, „Read in English Add Add to Plans Edit“, „Copy Markdown Print“;
zweimal „Access to this page requires authorization. You can try signing in or changing directories.“
Der Hinweis steht im HTML in <p class="… authentication-determined not-authenticated"> innerhalb von div.notification. Die Seite blendet ihn per JavaScript ein oder aus, eine Ableitung ohne JavaScript behielt ihn. Die Tabelle der Cmdlets kam sauber an.
Die Seite nennt ihre Quelle: <meta name="original_content_git_url" content="https://github.com/MicrosoftDocs/windows-powershell-docs/blob/live/docset/winserver2025-ps/OSLicense/OSLicense.md">.
Das Muster einer Registry mit „neues Format = Modul + Registrierung + Tests“ und Hinweisen nur in der Ausgabe gab es seit #199 (tools/chemenu/filters/).
Ziel
Für URLs einer bekannten Website holt raw fetch dieselbe Seite in Standardform, leitet sauberen Text ab und gibt die Hinweise, die für diese Website gelten, als CHECK-Zeilen aus - nur wenn sie zutreffen. Was ein Handler deterministisch erledigen kann, erledigt er selbst. Der Agent bekommt keine Anweisung wie „ignoriere den Anmeldehinweis“, weil der Hinweis im Text gar nicht mehr vorkommt.
Entscheidungen des Betreibers (2026-10-10)
Handler dieses Pakets sind Code im Stack. Die Instanz parametriert nur und gibt Hinweiszeilen als Text (Entwurf 5). Eigene Handler der Instanz sind ein eigenes Paket (#210), deklarativ als Daten.
Zuerst nur Bereinigung. Das Quell-Markdown aus original_content_git_url wird nicht abgerufen. Eine CHECK-Zeile nennt die Quell-URL. Den Abruf der Quelle bauen wir erst, wenn die Bereinigung nicht reicht.
Hinweiszeilen der Instanz als Text sind zugelassen, höchstens drei pro Muster. Sie sind Konfiguration des Betreibers, kein Inhalt aus raw/.
Entwurf (gebauter Stand)
Registry tools/chemenu/sites/, ein Modul pro Website, nach dem Muster von filters/; _load_modules() importiert jedes Modul des Pakets. Ein Handler ist ein Site-Datensatz mit name, host (exakt, klein geschrieben), optionalem Pfadmuster path (Regex gegen den Anfang des URL-Pfads), summary, parent und drei Bausteinen:
rewrites: die Standardform als Liste von Regex-Ersetzungen (Rewrite) auf der URL; {locale} in der Ersetzung ist die Einstellung der Instanz;
drop: Regeln (web_capture.Rule), welche Elemente vor der Ableitung entfallen - nach Tag, id, class, Attribut (mit Wert) und optional „innerhalb von Tag“, deterministisch, keine Heuristik;
checks: höchstens drei Check-Zeilen, jede Text mit optionaler Bedingung - „die Seite hat <meta name=…> mit Inhalt“ ({meta} im Text) oder „ein Selektor trifft mindestens ein Element“ ({count} im Text).
Abweichung vom ursprünglichen Entwurf: Dort standen canonical(url) und checks(html, url) als Funktionen, Python-Hooks für den Rest, und als Beispiel-Bedingung „wenn eine drop-Regel getroffen hat“. Gebaut ist alles als Daten, weil beide Handler damit vollständig ausdrückbar waren und #210 genau diese Form braucht; Python-Hooks gibt es keine, und die Bedingungen sind die zwei, die die Handler brauchten (Meta, Selektor-Zahl). Die im Entwurf genannten Erweiterungspunkte für #209 (Unterseiten) und #169 (Login) sind nicht als Hooks vorgebaut: Sie kommen als weitere Felder des Site-Datensatzes, wenn diese Pakete gebaut werden.
Auswahl: Unter den eingeschalteten Handlern eines Hosts gewinnt der mit dem längsten passenden Pfadmuster. Ein spezieller Handler erbt über parent="<name>"; register speichert ihn flachgelegt (die Bausteine des Elternteils zuerst), sodass zur Laufzeit keine Kette durchlaufen wird. Registrierungsfehler (ValueError beim Import): gleicher Name, gleicher Host mit gleichem Muster, unbekannter oder fremd-hostiger parent, mehr als drei Checks auch zusammen mit dem Elternteil. (Ursprünglich als Klassenvererbung PowerShellModule(LearnMicrosoft) skizziert; als Datenfeld ist es dieselbe Semantik in der Form, die #210 braucht.)
Wo er greift:raw fetch <url> und raw fetch --html <datei> --url <url>; nicht in raw derive. Das .html bleibt byte-genau die Antwort, nur die Ableitung ändert sich. Beim Abruf wird die Standardform geholt; aus ihr kommen url: im Header und der Dateistamm, die eingegebene URL steht als requested_url: direkt nach url:, wenn sie abweicht, und site: <name> nach charset:. (Der Entwurf nannte das Feld fetched_url; der bestehende Header heißt url:, daran wurde nichts umbenannt.) Bei --html gelten die drop-Regeln und Checks, die URL bleibt aber wie eingegeben, weil kein Abruf stattfand. Eine URL ohne Handler verhält sich unverändert.
Erste Handler (sites/learn_microsoft.py):
learn-microsoft: Gebietsschema-Segment → Einstellung locale (Standard en-us), Query view= bleibt; drop: #ms--content-header, #action-panel, #article-header, [unauthorized-private-section], .authentication-determined, #site-user-feedback-footer, #ms--inline-notifications, #assertive-live-region, #polite-live-region; eine CHECK-Zeile mit der Quell-URL aus original_content_git_url, wenn vorhanden.
learn-microsoft-powershell-module: Pfad /<locale>/powershell/module/<modul>/ - nur Modul-Übersichtsseiten, nicht alles unter /powershell/module/, damit die Zählung nicht auf Cmdlet-Seiten anschlägt; erbt; bis #209 eine weitere CHECK-Zeile mit der Zahl der Cmdlet-Links in der Tabelle.
Anteil der Instanz: Abschnitt sites der Einstellungen (Stufe instance, config_shapes.SITES, dokumentiert in docs/reference/configuration.md):
disabled: Handler-Namen, die nicht greifen; ein unbekannter Name ist ein Fehler (Exit 1 vor jedem Abruf), damit ein Tippfehler keinen Handler eingeschaltet lässt;
locale: Gebietsschema der Standardform;
notes: je Eintrag host, optional path, und lines - höchstens drei Zeilen zu je höchstens 300 Zeichen, ausgegeben als CHECK nach denen des Handlers, auch für Hosts ohne Handler.
tools/chemenu/web_capture.py: Rule, prune, count_matches, meta_content; derive_text/derive_document nehmen optionale drop-Regeln, site und requested_url, ohne Änderung für den Fall ohne
tools/chemenu/commands/raw/fetch.py samt Kommando-Record (Zusammenfassung, Header-Felder, Site-Handler, ON FAILURE für einen kaputten sites-Abschnitt)
tools/chemenu/config_shapes.py (SITES in SETTINGS_SECTIONS), reference_doc.CONFIG_REGIONS (reference-config-sites), docs/reference/configuration.md
Tests: tools/chemenu/tests/test_sites.py; Fixture als lizenzneutraler Nachbau der Seite mit derselben Struktur unter tools/chemenu/tests/fixtures/learn_microsoft/ - nicht unter testfiles/, weil testfiles/ an raw derive verfüttert wird
raw/CONTRACT.md § Getting a URL in, tools/README.md, docs/how-to/ingest-a-source.md, generierte Kommandoreferenz und tools/CONTRACT.md
Akzeptanzkriterien
Für die Fixture-Seite enthält die abgeleitete .md weder „requires authorization“ noch „Exit editor mode“ noch „Add to Plans“, aber die Überschrift „OSLicense Module“ und alle Zeilen der Cmdlet-Tabelle.
Das gespeicherte .html ist byte-identisch mit der Antwort des (Test-)Servers.
Die Ausgabe enthält eine CHECK-Zeile mit der Quell-URL aus original_content_git_url.
raw fetch https://learn.microsoft.com/de-de/… holt …/en-us/…; der Header nennt beide URLs.
Eine URL ohne passenden Handler ergibt byte-identische Ausgaben wie vorher (bestehende Tests von raw fetch unverändert grün).
Zwei Läufe über dieselben Bytes ergeben byte-identische .md, abgesehen vom Zeitstempel.
Eine doppelte Registrierung (gleicher Host, gleiches Muster) scheitert beim Import, im Test geprüft.
Ein Handler, der per Instanz-Einstellung abgeschaltet ist, greift nicht. Eine Hinweiszeile der Instanz erscheint als CHECK.
pytest, docs verify, instructions verify grün; CI grün (Läufe 657 und 658 auf 2213d68).
Versionsteil
--minor - gebaut als 10.0.0-beta.3. Neues Verhalten nur für URLs mit Handler. Kein Kommando, Flag oder maschinenlesbares Format entfällt (der Header ist Erfassungsmetadaten). Was schon in raw/ liegt, bleibt unberührt. Drop-in in beide Richtungen.
> Ausgearbeitet aus einem `status/incoming`-Stub am 2026-10-09 (Stand `9.0.0`, `7cfafd7`), in der Design-Sitzung zu #87/#200. Der Stub steht wörtlich im ersten Kommentar. Entscheidungen des Betreibers vom 2026-10-10 sind eingearbeitet. Ausgelagert sind der Umfang (Modulindex mit Unterseiten, Stub-Punkt 2) nach #209 und die eigenen Handler der Instanz nach #210.
>
> **Erledigt (2026-10-11):** gebaut in Version `10.0.0-beta.3` (`--minor` auf dem laufenden Kandidaten von 10.0.0), Commit `2213d68`. Verifiziert durch `pytest` (2784 bestanden, 4 übersprungen), `docs verify` und `instructions verify` lokal sowie CI auf `2213d68`: Läufe [657](https://gitea.nehmer.net/torben/chemenu/actions/runs/657) und [658](https://gitea.nehmer.net/torben/chemenu/actions/runs/658), beide `success`. Der Abschnitt „Entwurf“ beschreibt den gebauten Stand; wo er vom ursprünglichen Entwurf abweicht, steht es dort mit Grund.
## Befund (gegen den Baum und die echte Seite geprüft, 2026-10-09 - Stand vor diesem Paket)
- `raw fetch` leitete aus jedem HTML mit derselben Funktion ab (`tools/chemenu/web_capture.py`, `content_root`/`derive_text`), bewusst ohne Lesbarkeits-Heuristik, damit gleiche Bytes immer gleichen Text ergeben. Regeln pro Website gab es nicht.
- `web_capture.fetch` + `derive_text` auf `https://learn.microsoft.com/en-us/powershell/module/oslicense/?view=windowsserver2025-ps` ergab vor der Überschrift:
- Seitenbedienung: „Table of contents Exit editor mode“, „Ask Learn“, „Read in English Add Add to Plans [Edit](…)“, „Copy Markdown Print“;
- zweimal „Access to this page requires authorization. You can try signing in or changing directories.“
Der Hinweis steht im HTML in `<p class="… authentication-determined not-authenticated">` innerhalb von `div.notification`. Die Seite blendet ihn per JavaScript ein oder aus, eine Ableitung ohne JavaScript behielt ihn. Die Tabelle der Cmdlets kam sauber an.
- Die Seite nennt ihre Quelle: `<meta name="original_content_git_url" content="https://github.com/MicrosoftDocs/windows-powershell-docs/blob/live/docset/winserver2025-ps/OSLicense/OSLicense.md">`.
- Das Muster einer Registry mit „neues Format = Modul + Registrierung + Tests“ und Hinweisen nur in der Ausgabe gab es seit #199 (`tools/chemenu/filters/`).
## Ziel
Für URLs einer bekannten Website holt `raw fetch` dieselbe Seite in Standardform, leitet sauberen Text ab und gibt die Hinweise, die für diese Website gelten, als `CHECK`-Zeilen aus - nur wenn sie zutreffen. Was ein Handler deterministisch erledigen kann, erledigt er selbst. Der Agent bekommt keine Anweisung wie „ignoriere den Anmeldehinweis“, weil der Hinweis im Text gar nicht mehr vorkommt.
## Entscheidungen des Betreibers (2026-10-10)
1. **Handler dieses Pakets sind Code im Stack.** Die Instanz parametriert nur und gibt Hinweiszeilen als Text (Entwurf 5). Eigene Handler der Instanz sind ein eigenes Paket (#210), deklarativ als Daten.
2. **Zuerst nur Bereinigung.** Das Quell-Markdown aus `original_content_git_url` wird nicht abgerufen. Eine `CHECK`-Zeile nennt die Quell-URL. Den Abruf der Quelle bauen wir erst, wenn die Bereinigung nicht reicht.
3. **Hinweiszeilen der Instanz als Text sind zugelassen**, höchstens drei pro Muster. Sie sind Konfiguration des Betreibers, kein Inhalt aus `raw/`.
## Entwurf (gebauter Stand)
1. **Registry `tools/chemenu/sites/`**, ein Modul pro Website, nach dem Muster von `filters/`; `_load_modules()` importiert jedes Modul des Pakets. Ein Handler ist ein `Site`-Datensatz mit `name`, `host` (exakt, klein geschrieben), optionalem Pfadmuster `path` (Regex gegen den Anfang des URL-Pfads), `summary`, `parent` und drei Bausteinen:
- `rewrites`: die Standardform als Liste von Regex-Ersetzungen (`Rewrite`) auf der URL; `{locale}` in der Ersetzung ist die Einstellung der Instanz;
- `drop`: Regeln (`web_capture.Rule`), welche Elemente vor der Ableitung entfallen - nach Tag, `id`, `class`, Attribut (mit Wert) und optional „innerhalb von Tag“, deterministisch, keine Heuristik;
- `checks`: höchstens drei `Check`-Zeilen, jede Text mit optionaler Bedingung - „die Seite hat `<meta name=…>` mit Inhalt“ (`{meta}` im Text) oder „ein Selektor trifft mindestens ein Element“ (`{count}` im Text).
**Abweichung vom ursprünglichen Entwurf:** Dort standen `canonical(url)` und `checks(html, url)` als Funktionen, Python-Hooks für den Rest, und als Beispiel-Bedingung „wenn eine `drop`-Regel getroffen hat“. Gebaut ist alles als Daten, weil beide Handler damit vollständig ausdrückbar waren und #210 genau diese Form braucht; Python-Hooks gibt es keine, und die Bedingungen sind die zwei, die die Handler brauchten (Meta, Selektor-Zahl). Die im Entwurf genannten Erweiterungspunkte für #209 (Unterseiten) und #169 (Login) sind **nicht** als Hooks vorgebaut: Sie kommen als weitere Felder des `Site`-Datensatzes, wenn diese Pakete gebaut werden.
2. **Auswahl:** Unter den eingeschalteten Handlern eines Hosts gewinnt der mit dem längsten passenden Pfadmuster. Ein spezieller Handler erbt über `parent="<name>"`; `register` speichert ihn flachgelegt (die Bausteine des Elternteils zuerst), sodass zur Laufzeit keine Kette durchlaufen wird. Registrierungsfehler (`ValueError` beim Import): gleicher Name, gleicher Host mit gleichem Muster, unbekannter oder fremd-hostiger `parent`, mehr als drei Checks auch zusammen mit dem Elternteil. (Ursprünglich als Klassenvererbung `PowerShellModule(LearnMicrosoft)` skizziert; als Datenfeld ist es dieselbe Semantik in der Form, die #210 braucht.)
3. **Wo er greift:** `raw fetch <url>` und `raw fetch --html <datei> --url <url>`; nicht in `raw derive`. Das `.html` bleibt byte-genau die Antwort, nur die Ableitung ändert sich. Beim Abruf wird die Standardform geholt; aus ihr kommen `url:` im Header und der Dateistamm, die eingegebene URL steht als `requested_url:` direkt nach `url:`, wenn sie abweicht, und `site: <name>` nach `charset:`. (Der Entwurf nannte das Feld `fetched_url`; der bestehende Header heißt `url:`, daran wurde nichts umbenannt.) Bei `--html` gelten die `drop`-Regeln und Checks, die URL bleibt aber wie eingegeben, weil kein Abruf stattfand. Eine URL ohne Handler verhält sich unverändert.
4. **Erste Handler** (`sites/learn_microsoft.py`):
- `learn-microsoft`: Gebietsschema-Segment → Einstellung `locale` (Standard `en-us`), Query `view=` bleibt; `drop`: `#ms--content-header`, `#action-panel`, `#article-header`, `[unauthorized-private-section]`, `.authentication-determined`, `#site-user-feedback-footer`, `#ms--inline-notifications`, `#assertive-live-region`, `#polite-live-region`; eine `CHECK`-Zeile mit der Quell-URL aus `original_content_git_url`, wenn vorhanden.
- `learn-microsoft-powershell-module`: Pfad `/<locale>/powershell/module/<modul>/` - **nur Modul-Übersichtsseiten**, nicht alles unter `/powershell/module/`, damit die Zählung nicht auf Cmdlet-Seiten anschlägt; erbt; bis #209 eine weitere `CHECK`-Zeile mit der Zahl der Cmdlet-Links in der Tabelle.
5. **Anteil der Instanz:** Abschnitt `sites` der Einstellungen (Stufe `instance`, `config_shapes.SITES`, dokumentiert in `docs/reference/configuration.md`):
- `disabled`: Handler-Namen, die nicht greifen; ein unbekannter Name ist ein Fehler (Exit 1 vor jedem Abruf), damit ein Tippfehler keinen Handler eingeschaltet lässt;
- `locale`: Gebietsschema der Standardform;
- `notes`: je Eintrag `host`, optional `path`, und `lines` - höchstens drei Zeilen zu je höchstens 300 Zeichen, ausgegeben als `CHECK` nach denen des Handlers, auch für Hosts ohne Handler.
## Betroffene Dateien
- neu: `tools/chemenu/sites/__init__.py` (Registry, Auswahl, Bausteine, Einstellungen), `sites/learn_microsoft.py`
- `tools/chemenu/web_capture.py`: `Rule`, `prune`, `count_matches`, `meta_content`; `derive_text`/`derive_document` nehmen optionale `drop`-Regeln, `site` und `requested_url`, ohne Änderung für den Fall ohne
- `tools/chemenu/commands/raw/fetch.py` samt Kommando-Record (Zusammenfassung, Header-Felder, Site-Handler, ON FAILURE für einen kaputten `sites`-Abschnitt)
- `tools/chemenu/config_shapes.py` (`SITES` in `SETTINGS_SECTIONS`), `reference_doc.CONFIG_REGIONS` (`reference-config-sites`), `docs/reference/configuration.md`
- Tests: `tools/chemenu/tests/test_sites.py`; Fixture als lizenzneutraler Nachbau der Seite mit derselben Struktur unter `tools/chemenu/tests/fixtures/learn_microsoft/` - nicht unter `testfiles/`, weil `testfiles/` an `raw derive` verfüttert wird
- `raw/CONTRACT.md` § Getting a URL in, `tools/README.md`, `docs/how-to/ingest-a-source.md`, generierte Kommandoreferenz und `tools/CONTRACT.md`
## Akzeptanzkriterien
- [x] Für die Fixture-Seite enthält die abgeleitete `.md` weder „requires authorization“ noch „Exit editor mode“ noch „Add to Plans“, aber die Überschrift „OSLicense Module“ und alle Zeilen der Cmdlet-Tabelle.
- [x] Das gespeicherte `.html` ist byte-identisch mit der Antwort des (Test-)Servers.
- [x] Die Ausgabe enthält eine `CHECK`-Zeile mit der Quell-URL aus `original_content_git_url`.
- [x] `raw fetch https://learn.microsoft.com/de-de/…` holt `…/en-us/…`; der Header nennt beide URLs.
- [x] Eine URL ohne passenden Handler ergibt byte-identische Ausgaben wie vorher (bestehende Tests von `raw fetch` unverändert grün).
- [x] Zwei Läufe über dieselben Bytes ergeben byte-identische `.md`, abgesehen vom Zeitstempel.
- [x] Eine doppelte Registrierung (gleicher Host, gleiches Muster) scheitert beim Import, im Test geprüft.
- [x] Ein Handler, der per Instanz-Einstellung abgeschaltet ist, greift nicht. Eine Hinweiszeile der Instanz erscheint als `CHECK`.
- [x] `pytest`, `docs verify`, `instructions verify` grün; CI grün (Läufe 657 und 658 auf `2213d68`).
## Versionsteil
**`--minor`** - gebaut als `10.0.0-beta.3`. Neues Verhalten nur für URLs mit Handler. Kein Kommando, Flag oder maschinenlesbares Format entfällt (der Header ist Erfassungsmetadaten). Was schon in `raw/` liegt, bleibt unberührt. Drop-in in beide Richtungen.
## Kette
Kette „Beschaffung und Konfiguration“
- Vorgänger: #208
- Nachfolger: #210
Changelog: Stub ausgearbeitet (2026-10-09, Design-Sitzung zu #87/#200, Stand 9.0.0). Der Stub zerfiel in vier Teile: Bereinigung beim Ableiten, Standardform der URL, Umfang (Unterseiten) und Hinweise an den Agenten. Der Umfang ist nach #209 ausgelagert. Neu ist der Body als Site-Handler-Registry im Stack nach dem Muster der Filter aus #199. Offene Fragen stehen im Body. Teil der Kette „Beschaffung und Konfiguration“ (#205 → #206 → #207 → #208 → #200 → #209 → #169). status/incoming entfernt; gesetzt sind area/kb, kind/decision, prio/planned, size/M, dazu status/blocked (durch #206).
Der ursprüngliche Stub, wörtlich:
Analog zu #199 ein Gedanke: auch bestimmte URLs können Sonderbehandlungen vertragen. Beispiel:
Hier stolpert Luna über einen Anmeldehinweis, vermutlich zur Seitenbearbeitung oder ähnliches. man könnte hier besodere Anweisungen unterbringen, die aus einer Kombination des Stacks und der Instanz entstehen, basis ist die URL.
Ansatz:
Genereller Handler für learn.microsoft.com darüber, wie mit solchen pages/urls umzugehen ist (ignoriere den Auth Hinweis soundso, benutze immer en-us als quelle)
Erweiteter Handler für ein Powershell-Modul mit einer Regex in folgender Spielart (pseudocode zur illustration, sie ist unvollständig): learn.microsoft.com/./powershell/module/. (erstelle einen Index des moduls, berücksichtige subpages)
**Changelog:** Stub ausgearbeitet (2026-10-09, Design-Sitzung zu #87/#200, Stand `9.0.0`). Der Stub zerfiel in vier Teile: Bereinigung beim Ableiten, Standardform der URL, Umfang (Unterseiten) und Hinweise an den Agenten. Der Umfang ist nach #209 ausgelagert. Neu ist der Body als Site-Handler-Registry im Stack nach dem Muster der Filter aus #199. Offene Fragen stehen im Body. Teil der Kette „Beschaffung und Konfiguration“ (#205 → #206 → #207 → #208 → #200 → #209 → #169). `status/incoming` entfernt; gesetzt sind `area/kb`, `kind/decision`, `prio/planned`, `size/M`, dazu `status/blocked` (durch #206).
Der ursprüngliche Stub, wörtlich:
> Analog zu #199 ein Gedanke: auch bestimmte URLs können Sonderbehandlungen vertragen. Beispiel:
>
> https://learn.microsoft.com/en-us/powershell/module/oslicense/?view=windowsserver2025-ps
>
> Hier stolpert Luna über einen Anmeldehinweis, vermutlich zur Seitenbearbeitung oder ähnliches. man könnte hier besodere Anweisungen unterbringen, die aus einer Kombination des Stacks und der Instanz entstehen, basis ist die URL.
>
> Ansatz:
>
> 1. Genereller Handler für learn.microsoft.com darüber, wie mit solchen pages/urls umzugehen ist (ignoriere den Auth Hinweis soundso, benutze immer en-us als quelle)
> 2. Erweiteter Handler für ein Powershell-Modul mit einer Regex in folgender Spielart (pseudocode zur illustration, sie ist unvollständig): learn.microsoft.com/.*/powershell/module/.* (erstelle einen Index des moduls, berücksichtige subpages)
torben
changed title from handler für bestimmte URLs to Site-Handler für `raw fetch`: Standardform der URL, Bereinigung und Hinweise pro Website, als Code-Registry im Stack2026-10-09 21:42:32 +00:00
Changelog: Die drei Fragen sind entschieden (2026-10-10): Handler als Code im Stack, zuerst nur Bereinigung mit einer CHECK-Zeile für die Quell-URL, Hinweiszeilen der Instanz als Text. Neu ist, dass die Bausteine als Daten ausdrückbar geschnitten werden, für #210 (Handler der Instanz, auf Wunsch des Betreibers angelegt). Dazu ein Kriterium für die Quell-URL-Zeile. In der Kette ist #210 eingefügt, der Nachfolger ist jetzt #210 statt #209. kind/decision → kind/build, blockiert bleibt es durch #206/#207.
**Changelog:** Die drei Fragen sind entschieden (2026-10-10): Handler als Code im Stack, zuerst nur Bereinigung mit einer `CHECK`-Zeile für die Quell-URL, Hinweiszeilen der Instanz als Text. Neu ist, dass die Bausteine als Daten ausdrückbar geschnitten werden, für #210 (Handler der Instanz, auf Wunsch des Betreibers angelegt). Dazu ein Kriterium für die Quell-URL-Zeile. In der Kette ist #210 eingefügt, der Nachfolger ist jetzt #210 statt #209. `kind/decision` → `kind/build`, blockiert bleibt es durch #206/#207.
Der Kettenvorgänger #208 ist geschlossen (2026-10-11, 10.0.0-beta.2), die Blocker #206 und #207 waren es schon. status/blocked ist entfernt, die Blocker-Zeile im Body entsprechend ersetzt. Hinweis für den Bau: Seit #208 entsteht eine neue Instanz-Einstellung als Abschnitt in config_shapes.SETTINGS_SECTIONS (Stufe pro Feld), nicht als eigener Record oder eigene Datei. Das betrifft Entwurf 5 und die Zeile zu config_shapes.py unter „Betroffene Dateien“.
Der Kettenvorgänger #208 ist geschlossen (2026-10-11, `10.0.0-beta.2`), die Blocker #206 und #207 waren es schon. `status/blocked` ist entfernt, die Blocker-Zeile im Body entsprechend ersetzt. Hinweis für den Bau: Seit #208 entsteht eine neue Instanz-Einstellung als Abschnitt in `config_shapes.SETTINGS_SECTIONS` (Stufe pro Feld), nicht als eigener Record oder eigene Datei. Das betrifft Entwurf 5 und die Zeile zu `config_shapes.py` unter „Betroffene Dateien“.
Neue Registry tools/chemenu/sites/: ein Modul je Website, der längste Pfad gewinnt, ein spezieller Handler erbt vom allgemeinen, eine doppelte Registrierung scheitert beim Import. Die Bausteine (URL-Ersetzungen, Regeln für entfallende Elemente, Texthinweise mit Bedingung) sind auch als Daten ausdrückbar - Vorarbeit für #210.
Handler learn-microsoft (Gebietsschema en-us, Seitenbedienung und Anmeldehinweis entfallen, CHECK mit der Quell-URL) und learn-microsoft-powershell-module (zusätzlich die Zahl der Cmdlet-Seiten, nur auf Modul-Übersichtsseiten).
Header: site: und, wenn die Standardform abweicht, requested_url; das .html bleibt byte-genau. URLs ohne Handler und raw derive sind unverändert.
Neuer Einstellungsabschnitt sites (Stufe instance): Handler abschalten, Gebietsschema wählen, bis zu drei Hinweiszeilen je Host-Muster.
Abweichungen vom Entwurf (im Body vermerkt): Modul-Pfadmuster auf Übersichtsseiten eingegrenzt; Fixture als lizenzneutraler Nachbau unter tools/chemenu/tests/fixtures/learn_microsoft/; zusätzlicher Doku-Bereich reference-config-sites.
**Changelog:** `raw fetch` kennt jetzt Site-Handler (Version `10.0.0-beta.3`, Commit `2213d68`, CI-Läufe 657 und 658 grün).
- Neue Registry `tools/chemenu/sites/`: ein Modul je Website, der längste Pfad gewinnt, ein spezieller Handler erbt vom allgemeinen, eine doppelte Registrierung scheitert beim Import. Die Bausteine (URL-Ersetzungen, Regeln für entfallende Elemente, Texthinweise mit Bedingung) sind auch als Daten ausdrückbar - Vorarbeit für #210.
- Handler `learn-microsoft` (Gebietsschema `en-us`, Seitenbedienung und Anmeldehinweis entfallen, `CHECK` mit der Quell-URL) und `learn-microsoft-powershell-module` (zusätzlich die Zahl der Cmdlet-Seiten, nur auf Modul-Übersichtsseiten).
- Header: `site:` und, wenn die Standardform abweicht, `requested_url`; das `.html` bleibt byte-genau. URLs ohne Handler und `raw derive` sind unverändert.
- Neuer Einstellungsabschnitt `sites` (Stufe `instance`): Handler abschalten, Gebietsschema wählen, bis zu drei Hinweiszeilen je Host-Muster.
- Doku nachgezogen: `raw/CONTRACT.md`, `tools/README.md`, `docs/how-to/ingest-a-source.md`, `docs/reference/configuration.md`, Kommandoreferenz.
- Abweichungen vom Entwurf (im Body vermerkt): Modul-Pfadmuster auf Übersichtsseiten eingegrenzt; Fixture als lizenzneutraler Nachbau unter `tools/chemenu/tests/fixtures/learn_microsoft/`; zusätzlicher Doku-Bereich `reference-config-sites`.
Changelog: Abschluss - der Body beschreibt jetzt den gebauten Stand (Bausteine als Daten statt Funktionen, Vererbung über parent=, Header-Feld url: statt fetched_url, Erweiterungspunkte für #209/#169 nicht vorgebaut, Pfadmuster des Modul-Handlers eingegrenzt), verifiziert durch CI-Läufe 657 und 658 auf 2213d68 (10.0.0-beta.3).
Prüfung auf veraltete Doku nach dem grünen Lauf: raw/CONTRACT.md, tools/README.md, docs/how-to/ingest-a-source.md, docs/reference/configuration.md und der Kommando-Record von raw fetch stimmen mit dem Code überein; keine docs/explanation/-Seite und keine Installationsanweisung ist berührt, daher kein weiterer Publish. Beobachtung ohne Handlungsbedarf in diesem Paket: wiki-ingest erwähnt CHECK-Zeilen nicht - weder die der Filter (#199) noch die der Site-Handler; jede Zeile sagt selbst, was zu tun ist, und raw/CONTRACT.md verlangt, sie vor dem Annehmen zu beachten.
**Changelog:** Abschluss - der Body beschreibt jetzt den gebauten Stand (Bausteine als Daten statt Funktionen, Vererbung über `parent=`, Header-Feld `url:` statt `fetched_url`, Erweiterungspunkte für #209/#169 nicht vorgebaut, Pfadmuster des Modul-Handlers eingegrenzt), verifiziert durch CI-Läufe 657 und 658 auf `2213d68` (`10.0.0-beta.3`).
Prüfung auf veraltete Doku nach dem grünen Lauf: `raw/CONTRACT.md`, `tools/README.md`, `docs/how-to/ingest-a-source.md`, `docs/reference/configuration.md` und der Kommando-Record von `raw fetch` stimmen mit dem Code überein; keine `docs/explanation/`-Seite und keine Installationsanweisung ist berührt, daher kein weiterer Publish. Beobachtung ohne Handlungsbedarf in diesem Paket: `wiki-ingest` erwähnt `CHECK`-Zeilen nicht - weder die der Filter (#199) noch die der Site-Handler; jede Zeile sagt selbst, was zu tun ist, und `raw/CONTRACT.md` verlangt, sie vor dem Annehmen zu beachten.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Befund (gegen den Baum und die echte Seite geprüft, 2026-10-09 - Stand vor diesem Paket)
raw fetchleitete aus jedem HTML mit derselben Funktion ab (tools/chemenu/web_capture.py,content_root/derive_text), bewusst ohne Lesbarkeits-Heuristik, damit gleiche Bytes immer gleichen Text ergeben. Regeln pro Website gab es nicht.web_capture.fetch+derive_textaufhttps://learn.microsoft.com/en-us/powershell/module/oslicense/?view=windowsserver2025-psergab vor der Überschrift:Der Hinweis steht im HTML in
<p class="… authentication-determined not-authenticated">innerhalb vondiv.notification. Die Seite blendet ihn per JavaScript ein oder aus, eine Ableitung ohne JavaScript behielt ihn. Die Tabelle der Cmdlets kam sauber an.Die Seite nennt ihre Quelle:
<meta name="original_content_git_url" content="https://github.com/MicrosoftDocs/windows-powershell-docs/blob/live/docset/winserver2025-ps/OSLicense/OSLicense.md">.Das Muster einer Registry mit „neues Format = Modul + Registrierung + Tests“ und Hinweisen nur in der Ausgabe gab es seit #199 (
tools/chemenu/filters/).Ziel
Für URLs einer bekannten Website holt
raw fetchdieselbe Seite in Standardform, leitet sauberen Text ab und gibt die Hinweise, die für diese Website gelten, alsCHECK-Zeilen aus - nur wenn sie zutreffen. Was ein Handler deterministisch erledigen kann, erledigt er selbst. Der Agent bekommt keine Anweisung wie „ignoriere den Anmeldehinweis“, weil der Hinweis im Text gar nicht mehr vorkommt.Entscheidungen des Betreibers (2026-10-10)
original_content_git_urlwird nicht abgerufen. EineCHECK-Zeile nennt die Quell-URL. Den Abruf der Quelle bauen wir erst, wenn die Bereinigung nicht reicht.raw/.Entwurf (gebauter Stand)
Registry
tools/chemenu/sites/, ein Modul pro Website, nach dem Muster vonfilters/;_load_modules()importiert jedes Modul des Pakets. Ein Handler ist einSite-Datensatz mitname,host(exakt, klein geschrieben), optionalem Pfadmusterpath(Regex gegen den Anfang des URL-Pfads),summary,parentund drei Bausteinen:rewrites: die Standardform als Liste von Regex-Ersetzungen (Rewrite) auf der URL;{locale}in der Ersetzung ist die Einstellung der Instanz;drop: Regeln (web_capture.Rule), welche Elemente vor der Ableitung entfallen - nach Tag,id,class, Attribut (mit Wert) und optional „innerhalb von Tag“, deterministisch, keine Heuristik;checks: höchstens dreiCheck-Zeilen, jede Text mit optionaler Bedingung - „die Seite hat<meta name=…>mit Inhalt“ ({meta}im Text) oder „ein Selektor trifft mindestens ein Element“ ({count}im Text).Abweichung vom ursprünglichen Entwurf: Dort standen
canonical(url)undchecks(html, url)als Funktionen, Python-Hooks für den Rest, und als Beispiel-Bedingung „wenn einedrop-Regel getroffen hat“. Gebaut ist alles als Daten, weil beide Handler damit vollständig ausdrückbar waren und #210 genau diese Form braucht; Python-Hooks gibt es keine, und die Bedingungen sind die zwei, die die Handler brauchten (Meta, Selektor-Zahl). Die im Entwurf genannten Erweiterungspunkte für #209 (Unterseiten) und #169 (Login) sind nicht als Hooks vorgebaut: Sie kommen als weitere Felder desSite-Datensatzes, wenn diese Pakete gebaut werden.Auswahl: Unter den eingeschalteten Handlern eines Hosts gewinnt der mit dem längsten passenden Pfadmuster. Ein spezieller Handler erbt über
parent="<name>";registerspeichert ihn flachgelegt (die Bausteine des Elternteils zuerst), sodass zur Laufzeit keine Kette durchlaufen wird. Registrierungsfehler (ValueErrorbeim Import): gleicher Name, gleicher Host mit gleichem Muster, unbekannter oder fremd-hostigerparent, mehr als drei Checks auch zusammen mit dem Elternteil. (Ursprünglich als KlassenvererbungPowerShellModule(LearnMicrosoft)skizziert; als Datenfeld ist es dieselbe Semantik in der Form, die #210 braucht.)Wo er greift:
raw fetch <url>undraw fetch --html <datei> --url <url>; nicht inraw derive. Das.htmlbleibt byte-genau die Antwort, nur die Ableitung ändert sich. Beim Abruf wird die Standardform geholt; aus ihr kommenurl:im Header und der Dateistamm, die eingegebene URL steht alsrequested_url:direkt nachurl:, wenn sie abweicht, undsite: <name>nachcharset:. (Der Entwurf nannte das Feldfetched_url; der bestehende Header heißturl:, daran wurde nichts umbenannt.) Bei--htmlgelten diedrop-Regeln und Checks, die URL bleibt aber wie eingegeben, weil kein Abruf stattfand. Eine URL ohne Handler verhält sich unverändert.Erste Handler (
sites/learn_microsoft.py):learn-microsoft: Gebietsschema-Segment → Einstellunglocale(Standarden-us), Queryview=bleibt;drop:#ms--content-header,#action-panel,#article-header,[unauthorized-private-section],.authentication-determined,#site-user-feedback-footer,#ms--inline-notifications,#assertive-live-region,#polite-live-region; eineCHECK-Zeile mit der Quell-URL ausoriginal_content_git_url, wenn vorhanden.learn-microsoft-powershell-module: Pfad/<locale>/powershell/module/<modul>/- nur Modul-Übersichtsseiten, nicht alles unter/powershell/module/, damit die Zählung nicht auf Cmdlet-Seiten anschlägt; erbt; bis #209 eine weitereCHECK-Zeile mit der Zahl der Cmdlet-Links in der Tabelle.Anteil der Instanz: Abschnitt
sitesder Einstellungen (Stufeinstance,config_shapes.SITES, dokumentiert indocs/reference/configuration.md):disabled: Handler-Namen, die nicht greifen; ein unbekannter Name ist ein Fehler (Exit 1 vor jedem Abruf), damit ein Tippfehler keinen Handler eingeschaltet lässt;locale: Gebietsschema der Standardform;notes: je Eintraghost, optionalpath, undlines- höchstens drei Zeilen zu je höchstens 300 Zeichen, ausgegeben alsCHECKnach denen des Handlers, auch für Hosts ohne Handler.Betroffene Dateien
tools/chemenu/sites/__init__.py(Registry, Auswahl, Bausteine, Einstellungen),sites/learn_microsoft.pytools/chemenu/web_capture.py:Rule,prune,count_matches,meta_content;derive_text/derive_documentnehmen optionaledrop-Regeln,siteundrequested_url, ohne Änderung für den Fall ohnetools/chemenu/commands/raw/fetch.pysamt Kommando-Record (Zusammenfassung, Header-Felder, Site-Handler, ON FAILURE für einen kaputtensites-Abschnitt)tools/chemenu/config_shapes.py(SITESinSETTINGS_SECTIONS),reference_doc.CONFIG_REGIONS(reference-config-sites),docs/reference/configuration.mdtools/chemenu/tests/test_sites.py; Fixture als lizenzneutraler Nachbau der Seite mit derselben Struktur untertools/chemenu/tests/fixtures/learn_microsoft/- nicht untertestfiles/, weiltestfiles/anraw deriveverfüttert wirdraw/CONTRACT.md§ Getting a URL in,tools/README.md,docs/how-to/ingest-a-source.md, generierte Kommandoreferenz undtools/CONTRACT.mdAkzeptanzkriterien
.mdweder „requires authorization“ noch „Exit editor mode“ noch „Add to Plans“, aber die Überschrift „OSLicense Module“ und alle Zeilen der Cmdlet-Tabelle..htmlist byte-identisch mit der Antwort des (Test-)Servers.CHECK-Zeile mit der Quell-URL ausoriginal_content_git_url.raw fetch https://learn.microsoft.com/de-de/…holt…/en-us/…; der Header nennt beide URLs.raw fetchunverändert grün)..md, abgesehen vom Zeitstempel.CHECK.pytest,docs verify,instructions verifygrün; CI grün (Läufe 657 und 658 auf2213d68).Versionsteil
--minor- gebaut als10.0.0-beta.3. Neues Verhalten nur für URLs mit Handler. Kein Kommando, Flag oder maschinenlesbares Format entfällt (der Header ist Erfassungsmetadaten). Was schon inraw/liegt, bleibt unberührt. Drop-in in beide Richtungen.Kette
Kette „Beschaffung und Konfiguration“
torben referenced this issue2026-10-09 21:41:18 +00:00
Changelog: Stub ausgearbeitet (2026-10-09, Design-Sitzung zu #87/#200, Stand
9.0.0). Der Stub zerfiel in vier Teile: Bereinigung beim Ableiten, Standardform der URL, Umfang (Unterseiten) und Hinweise an den Agenten. Der Umfang ist nach #209 ausgelagert. Neu ist der Body als Site-Handler-Registry im Stack nach dem Muster der Filter aus #199. Offene Fragen stehen im Body. Teil der Kette „Beschaffung und Konfiguration“ (#205 → #206 → #207 → #208 → #200 → #209 → #169).status/incomingentfernt; gesetzt sindarea/kb,kind/decision,prio/planned,size/M, dazustatus/blocked(durch #206).Der ursprüngliche Stub, wörtlich:
handler für bestimmte URLsto Site-Handler für `raw fetch`: Standardform der URL, Bereinigung und Hinweise pro Website, als Code-Registry im StackChangelog: Die drei Fragen sind entschieden (2026-10-10): Handler als Code im Stack, zuerst nur Bereinigung mit einer
CHECK-Zeile für die Quell-URL, Hinweiszeilen der Instanz als Text. Neu ist, dass die Bausteine als Daten ausdrückbar geschnitten werden, für #210 (Handler der Instanz, auf Wunsch des Betreibers angelegt). Dazu ein Kriterium für die Quell-URL-Zeile. In der Kette ist #210 eingefügt, der Nachfolger ist jetzt #210 statt #209.kind/decision→kind/build, blockiert bleibt es durch #206/#207.Der Kettenvorgänger #208 ist geschlossen (2026-10-11,
10.0.0-beta.2), die Blocker #206 und #207 waren es schon.status/blockedist entfernt, die Blocker-Zeile im Body entsprechend ersetzt. Hinweis für den Bau: Seit #208 entsteht eine neue Instanz-Einstellung als Abschnitt inconfig_shapes.SETTINGS_SECTIONS(Stufe pro Feld), nicht als eigener Record oder eigene Datei. Das betrifft Entwurf 5 und die Zeile zuconfig_shapes.pyunter „Betroffene Dateien“.Changelog:
raw fetchkennt jetzt Site-Handler (Version10.0.0-beta.3, Commit2213d68, CI-Läufe 657 und 658 grün).tools/chemenu/sites/: ein Modul je Website, der längste Pfad gewinnt, ein spezieller Handler erbt vom allgemeinen, eine doppelte Registrierung scheitert beim Import. Die Bausteine (URL-Ersetzungen, Regeln für entfallende Elemente, Texthinweise mit Bedingung) sind auch als Daten ausdrückbar - Vorarbeit für #210.learn-microsoft(Gebietsschemaen-us, Seitenbedienung und Anmeldehinweis entfallen,CHECKmit der Quell-URL) undlearn-microsoft-powershell-module(zusätzlich die Zahl der Cmdlet-Seiten, nur auf Modul-Übersichtsseiten).site:und, wenn die Standardform abweicht,requested_url; das.htmlbleibt byte-genau. URLs ohne Handler undraw derivesind unverändert.sites(Stufeinstance): Handler abschalten, Gebietsschema wählen, bis zu drei Hinweiszeilen je Host-Muster.raw/CONTRACT.md,tools/README.md,docs/how-to/ingest-a-source.md,docs/reference/configuration.md, Kommandoreferenz.tools/chemenu/tests/fixtures/learn_microsoft/; zusätzlicher Doku-Bereichreference-config-sites.Changelog: Abschluss - der Body beschreibt jetzt den gebauten Stand (Bausteine als Daten statt Funktionen, Vererbung über
parent=, Header-Feldurl:stattfetched_url, Erweiterungspunkte für #209/#169 nicht vorgebaut, Pfadmuster des Modul-Handlers eingegrenzt), verifiziert durch CI-Läufe 657 und 658 auf2213d68(10.0.0-beta.3).Prüfung auf veraltete Doku nach dem grünen Lauf:
raw/CONTRACT.md,tools/README.md,docs/how-to/ingest-a-source.md,docs/reference/configuration.mdund der Kommando-Record vonraw fetchstimmen mit dem Code überein; keinedocs/explanation/-Seite und keine Installationsanweisung ist berührt, daher kein weiterer Publish. Beobachtung ohne Handlungsbedarf in diesem Paket:wiki-ingesterwähntCHECK-Zeilen nicht - weder die der Filter (#199) noch die der Site-Handler; jede Zeile sagt selbst, was zu tun ist, undraw/CONTRACT.mdverlangt, sie vor dem Annehmen zu beachten.