Commit Graph
4 Commits
Author SHA1 Message Date
Benjamin SutterandClaude Opus 5 30daa77937 feat(livia): Runde 10 Prompt 2 — eine Leadliste, dynamische Quellen, zeitliche Relevanz
Livia arbeitet nicht mehr neben dem Leadbestand, sondern in ihn hinein.

- Systemzugänge tragen Titel, Beschreibung und Adresse; die Liste zeigt je
  Eintrag nur noch Aktiv/Inaktiv und Lesen/Schreiben — kein Berechtigungsbalken,
  kein Auge-Icon, keine Lese-/Schreibgruppen
- Die Quellenregistry ist dynamisch: Der Lauf liest genau die aktiven
  Lesezugänge mit Adresse aus Livias Personalblatt. Für die drei gepflegten
  Quellen greift weiterhin ihr eigener Leser, für alles andere ein allgemeiner —
  eine Übersichtsseite, bis zu zehn Unterseiten, kein Spider. Freie Adressen
  werden auf http/https geprüft und gegen interne Netze gesperrt
- Manuell abgelegte PDF- und Word-Dokumente fliessen in denselben Lauf. Text
  wird beim Ablegen nativ extrahiert (ZIP + Flate über DecompressionStream,
  ohne neue Abhängigkeit), Datei und Text liegen in IndexedDB
- Neuer harter Filter «Zeitliche Relevanz»: das Modell beurteilt die
  Ereigniszeit der Veränderung, nicht das Publikationsdatum. «unknown» fällt
  bewusst nicht durch — ein erfundenes Datum wäre die schlechtere Antwort
- Quellentypen und Beobachtungsraum sind Chips mit Freitext; jeder Wert lässt
  sich einzeln entfernen, auch die vorgegebenen
- Info-Knopf bei «Zeitliche Relevanz» und «Mindestrelevanz» erklärt, wie der
  Wert entsteht — ohne erfundene Prozentgewichte
- Gefundene Leads gehen in den zentralen Signalbestand statt in eine zweite
  Ergebnisliste; die Herkunft steht am Signal (origin: RESEARCH_RUN)
- Der Lauf erzeugt einen echten Protokolleintrag mit den Zahlen des Laufs
- Lead-Detail: zeitliche Einordnung mit Fundstelle, semantisches Suchprofil bei
  Chancen mit «Matching starten», und bei Risiko ausdrücklich «Kein internes
  Objekt eindeutig zugeordnet» statt einer beliebigen Mock-Immobilie
- Aufgabenliste nach §11 bereinigt, «Unsichere Signale in Review Queue legen»
  von Nora übernommen

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 23:42:59 +02:00
Benjamin SutterandClaude Opus 5 f0ef9c57d4 feat(livia): das verwendete Modell steht im Ergebnis
Die Modellwahl läuft über eine Umgebungsvariable im Hosting-Dashboard. Damit
sah man nirgends in der Anwendung, welches Modell gerade urteilt — und eine
Einstellung, die man nur im Dashboard prüfen kann, prüft niemand.

Der Refresh gibt das Modell jetzt zurück, die Kopfzeile zeigt es neben dem
Zeitstempel. Wer wissen will, ob die Umstellung angekommen ist, sieht es dort,
wo er ohnehin hinschaut.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 19:28:04 +02:00
Benjamin SutterandClaude Opus 5 f53f3be1e8 fix(livia): Dateiendungen in den Importen der serverlosen Funktion
Erster Produktionslauf schlug mit HTTP 500 fehl, lokal lief derselbe Code
grün. Ursache: Vercel kompiliert jede Datei einzeln statt sie zu bündeln, und
weil das Projekt `"type": "module"` ist, verlangt Nodes ESM-Lader explizite
Dateiendungen in relativen Importen. Vite löst im Entwicklungsbetrieb
grosszügiger auf und verdeckt das.

Das ist genau die Klasse Fehler, die kein Typecheck und kein Test findet — nur
ein echter Aufruf gegen die deployte Funktion.

Geprüft gegen Produktion: HTTP 200, 20 Einträge aus 3/3 Quellen in 24
Sekunden, Beurteilung läuft, Originalquellen verlinkt, keine Laufzeitfehler.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 17:41:48 +02:00
Benjamin SutterandClaude Opus 5 2a0ba287f6 feat(livia): Research-PoC — drei reale Zürcher Quellen live
Livia liest jetzt tatsächlich aus dem Netz statt aus Mockdaten. Ein Knopf
«Research aktualisieren» ruft serverseitig drei Quellen ab, beurteilt die
Einträge in einem einzigen LLM-Aufruf und zeigt nur an, was plausibel zu
Flächenbedarf oder Flächenfreisetzung führen könnte.

Kein Crawler, kein Scheduler, keine Queue, keine Datenbank. Der Hoster kann
bereits serverlose Funktionen — es hat bisher nur niemand eine gebraucht.
Deshalb genügt eine einzige Datei unter `api/`, drei Abruffunktionen, eine
Normalisierung und ein Analyseaufruf.

Quellen, alle drei live geprüft:
- Zürcher Handelskammer, 10 Artikel
- Greater Zurich Area, 9 Artikel
- Zefix / Open Data Kanton Zürich, CSV direkt

Zur Zefix-Quelle eine Feststellung, die von der Aufgabenstellung abweicht: die
CSV enthält keine Firmennamen. Sie führt Tageszahlen von Neugründungen je
NOGA-Branche für den Kanton Zürich. Daraus lässt sich kein Unternehmenslead
bauen, sondern nur ein aggregiertes Frühsignal zum Zielmarkt — und genau so
wird es übergeben. Namen zu erfinden, um das erwartete Format zu treffen, wäre
die eine Sache, die Livia nie tun darf.

Die drei Quellen stehen im Frontend unter «Angebundene Kanäle & Systeme» mit
Status und anklickbarem Originallink; jeder erzeugte Lead verlinkt zusätzlich
die Seite, aus der er stammt. Die Adressen kommen aus derselben Liste, die der
Abruf benutzt — der angezeigte Link kann damit nicht von dem abweichen, was
tatsächlich gelesen wurde.

Der Textextraktor sucht den Artikeltext im engsten passenden Container. Ohne
das standen bei der Handelskammer Telefonnummern und Öffnungszeiten am Anfang
jedes Textes, und das Modell hätte die Fusszeile mitbeurteilt.

Der LLM-Schlüssel liegt ausschliesslich serverseitig in `ANTHROPIC_API_KEY`.
Fehlt er, sagt die Oberfläche offen, dass gelesen, aber nicht beurteilt wurde —
statt eine leere Liste als «nichts gefunden» auszugeben.

Für die lokale Entwicklung mountet ein Vite-Plugin dieselbe Handler-Datei, die
Vercel in der Produktion ausliefert; es gibt keine zweite Fassung des
Endpoints. `tsconfig.api.json` nimmt `api/` in `tsc -b` auf, damit ein
Tippfehler dort nicht erst beim Deployment auffällt.

Geprüft: tsc 0 Fehler, eslint 0 Fehler/0 Warnungen, 423/423 Tests grün, Build
erfolgreich, Live-Lauf im Browser mit 20 real gelesenen Einträgen aus 3/3
Quellen ohne Laufzeitfehler. Die LLM-Beurteilung selbst ist mangels Schlüssel
noch ungetestet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 14:23:35 +02:00