Skip to content

v0.6.0

Choose a tag to compare

@malkreide malkreide released this 30 Jul 14:56
40053ea

[0.6.0] - 2026-07-30

Reparatur-Release. In 0.5.0 lieferten drei der sechs Tools nichts
meteo_current für jede Station einen 404, meteo_forecast und
meteo_school_check gar keine Daten. Drei unabhängige Ursachen, zwei davon
Änderungen bei Datenquellen, eine ein Fehler im Server selbst. Alle drei sind
live gegen die echten APIs verifiziert.

Für Clients nicht breaking: Tool-Namen, Parameter und Rückgabetypen sind
unverändert. Einzig die Beschreibung von meteo_forecast wurde präzisiert
(siehe «Changed»), was tool-hashes.json ändert.

Behoben

  • Ortsnamen mit Zusatz waren gar nicht auflösbar
    (#37). Die
    Geocoding-API kennt nur einzelne Ortsnamen und liefert für
    «Schulhaus Leutschenbach Zürich» nichts. _geocode() schickte den vollen
    String in beiden Versuchen — der «Fuzzy»-Retry liess nur die
    Sprachrestriktion weg und kürzte die Anfrage nie. Damit scheiterten auch die
    Beispiele, die die Tools selbst dokumentieren (meteo_forecast-Docstring und
    die location-Beschreibung von meteo_school_check).

    Neu werden bei Misserfolg führende Tokens nach und nach weggelassen —
    Schweizer Ortsangaben sind konventionell Gattungswort… Ort Stadt, das
    verallgemeinert also von spezifisch nach allgemein und endet bei der Stadt.
    Zusätzlich wird jedes führende Token einzeln probiert, aber nur mit
    Namensprüfung
    : «Leutschenbach» → Leutschenbach wird angenommen,
    «Schulhaus» → Dübendorf / Schulhaus Wil verworfen. Ohne diese Prüfung
    bekäme eine Zürcher Anfrage stillschweigend Wetter aus einer anderen
    Gemeinde — schlimmer als der bisherige harte Fehler.

    Live verifiziert:

    Anfrage Ergebnis
    Schulhaus Leutschenbach Zürich Leutschenbach, ZH (47.4175, 8.5648)
    Sportanlage Heerenschürli Zürich Zurich, ZH (47.3667, 8.5500)
    Zürich / Bern unverändert exact, ein einziger Request

    match_type kennt dafür neu "shortened" — Aufrufende sehen damit, dass die
    Antwort allgemeiner ist als die Frage. Ein Volltreffer löst weiterhin genau
    einen Request aus; gekürzt wird nur, wenn der volle String scheitert.

  • meteo_forecast und meteo_school_check lieferten gar nichts mehr
    (#35). Open-Meteo hat
    die provider-eigenen Pfade abgeschafft; /v1/meteoswiss antwortet mit 404.
    Modelle werden neu über models= auf /v1/forecast gewählt.

    Ein reiner URL-Tausch reicht nicht, denn keines der MeteoSwiss-Modelle
    liefert, was die beiden Tools zusagen. Live gemessen für
    meteoswiss_icon_seamless (ICON-CH1 + ICON-CH2):

    • Reichweite 5 Tage. forecast_days=16 liefert darüber hinaus nur
      Nullwerte — das ist der ICON-CH2-Horizont, kein Parameterproblem.
      meteo_forecast verspricht aber bis zu 16 Tage.
    • Kein UV-Index, auch nicht stündlich (0 von 72 Werten über 3 Tage).
      Open-Meteo bezieht UV aus CAMS, nicht aus dem Modelloutput.
      meteo_school_check warnt aber ab UV 6.

    Der Server holt deshalb neu beide Modelle und mischt sie entlang der
    Zeitachse: MeteoSwiss ICON gewinnt überall, wo es einen Wert hat, None
    fällt auf best_match zurück. Dieselbe Regel erledigt die 5-Tage-Grenze und
    die UV-Lücke. Gemischt wird bewusst über Zeitstempel statt Listenindizes —
    der ICON-Block ist kürzer, und ein Indexversatz würde Werte still auf den
    falschen Tag schieben.

    Die Herkunft steht in jeder Antwort, statt im Ungefähren zu bleiben: die
    Markdown-Fussnote und die JSON-Felder modell / modell_details weisen aus,
    welche Tage aus MeteoSwiss ICON stammen, ab wann best_match übernimmt und
    dass UV durchgehend von dort kommt. Fällt der ICON-Request aus, trägt
    best_match die Antwort allein — und sagt das ebenfalls, statt einen
    Totalausfall zu produzieren.

    Kein Test hätte das finden können: die Unit-Tests deckten ausschliesslich
    Geocoding-Fehlerpfade ab, der erfolgreiche Prognosepfad war komplett
    ungetestet. Neu 11 Tests für Merge-Logik (inklusive Zeitachsen-Versatz),
    Provenance-Label, den vollen Hybrid-Pfad in Markdown und JSON, den
    ICON-Ausfall und die UV-Herkunft in meteo_school_check.

Changed

  • meteo_forecast-Beschreibung präzisiert — sie nannte pauschal
    «MeteoSwiss ICON-CH1/CH2-EPS» und verschwieg damit, dass Tage jenseits von 5
    und der UV-Index aus best_match stammen. tool-hashes.json entsprechend neu
    generiert (Rug-Pull-Signal, SEC-022). Für Clients nicht breaking: Parameter
    und Rückgabetyp sind unverändert, days akzeptiert weiterhin 1–16.

  • meteo_current lieferte für jede Station 404
    (#33). Die STAC-Item-ID
    ist der nackte Stationscode in Kleinschreibung (…/items/klo); der Server
    stellte ihm die Collection-ID voran (…/items/ch.meteoschweiz.ogd-smn-klo).
    Live gegen die BGDI-API verifiziert: /items/klo → 200, die Präfix-Variante
    und die Grossschreibung → je 404. Die URL wurde an drei Stellen dupliziert
    (Fetch, Fehlermeldung, JSON-Provenance) — jetzt einmal in
    _smn_stac_item_url().

    Beim Beheben kamen drei weitere Fehler zum Vorschein, die der 404 verdeckt
    hatte — sie hätten nach dem URL-Fix plausibel aussehende, aber falsche Daten
    geliefert:

    • Die Asset-Auswahl konnte nie greifen. Gesucht wurde nach /now/ im
      Pfad, doch die Granularität steckt im Dateinamen
      (ogd-smn_klo_t_now.csv); ein Verzeichnis /now/ existiert nicht. Der
      Fallback nahm daraufhin das erste CSV im Item — d_historical, also
      Tageswerte ab 1980, ausgegeben als «aktuelle Beobachtung». Neu wird gezielt
      _t_now gewählt, ersatzweise _t_recent; gibt es beides nicht, ist das ein
      Fehler statt eines stillen Griffs ins Archiv.
    • Der Zeitstempel war immer . Gelesen wurde time/Date/datum, die
      OGD-CSV führt aber reference_timestamp.
    • Die Zeile «Luftdruck (reduziert auf Meeresniveau)» blieb immer leer.
      prestah0 gibt es in der CSV nicht; der QNH-Wert heisst pp0qnhs0.

Tests

Alle drei Fehler oben hatten einen Test, der sie hätte finden müssen, aber so
formuliert war, dass auch der Fehlerfall ihn erfüllte. Das ist das eigentliche
Thema dieses Releases:

  • meteo_current (live): prüfte "KLO" in result or "Zürich" in result
    beides steht auch in der Fallback-Fehlermeldung. Der Test lief also durch
    einen Totalausfall hindurch grün. Verlangt jetzt echte Messwerte.

  • meteo_forecast / meteo_school_check: der erfolgreiche Prognosepfad war
    komplett ungetestet, abgedeckt waren nur Geocoding-Fehlerpfade. Zudem mockten
    die Tests die eigene Endpoint-Konstante — sie konnten das Abschalten upstream
    gar nicht bemerken.

  • _geocode (live): prüfte nur einen Koordinatenbereich (8.4–8.7), den
    Dübendorf mit 8.62 ebenfalls erfüllt — der Fehlgriff auf eine andere Gemeinde
    wäre durchgewinkt worden. Verlangt jetzt den Ortsnamen im Ergebnis.

  • Cache-Isolation zwischen Tests. Der TTL-Cache ist modul-global und
    überlebte den einzelnen Test. Ein Test sah dadurch Einträge eines früheren,
    umging sein eigenes respx-Mock und schlug je nach Ausführungsreihenfolge fehl
    — oder bestand aus dem falschen Grund. Eine autouse-Fixture räumt jetzt vor
    und nach jedem Test auf.