Changelog
GitHubJede nennenswerte Änderung, Release für Release. Dieselbe Datei liegt im Repository und ist in alle 19 Sprachen übersetzt.
[1.204.0] — 2026-08-15
Hinzugefügt — ein “Einrichtungs-Doktor”-Panel in den Einstellungen, das einen unvollständigen oder Beispieldaten-CV/Profil meldet.
Hinzugefügt
- Einstellungen → Einrichtungs-Doktor prüft jetzt tokenfrei dein
cv.mdundconfig/profile.ymlund listet blockierende Probleme (fehlende Dateien/Felder) und Warnungen (übrig gebliebene Beispiel-/Platzhalterdaten, hartkodierte Kennzahlen) — damit du eine unvollständige Einrichtung erkennst, bevor sie deine Scans und Zuschnitte schwächt. Nur lesend; per Klick neu ausführbar.
Hinweise
- Neue nur lesende
GET /api/cv-sync-checkleitet dascv-sync-check.mjsdes Elternprojekts weiter, das Text + einen Exit-Code ausgibt (kein--json); die Route parst dessen stabileERROR:/WARN:-Zeilen leicht zu{ok, errors[], warnings[]}— das Banner, nicht der Exit-Code, entscheidet über den Erfolg. Weiches Scheitern{available:false}bei eigenständigen Installationen.tests/cv-sync-check-route.test.mjs. Suite: 2602.
[1.203.0] — 2026-08-15
Hinzugefügt — ein “früheren Lebenslauf wiederverwenden?”-Hinweis im CV Studio.
Hinzugefügt
- Wenn du im CV Studio eine gespeicherte Stellenanzeige öffnest, vergleicht die App sie jetzt mit deinen anderen gespeicherten Anzeigen (deterministische Wortüberlappung, null Tokens) und sagt dir, ob die nächste ähnlich genug ist, um den zugeschnittenen Lebenslauf wiederzuverwenden, ihn mit Änderungen wiederzuverwenden oder einen neuen zuzuschneiden — damit du für eine bereits anvisierte Rolle nicht von vorn beginnst.
Hinweise
- Neue nur lesende
GET /api/jds/:name/reuseleitet dasjd-similarity.mjsdes Elternprojekts weiter (Jaccard-Überlappung + Senioritäts-Guard; JSON{decision, score, reason}) einmal pro früherer Anzeige (Fan-out auf 25 begrenzt, bester Treffer gewinnt); weiches Scheitern{available:false}, wenn Skript oder frühere Anzeigen fehlen.tests/jd-similarity-reuse-route.test.mjs. Suite: 2594.
[1.202.0] — 2026-08-15
Hinzugefügt — finde das ATS-Jobboard eines Unternehmens von #/portals aus und verfolge es.
Hinzugefügt
- Auf #/portals gibst du einen Firmennamen ein, und die App prüft Greenhouse, Ashby und Lever auf dessen öffentliches Board — null LLM, kein Browser — und zeigt die Boards, die existieren und aktuell ≥1 Job listen. Ein Klick fügt das gewählte Board den Firmen hinzu, die dein Scanner beobachtet. Das Prüfen ist schreibgeschützt; die Schreibaktion in
portals.ymlerfolgt nur beim Klick auf Hinzufügen.
Hinweise
- Neue
server/lib/discover-ats.mjs(Slug-Probe mit festem Host und charset-validiert über das DNS-gepinntesafeGet, ≤12 Proben/Anfrage) +POST /api/portals/discover(nur lesen) undPOST /api/portals/track(explizites Schreiben:withFileLock+ chirurgisches Text-Splicing + Re-Parse-Guard + atomares Umbenennen; nur bekannte ATS-Hosts, idempotent). Verwendet die Adapter-Registry des Scanners wieder. i18n ×17.tests/discover-ats-resolver.test.mjs+tests/discover-ats-route.test.mjs. Suite: 2588.
[1.201.0] — 2026-08-15
Behoben — ein Tracker mit lokalisierten oder abweichenden Spaltenüberschriften wird nicht mehr leer angezeigt.
Behoben
- Wenn deine
data/applications.mdnicht-englische oder abweichende Überschriften nutzt — spanischempresa/puesto/estado/fecha/enlaceoderposition/stage/link— las der Tracker sie unter den falschen Schlüsseln und zeigte leere Spalten Firma / Rolle / Status / Datum / Link. Diese Überschriften werden nun auf die kanonischen Feldnamen gefaltet, sodass der Tracker korrekt anzeigt. Ein rein englischer Tracker wird wie zuvor geparst.
Hinweise
- Neue
HEADER_ALIASES-Tabelle + eine Normalisierungsfaltung inparseApplications(server/lib/parsers.mjs); unbekannte oder bereits kanonische Überschriften passieren unverändert.tests/tracker-header-aliases.test.mjs. Suite: 2563.
[1.200.0] — 2026-08-15
Hinzugefügt — ein “Noch aktiv?”-Check mit einem Klick für ATS-gehostete Jobs in deinem Tracker.
Hinzugefügt
- Auf #/tracker zeigt eine Bewerbung, deren URL ein Greenhouse- / Lever- / Ashby- / Workday- / SmartRecruiters-Posting ist, jetzt einen “Noch aktiv?”-Button. Ein Klick fragt das öffentliche JSON des ATS selbst ab — null Tokens, kein Browser — und zeigt Aktiv / Abgelaufen / Unbekannt, damit du tote Ausschreibungen findest, ohne jede zu öffnen. Konservativ ausgelegt: nur ein eindeutiges 404/410 gilt als Abgelaufen; alles Mehrdeutige bleibt Unbekannt (nie ein falsches Abgelaufen).
Hinweise
- Neue
server/lib/liveness-core.mjs+liveness-api.mjsund eine nur lesendeGET /api/liveness?url=(keine Schreibvorgänge, kein LLM). SSRF-sicher: Die URL läuft durchisValidJobUrl, dann wird die ATS-API nur über das DNS-gepinntesafeGetmit festem Host und charset-validierten Pfadsegmenten erreicht.tests/liveness-core.test.mjs+tests/liveness-route.test.mjs. Suite: 2557.
[1.199.0] — 2026-08-15
Behoben — breite Tabellen scrollen jetzt seitwärts, statt abgeschnitten zu werden.
Behoben
- Auf der Scan-Seite (und in allen anderen Tabellen — Tracker, Statistik, Nutzung, Dashboard) wurde eine Tabelle, die breiter als das Fenster war, ohne Bildlaufleiste abgeschnitten, sodass die rechten Spalten unerreichbar waren. Breite Tabellen zeigen jetzt bei Bedarf eine horizontale Bildlaufleiste, sodass jede Spalte in jeder Breite erreichbar bleibt.
Hinweise
.table-wrapinpublic/css/components.csswechselte vonoverflow: hiddenzuoverflow-x: auto(wie der bestehende.reports-scroll-Container); der abgerundete Rahmen bleibt erhalten.tests/table-wrap-scroll.test.mjs. Suite: 2540.
[1.198.0] — 2026-08-15
Hinzugefügt — Scan-Wiederholungen nutzen jetzt exponentielles Backoff, Jitter und respektieren das Retry-After eines Rate-Limiters.
Hinzugefügt
- Wenn ein Jobboard mitten im Scan kurz drosselt oder fehlschlägt (HTTP 429 / 5xx), wartet die Wiederholung jetzt mit exponentiellem Backoff + Jitter statt einer festen kurzen Verzögerung — ein ausgelastetes Board wird nicht im gleichen Takt weiter gehämmert, und gleichzeitige Wiederholungen kollidieren nicht erneut im Gleichschritt. Ein
Retry-Aftervom Board wird respektiert (aber geklemmt, damit ein feindseligesRetry-After: 86400nicht den ganzen Scan blockiert). Permanente Fehler (404, abgelehnte Weiterleitungen) schlagen weiterhin sofort fehl — unverändert.
Hinweise
- Neue
parseRetryAfterMs()und die reinecomputeRetryDelayMs()inserver/lib/http-json.mjs;fetchJsonerfasst jetzt.retryAfterbei einer nicht-ok-Antwort, undfetchJsonWithRetrynimmt ein optionalesmaxDelayMs(Standard 8000).tests/http-json.test.mjs(+9). Suite: 2536.
[1.197.0] — 2026-08-14
Hinzugefügt — verfolge ein Getro-VC-Jobboard allein über seine careers_url; die Collection-ID löst sich automatisch auf.
Hinzugefügt
- Ein verfolgtes Getro-Board (b2venture, Earlybird, Point Nine, …) braucht keine von Hand herausgesuchte numerische
getro_collectionmehr. Gib die eigenecareers_urldes Boards an, und die ID löst sich beim ersten Scan automatisch aus dieser Seite auf — ein einziges SSRF-sicheres GET liest die numerischenetwork.iddirekt aus den eingebetteten Seitendaten. Eine explizitegetro_collectiongewinnt weiterhin und überspringt den Abruf vollständig.
Hinweise
- Neue
httpsCareersUrl(),extractCollectionId()und das asynchroneresolveCollectionId()inserver/lib/sources/getro.mjs; die Board-Seite wird übersafeGet(DNS-fixiert, größenbegrenzt) abgerufen, und die aufgelöste ID bleibt perassertGetroUrlan den Hostapi.getro.comgebunden. Der Adapter passt jetzt auf einenprovider: getro-Eintrag mit einer https-careers_url, auch ohne ID.tests/sources-getro.test.mjs(+8). Suite: 2527.
[1.196.0] — 2026-08-14
Behoben (Sicherheit) — der Workday-Adapter validiert einen api-Endpunkt über seinen Hostnamen, nicht über eine Teilzeichenfolge.
Behoben
- Ein Workday-
api:-Wert inportals.ymlwird jetzt nur akzeptiert, wenn sein Hostnamemyworkdayjobs.com(oder eine.myworkdayjobs.com-Subdomain) ist. Die alte Prüfung war ein Teilzeichenfolgen-Match, sodass jede URL, die die Zeichenfolge nur enthielt — z. B.https://example.com/?x=myworkdayjobs.com— durchkam und als Endpunkt verwendet worden wäre. Echte Workday-Endpunkte sind nicht betroffen. (Von CodeQL gemeldet, #443.)
Hinweise
- Neues
isWorkdayApi()parst die URL und prüft den Host (server/lib/portals/adapters/workday.mjs).tests/workday-adapter-endpoint.test.mjs(+1). Suite: 2522.
[1.195.0] — 2026-08-14
Performance (Scanner) — die Repost-Erkennung bleibt bei großen Scan-Historien schnell.
Performance
- Die Duplikat-Erkennung entartet auf einer großen
scan-history.tsvnicht mehr zu O(N²). Die Titel-Gruppierung pro Firma war eine verschachtelte Schleife, die pro Paar ein vollesroleFuzzyMatchzahlte; jetzt ist es ein invertierter Index — Zeilen in einem Durchgang nach exaktem Titel bucketen, dann Fuzzy-Match nur zwischen VERSCHIEDENEN Buckets, die einen unterscheidenden (Nicht-Baseline-)Token teilen. Die Ausgabe ist identisch — dieselben Repost-Cluster — bewiesen durch einen Differenztest gegen den alten Algorithmus über 200+ zufällige Historien.
Hinweise
groupRowsByTitleinserver/lib/detect-reposts.mjs(für den Differenztest exportiert).tests/detect-reposts-grouping.test.mjs(+2). Suite: 2521.
[1.194.0] — 2026-08-14
Behoben (Scanner) — Workday-Karriereseiten mit einer Ein-Segment-URL werden jetzt korrekt gescannt.
Behoben
- Der Workday-Adapter parst nun Karriere-URLs, deren Pfad ein einzelnes Segment ist — z. B.
https://parsons.wd5.myworkdayjobs.com/Search,.../KBR_Careers,.../Careers. Zuvor fiel die Site aufExternalzurück, der Adapter traf den falschen CXS-Endpunkt, und eine Probe konnte gesund aussehen, ohne etwas zurückzugeben. Er nimmt jetzt das erste nicht-leere Pfadsegment als Site (und lässt ein Sprachpräfix wieen-USweg); der dokumentierte Fall/en-US/Externalbleibt unverändert. (Gemeldet in #255.)
Hinweise
- Strukturelles Pfad-Parsing in
server/lib/portals/adapters/workday.mjs.tests/workday-adapter-endpoint.test.mjs(+7). Suite: 2519.
[1.193.0] — 2026-08-14
Hinzugefügt (Statistik) — ein “Stille nach dem Gespräch”-Tab, der Gespräche zum Nachfassen zeigt.
Hinzugefügt
- Ein Stille nach dem Gespräch-Tab in
#/stats: Gespräche, die nach einem Kulanzfenster (Standard 30 Tage) verstummt sind, verbindet deine aktiven Gespräche und den Tracker — mit der Stille-Dauer, dem letzten Gesprächsdatum und dem Grund. Eine sanfte Erinnerungs-/Abschlussliste; nur Vorschläge, nie eine Absage-Behauptung. Ohne Token.
Hinweise
- Neue Route
GET /api/stats/rejection-latency(fail-soft{available:false}).tests/stats-rejection-latency-route.test.mjs(+2). +10 i18n-Schlüssel ×17;#/statshelp-hint von 7→8 Tabs. Suite: 2510.
[1.192.0] — 2026-08-14
Hinzugefügt (cv-studio) — ein “Fakten im Lebenslauf prüfen”-Wächter, der Zahlen findet, die du nie hattest.
Hinzugefügt
- Eine Fakten im Lebenslauf prüfen-Karte in
#/cv-studio: füge einen angepassten Lebenslauf oder ein Anschreiben ein und prüfe jede behauptete Kennzahl und Tatsache gegen deinen echten Lebenslauf, dein Profil und den Two-Pager. Du bekommst ein pass / warn / block-Urteil plus die genauen erfundenen Kennzahlen, unbelegten Fakten und verbotenen / hinweisenden Phrasen. Kein LLM; nichts wird geschrieben.
Hinweise
- Neue Route
POST /api/cv-studio/verify-facts: schreibt den Text in eine Einweg-Temp-Datei und führtverify-cv-facts.mjsaus, wobei sie dem JSON-Urteil vertraut, auch wenn das Skript bei block mit 1 endet.tests/cv-studio-verify-facts-route.test.mjs(+4). +15 i18n-Schlüssel ×17. Suite: 2508.
[1.191.0] — 2026-08-14
Hinzugefügt (Statistik) — ein “Was als Nächstes lernen”-Tab, der die zuerst zu lernenden Fähigkeiten rankt.
Hinzugefügt
- Ein Was als Nächstes lernen-Tab in
#/stats: eine tracker-weite Auswertung — die fehlenden Fähigkeiten, die am häufigsten eine schwache Passung versenkt haben, gewichtet (nach 5−Passungswert je Bericht) und gestuft Critical / High / Medium — plus die von deinem CV/Profil bereits abgedeckten. Schreibgeschützt, nur Vorschläge, ohne Token.
Hinweise
- Neue Route
GET /api/stats/upskill({ error }-Feld bei zu wenig Daten; fail-soft{available:false}).tests/stats-upskill-route.test.mjs(+3). +15 i18n-Schlüssel ×17. Suite: 2504.
[1.190.0] — 2026-08-14
Hinzugefügt (Tracker) — ein “Firmenhistorie”-Panel, das zeigt, welche Firmen dir tatsächlich antworten.
Hinzugefügt
- Eine Firmenhistorie-Karte auf
#/tracker: wähle eine Firma und erhalte schreibgeschützte Belege — wie sehr sie dir geantwortet hat (schweigt dir gegenüber / gemischt / hat schon geantwortet) und ob dieselbe Stelle immer wieder neu ausgeschrieben wird — verbunden aus Tracker, Follow-ups und Scan-Historie. Ohne Token; der Scanner wird nie aufgerufen.
Hinweise
- Neue Route
GET /api/stats/company-history[?company=](fail-soft{available:false}).tests/stats-company-history-route.test.mjs(+3). +18 i18n-Schlüssel ×17. Suite: 2501.
[1.189.0] — 2026-08-14
Behoben (Scanner) — als römische Ziffern geschriebene Senioritätsstufen zählen jetzt auch bei nicht-lateinischen Titeln.
Behoben
- Der Tier-Klassifikator hinter
skip_tiersliest jetzt ein Stufensuffix in römischen Ziffern (I / II / III / IV / V) nach dem Berufswort in jeder Schrift — „Инженер III”, „エンジニア I”, „Ingénieur IV” — nicht nur nach ASCII-Wörtern. Zuvor wurde eine Stufenzahl nach einem nicht-lateinischen Wort ignoriert und die Stelle fiel auf mid, sodassskip_tiers: [senior]oder[entry]sie verpasste.
Hinweise
- Schriftunabhängiges Lookbehind in
server/lib/classify-tier.mjs; toter doppelterSr.-Matcher entfernt.tests/classify-tier.test.mjs(+1). Suite: 2498.
[1.188.0] — 2026-08-14
Behoben (UI) — die primären Aktionsschaltflächen kleben nicht mehr am Seitentitel-Untertitel.
Behoben
- Die primäre Aktions-/Steuerzeile auf Wöchentliches Interview-Digest, Finanzierte Unternehmen, Portale, Karriereplan und Berufsorientierung hat jetzt einen passenden oberen Abstand, sodass die Schaltfläche unter dem Untertitel Luft bekommt, statt daran zu stoßen.
Hinweise
- Regressions-Guard
tests/lead-row-top-margin.test.mjs(+5). Suite: 2497.
[1.187.0] — 2026-08-14
Behoben (Scanner) — die skip_tiers-Einstellung greift wieder: Stellen, die du nach Seniorität überspringen wolltest, werden verworfen.
Behoben
- Eine
skip_tiers:-Liste inportals.yml(z. B.skip_tiers: [intern, entry]) wird jetzt beim Scan beachtet. Der Titel jeder Stelle wird in eine Senioritätsstufe (intern / entry / mid / senior) eingeordnet und verworfen, wenn die Stufe auf deiner Liste steht. Zuvor liefen die Titel- / Standort- / Inhalts- / Trust-Filter, aber kein Stufenfilter, sodassskip_tiersstill ignoriert wurde. Titel ohne Level-Wort fallen auf mid (also verwirftskip_tiers: [mid]auch die meisten gewöhnlichen Stellen), und der Klassifizierer liest das LINKESTE Level-Wort.
Hinweise
- Neues reines Modul
server/lib/classify-tier.mjs(classifyTier+buildTierFilter), eingebunden in die Filterketten des EN- und RU-Scanners.tests/classify-tier.test.mjs(+7). Suite: 2492.
[1.186.0] — 2026-08-14
Hinzugefügt (CV Studio) — ein “Skill-Gap”-Panel: welche der geforderten Fähigkeiten einer Stelle dein CV nennt, andeutet oder fehlt.
Hinzugefügt
- Ein neues Skill-Gap-Panel in CV Studio. Wähle eine gespeicherte Stellenbeschreibung, und es sortiert jede geforderte Fähigkeit in im CV genannt, im CV angedeutet oder fehlend — Wortvergleich ohne LLM, nichts wird geschrieben. Ein Hinweis auf geringe Zuverlässigkeit erscheint, wenn die Stelle keinen klaren Anforderungsabschnitt hatte.
Hinweise
- Neuer
GET /api/jds/:name/skill-gap(der Stellenname wird pfad-bereinigt und unterjds/bestätigt, bevor er ein Argument wird; weicher Fallback auf{available:false}ohne das Skript). +13 i18n-Schlüssel ×17. Tests:tests/jds-skill-gap-route.test.mjs(+4, inkl. Path-Traversal-Ablehnung). Suite: 2485.
[1.185.0] — 2026-08-14
Hinzugefügt (Statistik) — ein Tab “Funnel & Tempo”: wie sich dein Funnel mit dem Markt vergleicht und wie schnell du zwischen Stufen vorankommst.
Hinzugefügt
- Ein neuer Tab Funnel & Tempo in Statistik zeigt deine Antwort- und Interview-Raten neben Markt-Benchmark-Bereichen (mit den Hinweisen zu kleiner Stichprobe und Selektionsbias), eine Warteliste laufender Bewerbungen jenseits des typischen Erst-Antwort-Fensters und Median-Tage pro Stufe (Beworben → Geantwortet → Interview → Angebot) — langsame Zeilen werden rechtszensiert, damit sie die Mediane nicht verzerren. Schreibgeschützt und ohne Tokens; liest nur deinen eigenen Tracker.
Hinweise
- Neuer
GET /api/stats/funnel(weicher Fallback auf{available:false}ohne das Skript). +18 i18n-Schlüssel ×17. Tests:tests/stats-funnel-route.test.mjs(+2). Suite: 2481.
[1.184.0] — 2026-08-14
Behoben (UI) — die Schnellaktions-Kacheln im Dashboard richten sich jetzt in einem gleichmäßigen Raster aus.
Behoben
- Im Dashboard (Kommandozentrale) wurde eine Gruppe aus 3 Kacheln breiter dargestellt als eine aus 4, sodass die Abschnitte eine unregelmäßige rechte Kante hatten. Jede Gruppe verwendet jetzt gleich breite Spalten (4 auf breitem Bildschirm, herunter auf 3 / 2 / 1, wenn das Fenster schmaler wird), sodass alle Kacheln gleich groß sind und ihre rechten Kanten fluchten.
Hinweise
- Nur CSS (
.qa-grid: festesrepeat(N, minmax(0,1fr))stattauto-fill). Abgesichert durchtests/dashboard-grid-align.test.mjs(+2). Suite: 2479.
[1.183.0] — 2026-08-14
Hinzugefügt (Scanner) — schlauere Dublettenerkennung: dieselbe Stelle, mit einem Tracking-Link neu eingestellt, erscheint nicht mehr doppelt.
Hinzugefügt
- Der Scanner erkennt eine Stelle jetzt an einem kanonischen URL-Schlüssel, sodass dieselbe Stelle, neu eingestellt mit einem Tracking-Parameter (
?utm_…,gclid, …), überhttpvshttpsoder mit abschließendem Schrägstrich /#Fragment, als die eine Stelle behandelt wird, die sie ist — keine doppelte Zeile in Scan-Ergebnissen oder Pipeline und keine verschwendete Bewertung einer bereits gesehenen Stelle. Wirklich unterschiedliche Stellen (eine erhaltene funktionale id wiegh_jid) zählen weiterhin getrennt.
Hinweise
- Neues
server/lib/url-key.mjs, eingebunden in die Dedup beider Scanner und den Pipeline-Writer. Normalisiert bewusst zurückhaltend — führt nie zwei verschiedene Stellen zusammen. Tests:tests/url-key.test.mjs(+5),tests/parsers.test.mjs(+1). Suite: 2477 (+6).
[1.182.0] — 2026-08-14
Behoben (Scanner) — Gehaltsspannen werden jetzt in jeder Sprache gleich angezeigt.
Behoben
- Gehaltsangaben in Scan- und Tracker-Zeilen verwenden die sprachneutralen Symbole ≥ und ≤ (z. B.
≥ 120000 EUR,≤ 90000) statt der englischen Wörter „from” / „up to”, die unübersetzt in nicht-englische Oberflächen durchsickerten. Gilt für jedes Board mit einseitiger Spanne (Getro, Remotli, Manfred, Agentic Jobs, JustJoin, Jobicy); zweiseitige Spannen (100000–150000 USD) waren schon neutral.
Hinweise
- Nur Anzeige — der Gehaltsfilter des Clients parst die Zahlen unabhängig vom Präfix, das Filtern bleibt unverändert. Suite: 2471.
[1.181.0] — 2026-08-14
Hinzugefügt (Scanner) — Getro-Jobboards zeigen jetzt Gehalt, alle Standorte und Remote-Stellen.
Hinzugefügt
- Der Getro-Scanner (Talent-Netzwerk-Boards von Fonds) zeigt jetzt bei jeder Stelle ein Gehalt (Jahresspanne + Währung), listet alle Standorte statt nur des ersten und markiert Remote-Stellen. Eine Getro-Stelle in Scan und Tracker trägt nun dieselben Gehalts- + Standortdetails wie die übrigen Boards.
Hinweise
- Nur Scanner; keine neue Abhängigkeit, keine Änderung an Route / CSP / SSRF. Tests:
tests/sources-getro.test.mjs(+5). Suite: 2470 (+5).
[1.180.0] — 2026-08-14
Behoben (MITTEL, Berichte) — die #/reports-Liste ist jetzt eine Tabelle, und eine echte Bewertung, die ein Machine-Summary-Platzhalter verdeckte, wird wiederhergestellt.
Behoben
- Die
#/reports-Liste ist eine Tabelle (Bericht · Datum · Legitimität · Bewertung), kein 4-Karten-Raster. Ein langer Chip „Bewertung nicht erkannt” drückte die Titelspalte fast auf null, und dasoverflow-wrap: anywheredes Kartentitels brach den Berichtsnamen Zeichen für Zeichen um. Jetzt hat jedes Feld eine eigene Spalte, die Namenszelle bricht an Wortgrenzen um, und die Tabelle scrollt auf schmalen Viewports horizontal (neuer.reports-scroll-Container). Neuer i18n-Schlüsselrep.colReport×17. - Eine echte Bewertung im Text (
**Итоговый балл:** 1.8 / 5) wird nicht mehr durch einen Machine-Summary-Platzhalter (score: —) verdeckt. Trug der## Machine Summary-Block eine nicht-numerische oder außerhalb des Bereichs liegende Bewertung, belegte sie den geparsten Bewertungsplatz und blockierte den Fett-Wertform-Fallback, sodass der Bericht „Bewertung nicht erkannt” zeigte, obwohl im Text ein echtesX / 5stand.parseReportHeaderstellt nun die Wertform aus dem Text wieder her, wenn keine brauchbare Zahl übrig blieb (Schritt 4.5).
Hinweise
- Nur Client + Parser; keine Änderung an Route / CSP / SSRF / Eltern-Schreibzugriff. Tests:
tests/reports-table.test.mjs(+5),tests/report-header-locale.test.mjs(+2). Suite: 2465 (+7).
[1.179.0] — 2026-08-13
Geändert (LOW, Scanner) — 20 duplizierte HTML-Entitäten-Decoder auf das gemeinsame Modul zusammengeführt (Paritäts-Nachlauf, schließt die Worklist).
Geändert
- 20 Scraping-Scan-Quellen trugen je einen eigenen
decodeEntities/decodeXmlEntities(+ einenfromCodePoint-Helfer) — Kopien, die auseinandergedriftet waren (drei konnten einenRangeErrorwerfen, in v1.172.0 behoben; andere ließen NUL/C0 zu oder parstena2;falsch). Alle laufen nun über das eineserver/lib/html-entities.mjs(XML-1.0-Char-sicherer Decoder), was ~237 Zeilen Duplizierung entfernt. Die 8 RSS-artigen Quellen erhielten die -Dekodierung (zuvor nur 5 Entitäten); das absichtliche Doppel-Dekodieren von cryptocurrencyjobs bleibt per Alias erhalten.hhbehält seinen Decoder (behandelt—/–, außerhalb der gemeinsamen 6). Ein neuer Wächter-Test schlägt fehl, wenn eine Quelle wieder einen lokalen Decoder anlegt.
Hinweise
- Verhaltenserhaltende Refaktorierung; keine Änderung an Route / CSP / SSRF / Eltern-Schreibzugriff. Tests:
tests/decoder-consolidation.test.mjs(+2). Suite: 2458 (+2).
[1.178.0] — 2026-08-13
Behoben (LOW, Eltern-Parität) — zwei veraltete Konstanten an das Elternprojekt angeglichen (PARENT-SYNC GAP #4 + #5).
Behoben
- Browser-User-Agent (GAP #4) —
BROWSER_LIKE_USER_AGENT(von workable/workday/oraclecloud/a16z/eightfold gesendet, um WAF/Bot-Gates zu passieren) von Chrome 131 auf 151 angehoben, passend zumuser-agent.mjsdes Elternprojekts; ein veralteter Build wird häufiger blockiert. Durch einenChrome major ≥ 151-Test abgesichert. - Tracker-Status-FALLBACK (GAP #5) — der Notfall-
FALLBACKinstates.mjs(nur genutzt, wenn die Live-templates/states.ymlunlesbar ist — frischer Klon / CI-isolierte Wurzel) erhielt die türkischen Status-Aliase des Elternprojekts (#2615): değerlendirildi, başvuruldu, yanıt verildi, mülakat, teklif, reddedildi, iptal edildi, uygun değil, kabul edildi/işe alındı. In Produktion lieferte die Live-Datei sie bereits.
Hinweise
- Nur zwei Konstanten; keine Änderung an Route / CSP / SSRF / Eltern-Schreibzugriff. Tests:
tests/http-json.test.mjs(+1) +tests/states.test.mjs(+1). Suite: 2456 (+2).
[1.177.0] — 2026-08-13
Behoben (MEDIUM, Scanner) — csod (Cornerstone) lieferte 0 Jobs bei Tenants, die die Such-API hinter Session-Cookies sperren (parent #2769, PARENT-SYNC GAP #1).
Behoben
- Manche Cornerstone-Tenants setzen Session-Cookies auf der Bootstrap-Startseite der Karriereseite und antworten der Such-API mit
401 CSOD Unauthorized, sofern diese Cookies nicht zusammen mit dem anonymen Bearer-Token zurückkommen.sources/csod.mjsliest den Bootstrap nun über einen neuenfetchResponse-Helfer, baut aus dessenSet-Cookie-Werten einenCookie-Header (cookieHeaderFrom— nur name=value, Jar-Semantik) und spielt ihn auf dem Such-POST erneut ein. Nur gleicher Origin (Host angeheftet +redirect:'error'), sodass Session-Cookies nie zu Dritten gelangen; ein Tenant ohne Cookies verhält sich wie zuvor.
Hinweise
- Neu
server/lib/http-json.mjs::fetchResponse(additiv; bestehende Quellen unberührt). Keine Änderung an Route / CSP / SSRF / Eltern-Schreibzugriff. Tests:tests/sources-parity-v1118a.test.mjs(+1). Suite: 2454 (+1).
[1.176.0] — 2026-08-13
Behoben (MEDIUM, Berichte) — ein Score unter einem fetten Label, das die RU-Tabelle nicht listet, zeigte weiter “Score not detected” (FIND-5).
Behoben
- Zwei RU-Berichte schrieben den Score als
**Итоговый балл:** 1.8 / 5/**Скор:** 1.8 / 5— fette Labels, dieREPORT_LABELS.runicht aufführt (kennt nur „Оценка”/„Балл”), sodass der Score ungeparst blieb. Statt die Synonymliste zu erweitern, greiftparseReportHeadernun auf die Wertform zurück: ein Bruch über das /5-Raster unter EINEM BELIEBIGEN fetten Label. Sie ist sprachunabhängig, immun gegen eine Überschrift (kein**, kein/5-Wert) und weist ein Datum wie5/5/2026ab (negativer Lookahead auf den Nenner).
Hinweise
- Nur Server-Parser; keine Änderung an Route / CSP / SSRF / Eltern-Schreibzugriff. Tests:
tests/report-header-locale.test.mjs(+2). Suite: 2453 (+2).
[1.175.0] — 2026-08-13
Behoben (LOW, Härtung) — ein Regressionswächter für die FIND-3-SEO-Beschreibung + ein nullsicheres Seriositäts-Strip (AI-Review-Nachbereitung).
Behoben
- Paritätswächter der SEO-Beschreibung — der v1.174.0-Fix, der ein fest codiertes “~55” im
meta.descjeder Sprache durch einen registry-abgeleiteten{adapters}-Platzhalter ersetzte, hatte keinen Test und konnte bei der nächsten Locale-Bearbeitung still regredieren. Der neue CI-isoliertetests/site-meta-desc-parity.test.mjsschlägt fehl, wenn eine der 17site/src/i18n/*.jsonden Platzhalter verliert oder eine Zahl erneut fest codiert, oder wennLanding.astroihn nicht mehr in alle drei Beschreibungs-Metas interpoliert. - Nullsicheres Seriositäts-Strip —
stripEmphasisliefert''für einen nullish-Eingang statt der Zeichenkette “undefined” (die Felder sind string-initialisiert, also Verteidigung in der Tiefe).
Hinweise
- Test + ein einzeiliger Wächter im Parser; keine Änderung an Route / CSP / SSRF / Eltern-Schreibzugriff. Tests:
tests/site-meta-desc-parity.test.mjs(+3). Suite: 2451 (+3).
[1.174.0] — 2026-08-13
Behoben (HIGH, Berichte) — lokalisierte Berichte zeigten „Score not detected”; die SEO-Beschreibung war veraltet.
Behoben
- Score-Parsing (FIND-1) — ein nicht-englischer Bericht, dessen H1 das Score-Label-Wort enthält (
# Оценка вакансии: <Titel>), verwechselt diesen Titel nicht mehr mit dem Score.parseReportHeaderverankert nun am lokalisierten fetten Label (**Оценка:** 1.5 / 5), überspringt Überschriftszeilen und verlangt das Label direkt vor seinem Doppelpunkt — so zeigen RU-Berichte, die „Score not detected” anzeigten, ihren echten Score. - Seriositäts-Chip (FIND-2) — Markdown-Hervorhebung wird aus dem Wert entfernt, der Chip zeigt „High Confidence” statt „** High Confidence”.
- Score-Überlauf — eine Score-Zeile mit angehängtem Statustext („1.8, Status: Evaluated, …“) wird auf den reinen Score komprimiert;
.score-pillerhält eine Kein-Umbruch-/Overflow-Grenze und die Titelspalte kann schrumpfen, sodass ein farbiger Chip nie über den Kartenrand hinausläuft. - SEO-Beschreibung (FIND-3) — die meta / OG / Twitter-Beschreibungen von cvstart.org (alle 17 Sprachen) codierten „Scan ~55 job boards” fest, während der Fließtext das echte Registry zählte („~75”). Die Beschreibung fügt nun die Registry-abgeleitete Zahl ein und driftet nicht mehr.
Hinweise
- Server-Parser + Client-Render/CSS + Site-i18n; keine Änderung an Route / CSP / SSRF / Eltern-Schreibzugriff. Tests:
tests/report-header-locale.test.mjs(+4). Suite: 2448 (+4).
[1.173.0] — 2026-08-13
Hinzugefügt (LOW, Konfiguration) — Hermes wird in die erkannte KI-CLI-Liste aufgenommen (career-ops-Parität).
Hinzugefügt
- Der Tab
#/config→ „KI-CLI-Werkzeuge” erkennt nun Hermes (Nous Research), die neu unterstützte Agent-Laufzeit des Elternprojekts (Binärdateihermes). Die feste Allowlist inserver/lib/routes/cli-detect.mjswächst von 10 auf 11 Werkzeuge; die Erkennung bleibt ein schreibgeschützter PATH-Scan (es wird nie eine Binärdatei ausgeführt).
Hinweise
- Keine Änderung an i18n / Route / CSP / SSRF / Eltern-Schreibzugriff; die Liste ist fest, niemals Eingabe. Suite: 2444 (der cli-detect-Canary von 10 auf 11 aktualisiert).
[1.172.0] — 2026-08-13
Behoben (MEDIUM, Scanner) — eine fehlerhafte HTML-Entität konnte eine Scan-Quelle zum Absturz bringen (career-ops #2150-Parität).
Behoben
- Die Quellen
oraclecloud,gemunddassaultdekodierten numerische HTML-Entitäten mit einer schwachenNumber.isFinite-Prüfung vorString.fromCodePoint— eine Referenz über0x10FFFF(z. B.�aus einem fehlerhaften oder feindlichen Feed) warf einen nicht abgefangenenRangeErrorund brach das gesamte Parsen dieser Quelle ab. Ein gemeinsames Modulserver/lib/html-entities.mjs(spiegelt das_html-entities.mjsdes Elternprojekts) beschränkt numerische Referenzen nun auf die XML-1.0-§2.2-Char-Menge, sodassString.fromCodePointniemals werfen kann, und trennt Hex- und Dezimalabgleich, sodassa2;nicht mehr falsch geparst wird. Die drei Quellen importieren es.
Hinweise
- Keine Änderung für gültige Feeds; keine Änderung an JS / i18n / Route / CSP / SSRF / Eltern-Schreibzugriff. Die Konsolidierung der ~20 verbliebenen Decoder-Kopien in den Quellen wird in
qa/PARENT-SYNC-WORKLIST-v1.26.0.mdverfolgt. - Tests:
tests/html-entities.test.mjs(+7). Suite: 2444 (+7).
[1.171.0] — 2026-08-13
Geändert (NIEDRIG, Design-System) — Typo-Skala + z-index-Layer-Tokens (D-4, erster Schritt). Größen und Stapelung waren pro Komponente literal.
Geändert
- z-index-Layer —
--z-*-Tokens (--z-topbar…--z-skiplink) eingeführt und jedes z-index-Literal migriert. Werte erhalten, Stapelung identisch; ein neuer Canary verbietet neue Magic Numbers. - Typo-Skala —
--font-size-*-Rampe (xs 11…2xl 28, Basis = Inter 15px); die Kern-Größen migriert (keine visuelle Änderung). Werte außerhalb der Rampe migrieren schrittweise (docs/UX-ROADMAP.md).
Hinweise
- Nur CSS-Token; keine Änderung an Verhalten/JS/i18n/Route/CSP/SSRF/Schreibzugriff. Keine Pixel-Änderung.
tests/design-tokens-scale.test.mjs(+3). Suite: 2437 (+3).
[1.170.0] — 2026-08-13
Hinzugefügt (NIEDRIG) — ehrliche ETA-Hinweise bei langen KI-Generierungen (P4-ETA). Aufwändige Generierungen (Karriereplan ~40 s, Orientierung / Markt / Networking ~30 s, Two-Pager ~20 s) zeigten nur „Generiere…” ohne Dauer-Gefühl.
Hinzugefügt
- Neben jedem Button für lange Generierung steht jetzt ein gedämpfter
⏱ ~Ns-Hinweis (wie die ETA auf#/auto). Gemeinsamer.eta-hint-Stil + zwei generische Schlüssel (common.eta~{n}s,common.etaTitle).
Hinweise
- Nur Client; keine Änderung an Route/CSP/SSRF/Schreibzugriff. +2 i18n-Schlüssel ×17 (Snapshot 1219 → 1221).
tests/generation-eta-hint.test.mjs(+2). Suite: 2434 (+2).
[1.169.0] — 2026-08-13
Hinzugefügt (NIEDRIG) — Inline-PDF-Vorschau (D-5). GET /api/output/pdfs/:name erzwang Content-Disposition: attachment, sodass selbst der „Öffnen”-Link auf #/cv herunterlud statt anzuzeigen.
Hinzugefügt
?inline=1liefert dieselbe bereinigte Datei mitContent-Disposition: inline, für eine 👁 Vorschau in einem neuen Tab; Standard bleibt Download. Keine neue Route; dieselben Namens-Guards.- Der erste Button der PDF-Liste auf
#/cvist jetzt 👁 Vorschau neben ⬇ Herunterladen.cv.openPdf„Öffnen” → „Vorschau” ×17.
Hinweise
- Keine CSP/SSRF-Änderung — dasselbe
sanitizePathName. Ein bestehender i18n-Schlüssel neu formuliert ×17 (Snapshot 1219).tests/output-pdfs.test.mjs(+3). Suite: 2432 (+3).
[1.168.0] — 2026-08-13
Behoben (NIEDRIG, a11y) — Checkbox-Zeilen erfüllen jetzt das 24×24-Minimum von WCAG 2.5.8 (D-2). Checkbox-/Radio-Labels auf #/scan, #/config, #/evaluate und #/cv-studio lagen in einem ~22-px-Band.
Behoben
- Eine begrenzte Regel
label:has(> input[type="checkbox"/"radio"]) { min-height: 24px }garantiert ein ≥24-px-Band. Nurmin-height— die Labels sind bereits flex, nichts verschiebt sich;.apply-checklist(32 px) war bereits konform.
Hinweise
- Nur CSS; keine Änderung an Verhalten/JS/i18n/Route/CSP/SSRF/Schreibzugriff.
tests/checkbox-target-size.test.mjs(+1). Suite: 2429 (+1).
[1.167.0] — 2026-08-13
Behoben (NIEDRIG, Design-System) — erhöhte Flächen heben sich jetzt von Haarlinien ab (D-3). Die Tokens --panel-2 / --surface-elev1 lösten zu --slate auf — demselben Wert wie die Haarlinien --line / --border — ohne visuelle Trennung.
Behoben
- Ein dediziertes, themenbewusstes Token
--elev(#eef1f6hell /#1e232edunkel, in beiden Themes von--slateverschieden) trägt jetzt die erhöhten Flächen; die Haarlinien bleiben auf--slate. Die übrigen Befunde (D-2, D-4, D-5, P4-ETA) stehen als Backlog indocs/UX-ROADMAP.md.
Hinweise
- Nur CSS-Token; keine Änderung an Verhalten/JS/i18n/Route/CSP/SSRF/Schreibzugriff.
tests/elevation-token.test.mjs(+2). Suite: 2428 (+2).
[1.166.0] — 2026-08-13
Behoben (NIEDRIG) — die Rubrik-Terminologie spiegelt jetzt die kanonischen Docs. career-ops.org/docs beschreibt „fünf Dimensionen plus eine ganzheitliche Gesamtbewertung”, aber Web-UI, cvstart.org und das Wiki sagten alle „Rubrik mit sechs Dimensionen” (5 + 1 = 6, aber der Wortlaut wich ab).
Behoben
- Die Docs-Formulierung — „fünf Dimensionen plus eine ganzheitliche Gesamtbewertung” — konsistent in README ×17, der cvstart.org-Site ×17, dem Hilfe-Guide ×17,
docs/career-ops-canonical.mdund dem Wiki (Home ×17 + Features) übernommen.
Hinweise
- Nur Docs/Marketing; keine Änderung an Code/i18n-Schlüssel/Route/CSP/SSRF/Schreibzugriff.
tests/rubric-terminology.test.mjs(+2). Suite: 2426 (+2).
[1.165.0] — 2026-08-13
Behoben (NIEDRIG) — der Begriff “Two-pager” ist jetzt innerhalb jeder Sprache konsistent. Im Arabischen zeigte die Seitenleiste das lateinische “Two-pager”, während der <h1> vollständig lokalisiert war — die einzige lateinische Zeichenkette in einer ansonsten gespiegelten RTL-Navigation.
Behoben
- Entscheidung durchgesetzt: pro Sprache stimmen
nav.twoPagerundtwoPager.titlebeim Begriff überein (beide Latein oder beide lokalisiert). Nur Arabisch war getrennt; sein Navi-Label ist jetzt lokalisiert (“الصفحتان”). Ein neuer Canary schlägt fehl, wenn eine Sprache sie wieder trennt.
Hinweise
- Nur Text; keine Änderung an Route/CSP/SSRF/Schreibzugriff. Ein i18n-Wert geändert (ar); keine neuen Schlüssel (Snapshot 1219).
tests/two-pager-term-consistency.test.mjs(+2). Suite: 2424 (+2).
[1.164.0] — 2026-08-13
Behoben (NIEDRIG) — der Suchleisten-Platzhalter läuft in keiner Sprache mehr über. “Find a company, role or URL…” wurde abgeschnitten (nowrap), wenn die Suchleiste schrumpfte; die “…or URL”-Hälfte war nie sichtbar.
Behoben
top.search(×17) ist jetzt das kurze “Suchen oder URL einfügen” (≤24 Zeichen in jeder Sprache), passt auch in eine schmale Leiste und behält den URL-Hinweis. Der Fallback inindex.htmlpasst; dasaria-labelbehält das volle Detail.
Hinweise
- Nur Text; keine Änderung an Route/CSP/SSRF/Schreibzugriff. Ein bestehender i18n-Schlüssel neu formuliert ×17 (keine neuen; Snapshot 1219).
tests/search-placeholder-fit.test.mjs(+2). Suite: 2422 (+2).
[1.163.0] — 2026-08-13
Behoben (NIEDRIG) — der In-App-Assistent “Frag die Docs” deckt jetzt den PDF-Export eines Berichts ab. Er antwortete, der Leitfaden decke das nicht ab, obwohl #/reports/:slug einen funktionierenden 📄 Generate PDF-Button hat.
Behoben
- Ein H3 “Einen Bericht als PDF exportieren” unter §10 Berichte in allen 17 Hilfe-Bundles hinzugefügt (wo der Button ist, dass die Datei nach
output/*.pdfgeht, Playwright nötig, vor dem Senden prüfen). Die Assistenten-Suche zeigt jetzt die Berichte-Sektion.
Hinweise
- Nur Docs/Hilfe; keine Änderung an Code/Route/CSP/SSRF/Schreibzugriff. Hilfe-Gate 112 → 113 H3 (31 H2 unverändert).
tests/help-reports-pdf-section.test.mjs(+2). Suite: 2420 (+2).
[1.162.0] — 2026-08-13
Behoben (MITTEL) — das Hilfe-“?” ist jetzt ein ≥24×24-Zeigeziel (WCAG 2.5.8). .help-hint maß 18×18 px mit padding:0, unter dem Minimum, auf jeder Überschrift.
Behoben
- Die
.help-hint-Box ist jetzt 24×24 (das messbare Ziel), während der sichtbare Ring 18px bleibt — von einem zentrierten::beforegezeichnet, sodass Glyph und<h1>-Grundlinie unverändert sind. Hover/aktiv/Fokus folgen dem Ring; Rand 6→3px erhält den Abstand.
Hinweise
- Nur CSS; keine Änderung an JS/i18n/Route/CSP/SSRF/Schreibzugriff.
tests/help-hint-target-size.test.mjs(+2). Suite: 2418 (+2).
[1.161.0] — 2026-08-13
Behoben (MITTEL) — #/reports zeigt einen “Score nicht erkannt”-Chip statt Leerraum. Nach dem sprachbewussten Parser aus v1.159.0 zeigte ein Bericht ohne lesbaren Score einen leeren Bereich — nicht von einem Fehlschlag zu unterscheiden.
Behoben
- Die Score-Zelle verzweigt jetzt: Score vorhanden → Ton-Pille; kein Score → gedämpfter
.score-muted-Chip (“Score nicht erkannt”, ×17) mit Tooltip “Öffne den Bericht…”. Die Karte bleibt ein tastaturbedienbaresrole="link", und das Datum wird angezeigt. - Nutzt den vorhandenen neutralen Token; keine neue Farbe.
Hinweise
- Nur Client; keine Änderung an Route/CSP/SSRF/Schreibzugriff. +2 i18n-Schlüssel ×17 (Snapshot 1217 → 1219). Suite: 2416 (+3).
[1.160.0] — 2026-08-13
Behoben (HOCH) — der Anbieter-Text widerspricht nicht mehr dem 7-Anbieter-Versprechen. #/config sagte, die Live-Bewertung “nutzt deinen Anthropic- oder Gemini-Schlüssel” und der OpenAI-Schlüssel werde “nicht von der Web-UI selbst genutzt”; das Dashboard zeigte “Anthropic-first-Scoring” — falsch seit der 7-Anbieter-Kaskade (v1.157.0).
Behoben
config.providerModelNote(×17): sagt jetzt, dass die ⚡ Live-Bewertung headless mit einem beliebigen deiner sieben Schlüssel (Anthropic · Gemini · OpenAI · Qwen · OpenRouter · GitHub Models · Hermes) läuft, automatisch geordnet mit Fallback. Der falsche OpenAI-Satz ist entfernt.dash.quick.evaluateSub(×17): anbieterneutral (“0–5 Eignungs-Score”).Keys: N / 5→N / 7.
Hinweise
- Nur Text; keine Änderung an Route/CSP/SSRF/Schreibzugriff. Keine neuen i18n-Schlüssel (Snapshot 1217). Suite: 2413 (+3).
[1.159.0] — 2026-08-13
Behoben (HOCH) — Berichts-Metadaten sind nicht mehr sprachgekoppelt. In einer anderen Sprache als Englisch erzeugte Berichte zeigten auf #/reports einen leeren Metadatenstreifen, weil parseReportHeader nur englische Fettschrift-Labels erkannte.
Behoben
parseReportHeaderparst jetzt den sprachinvarianten## Machine Summary-YAML-Block (score:/legitimacy:/date:— dieselbe Quelle, dieauto-pipelinebereits liest): englische Labels → Machine Summary → lokalisierte Labels (REPORT_LABELS, 17 Sprachen). Englische Berichte bleiben Byte für Byte identisch.- Toleranter Zahl-Parse (
1.5/5,1,5/5,1.5 из 5,4.5 out of 5); das Datum fällt auf die Datei-mtime zurück, wenn der Text keines hat.
Hinweise
- Nur Lesen/Parsen; keine Änderung an Route, CSP, SSRF oder Eltern-Schreibzugriff. Keine neuen i18n-Schlüssel. Suite: 2410 (+8).
[1.158.0] — 2026-08-12
Behoben — zwei kosmetische Anzeigefehler (ein in den Tab-Titel durchgesickertes «?» und eine falsche Anbieterzahl auf der Landingpage). Nur Anzeige; keine Änderung an Verhalten, Sicherheit oder Datenfluss.
Behoben
- Das «?» von HelpHint sickert nicht mehr in
document.title. Der Router leitete den Tab-Titel aus dem rohenh1.textContentab, sodass der Tab «Vacancy search?» statt «Vacancy search» zeigte.router.js::focusNewViewklont die Überschrift nun, entfernt.help-hintund liest dann den Text; das sichtbare «?» bleibt unberührt. - cvstart.org zeigte «17 AI providers» statt «7». Der
sub()-Helper inFeatures.astroersetzte alle{n}durch die Sprachanzahl (17) vor der kartenweisen Ersetzung;{n}wird jetzt pro Karte aufgelöst (Anbieter → 7, Sprachen → 17).
Hinweise
- Keine Änderung an Server, Route, CSP, SSRF oder i18n-Schlüsseln;
facts.json-Form unverändert. Suite: 2402 Tests (+1).
[1.157.0] — 2026-08-12
Behoben — Live-Evals laufen jetzt mit JEDEM konfigurierten Provider, nicht nur Anthropic/Gemini. Ein Nutzer mit nur OPENROUTER_API_KEY wurde fälschlich in den manuellen Modus gezwungen.
Behoben
- Ursache: ein
LLM_PROVIDER-Pin ohne Schlüssel (z. B.LLM_PROVIDER=claudeausinit) lief ins Leere; nun wird auf die Auto-Reihenfolge unter den konfigurierten Providern zurückgegriffen (inselectActiveProvider+ beiden Dispatch-Kaskaden). - Das Client-Gating (
#/deep+ mode-page-Views) nutzt jetztwindow.ProviderStatus(/api/status/providers, alle 7) statt der veralteten Anthropic/Gemini-Prüfung; überarbeitete Texte (deep/eval × 17) + „Live-Evals“-Badge im Dashboard +config.llmProviderHint.
Hinweise
- Keine Sicherheitsänderung. Suite: 2401 Tests (+5).
[1.156.0] — 2026-08-12
Refactor — scan.js unter das Größenlimit aufteilen (P-16) + ein CodeQL-Fix. scan.js hatte 906 Zeilen; zwei verhaltensbewahrende Factories wurden herausgezogen → 648. Vervollständigt das View-Split-Paar P-15/P-16.
Geändert
- Neue
scan/runner.js(Scan-Ausführungs-Engine) undscan/filters.js(Filter-Zustandsmaschine) überctx/refs-Bags;scan.jsverdrahtet beide.
Behoben
- CodeQL
js/useless-assignment-to-local(#428) inconfig/tab-controller.js:let n = i;→let n;.
Hinweise
- Reiner Refactor, keine Verhaltensänderung; 4 quelllesende Tests umgeleitet. Beide großen Views jetzt unter 800 (P-15/P-16 fertig). Suite: 2396 Tests.
[1.155.0] — 2026-08-12
Refactor — config.js unter das Größenlimit aufteilen (P-15). config.js hatte 1030 Zeilen (über dem 800-Limit); zwei verhaltensbewahrende Module wurden herausgezogen, auf 783.
Geändert
- Neue
config/field-specs.js(Felddaten + Modelllisten) undconfig/tab-controller.js(Tab-Leisten-Factory);config.jsreferenziert sie, die Render-Logik bleibt unverändert.
Hinweise
- Reiner Refactor, keine Verhaltensänderung; 6 quelllesende Tests umgeleitet.
scan.js(906) bleibt wie es ist (bereits teilweise aufgeteilt; Kern zu stark gekoppelt für eine saubere mechanische Aufteilung). Suite: 2396 Tests.
[1.154.0] — 2026-08-12
Neuer Leitfaden — „Den ganzen Stack in der Cloud betreiben“. career-ops hat keine eigene Cloud/Server-Story, also fügen wir eine hinzu: eine Schritt-für-Schritt-Anleitung, um die übergeordnete career-ops-Pipeline, diesen career-ops-ui-Viewer und die KI-Engine (ein Claude-Abo über Claude Code, ein lokales Hermes, oder API-Schlüssel) auf einen kleinen Always-on-Server zu bringen. Als Hilfe §31 in 17 Sprachen, ein README-Abschnitt und eine Wiki-Seite.
Hinzugefügt
- Hilfe §31 „Den ganzen Stack in der Cloud betreiben“ (× 17) — die drei Teile, Bereitstellen + Installieren, Engine wählen, sicher exponieren (HTTPS-Reverse-Proxy + Auth + die CSP/SSRF/XSS/keine-Secrets-Invarianten). Das Hilfe-Bundle wächst auf 31 H2 / 112 H3.
- README — ein Abschnitt „Den ganzen Stack in der Cloud betreiben“ (× 17) + eine Cloud-Deployment-Wiki-Seite.
Hinweise
- Nur Docs — keine Route, kein Server, keine Client-Änderung; kein neuer i18n-Schlüssel. Die 4 Hilfe-Tests wechseln auf den 31 H2 / 112 H3-Vertrag. Suite: 2396 Tests (unverändert).
[1.153.0] — 2026-08-12
Jobvite-Scanner auf den öffentlichen XML-Feed migriert (Parent-Sync). Der Parent hat die Jobvite-JSON-API stillgelegt (liefert jetzt null Jobs); der web-ui-Source nutzte denselben toten Endpunkt, sodass jede getrackte Jobvite-Firma still leer scannte. Portiert den Parent-Fix (#2623): der Source liest jetzt den öffentlichen Per-Tenant-XML-Feed, geschlüsselt über companyEId.
Behoben
- Der Source rief die stillgelegte JSON-API auf und lieferte null Jobs; er ruft nun
https://app.jobvite.com/CompanyJobs/Xml.aspx?c={companyEId}auf und parst das XML<result><job>…(CDATA + Entities,detail-urlvorapply-url).
Geändert
companyEId-Auflösung: (1)company_eid:am Portal, (2)c=einer explizitenapi:-URL, (3) Board-Seiten-Discovery.fetchText(http-json.mjs) hängt.location/.retryAfteran den non-ok-Fehler (nur-lesend, rückwärtskompatibel).
Hinweise
- Sicherheit — zwei Hosts (
jobs.jobvite.com,app.jobvite.com) perassertJobviteUrlgepinnt: nur https, strikte Allowlist, kein Redirect wird verfolgt.companyEIdist nur ein?c=-Wert; Source-Anzahl unverändert. - Suite: 2396 Tests (+4).
[1.152.0] — 2026-08-12
Hermes-Provider — Verdrahtung abgeschlossen + Doku-Aktualisierung. Ein Code-Review der Hermes-Integration aus v1.151.0 fand zwei echte Lücken und vier Vollständigkeitspunkte; alle hier behoben, und die LLM-Provider-Liste der gesamten App ist auf die vollen sieben über alle Doku-Flächen und die 17 Sprachen gebracht.
Behoben
#/configkonnte Hermes nicht erzwingen — dasLLM_PROVIDER-Dropdown listete nur sechs Provider, man konnteHERMES_API_KEYsetzen, Hermes aber nicht aus der UI erzwingen.hermesist jetzt die 8. Option, und ein neuer Paritätstest verhindert erneutes Abweichen des Dropdowns vonLLM_PROVIDERS.- Kurze selbstgehostete Schlüssel wurden still verworfen — die 20-Zeichen-Grenze von
isUsableKeywar auf Cloud-Schlüssel ausgelegt;hasHermesKeynutzt nun eine gelockerte Grenze von 8 (das Beispiel der Hermes-Doku hat 19 Zeichen).
Geändert
- Die Provider-Liste wurde in README (× 17), In-App-Hilfe (× 17), dem
config.llmProviderHint-Dict (× 17) unddocs/sddauf die vollen sieben normalisiert;hermesChatUrlergänzt einen Host ohne Pfad; der manuelle Fallback-Text nennt Hermes.
Hinweise
- Sicherheit unverändert — keine neue Route, keine SSRF/CSP-Änderung; health/doctor erhält eine
HERMES_API_KEY-Zeile. - Suite: 2392 Tests (+2).
[1.151.0] — 2026-08-12
Hermes ist jetzt ein angebundener LLM-Provider (Phase 5) — der Phase-5-Spike bestätigte, dass Nous Researchs Hermes einen OpenAI-kompatiblen API Server mitbringt (hermes gateway → POST /v1/chat/completions), sodass career-ops-ui Live-Auswertungen nun über ein lokales Hermes genau wie OpenAI/Qwen ausführt. Setzen Sie HERMES_API_KEY in den App-Einstellungen, und es reiht sich in die auto-Reihenfolge ein (zuletzt). Schließt den letzten offenen Roadmap-Punkt — Phase 5, Shape A.
Hinzugefügt
- Hermes-LLM-Provider (Shape A) —
runHermesauf dem gemeinsamenrunOpenAICompatible-Client (server/lib/openai.mjs), in beiden Kaskaden (llm-dispatch.mjs+routes/llm.mjs), am Ende der auto-Reihenfolge +LLM_PROVIDER=hermes-Pin,/api/status/providersundllm-pricing.mjs. Er erreicht eine konfigurierbare lokale Basis-URL (Standardhttp://127.0.0.1:8642/v1) mit Bearer-Auth — ein KONFIGURIERTER Provider-Endpoint (wie OpenRouter/Qwen), keine nutzergelieferte Job-URL, also ohne SSRF-Guard. #/config-Felder —HERMES_API_KEY(geheim) +HERMES_BASE_URL+HERMES_MODEL(Standardhermes-agent), mit 6 neuen i18n-Schlüsseln × 17 Sprachen (Snapshot 1208 → 1214).
Geändert
- Der Scoping-Spike ist gelöst:
docs/integrations/HERMES.md, die In-App-Hilfe §30 (× 17), der README-Teaser (× 14), diehermes-bridge-Skill und die Roadmap gehen von „geplant / noch nicht angebunden” zu angebunden (Shape A). Shape B (ein maßgeschneidertes Agent-Runtime-Relay) war nicht nötig.
Hinweise
- Sicherheit: der Provider-Fetch ist ein konfigurierter Endpoint, derselben Kategorie wie die anderen OpenAI-kompatiblen Provider — keine neue SSRF-Fläche, keine CSP-/Sanitizer-Änderung.
HERMES_API_KEYist einSECRET_KEY(wird nie ausgegeben). - Tests (CI-isoliert, Transport-Stub):
tests/hermes-provider.test.mjs(+5); der v1.146.0-Canary „kein Hermes-Zweig” ist invertiert, um zu bestätigen, dass er DA ist; Provider-Flächen-Tests auf die 7-Provider-Reihenfolge aktualisiert. - Suite: 2390 Tests (+5).
[1.150.0] — 2026-08-12
Konsistente Leerzustände (Phase-4-Feinschliff) — jedes „noch nichts hier”-Panel wird jetzt über den einen gemeinsamen .empty-Stil gerendert, statt dass einige Ansichten das Aussehen inline mit einem magischen 40px erneut deklarieren. Kleine visuelle Konsistenzkorrektur; die Leerzustände auf #/activity, #/cv-studio, #/stats und #/usage passen jetzt zu allen anderen (tokenisiertes 48px-Padding + gestrichelter Rahmen).
Geändert
#/activity,#/cv-studio,#/stats,#/usageentfernten ihr Inline-style: { padding: '40px', textAlign: 'center', color: 'var(--foggy)' }auf Leer-Panels — alle drei Eigenschaften liefert bereits die gemeinsame.empty-Klasse (--space-7= 48px, zentriert, gedämpft, gestrichelter Rahmen). So rendern diese vier identisch zu den ~25 anderen.empty-Panels.- Berechtigte Überschreibungen pro Ansicht (
#/dashboardwidth:100%,#/pipelineborder:none) bleiben unangetastet — nur die rein redundanten Re-Deklarationen wurden entfernt.
Hinweise
- Nur Bereinigung der CSS-Nutzung im Client — keine Änderung an Route, Server, i18n-Schlüssel oder CSS-Regeln (die
.empty-Klasse ist unverändert); Wörterbuch-Snapshot 1208. Im Browser verifiziert (das leere#/usage-Panel berechnet 48px Padding + gestrichelten Rahmen, 0 Konsolenfehler). - Der neue Canary
tests/empty-state-consistency.test.mjshält.emptyals einzige Quelle der Wahrheit. Phase 5 (Hermes-Provider) bleibt blockiert. - Suite: 2385 Tests (+2:
tests/empty-state-consistency.test.mjs).
[1.149.0] — 2026-08-12
Portale in die Einstellungen verschoben (Phase 4) — #/portals liegt jetzt in der Navigationsgruppe Setup neben den App-Einstellungen, statt unter Sourcing. Seit v1.144.0 ist es eine Einstellungsfläche (verfolgte Firmen aktivieren/deaktivieren + ein ATS-Health-Probe), keine Sourcing-Aktion — also gehört es dorthin. Nur eine Navigationsänderung; die Seite und ihre Route bleiben unverändert.
Geändert
#/portals-Navigationselement → Setup-Gruppe (inpublic/index.html), direkt nach den App-Einstellungen platziert. Aus der Sourcing-Gruppe entfernt (die Scan / Pipeline / Auto-pipeline / Finanzierte Firmen behält). Die Route#/portals, die Ansicht und das Labelnav.portalssind unverändert — nur die Position in der Seitenleiste hat sich bewegt.
Hinweise
- Nur Navigations-Markup — keine Änderung an Route, Ansicht, i18n-Schlüssel oder Server. Im Browser verifiziert (0 Konsolenfehler); abgesichert durch
tests/portals-nav-placement.test.mjs. - Suite: 2383 Tests (+2:
tests/portals-nav-placement.test.mjs).
[1.148.0] — 2026-08-12
Übersichtlichere Scan-Filter (Phase 4) — das Filterpanel ist jetzt ein aufgeräumtes Raster — das Filterpanel von #/scan wechselte von einem ungleichmäßigen Flex-Wrap aus starren Boxen unterschiedlicher Breite zu einem responsiven Raster, und die Aktionen Anwenden / Zurücksetzen liegen nun in ihrer eigenen abgetrennten, rechtsbündigen Zeile. Gleiche Filter, gleiches Verhalten — nur besser lesbar. Eine Design-Feinpolitur (ohne parent-sync).
Geändert
#/scan-Filterpanel → responsives Raster —.scan-filtersist jetztdisplay: gridmitrepeat(auto-fill, minmax(180px, 1fr))-Spalten und gleichmäßigen Abständen, sodass sich die 11 beschrifteten Filter bei jeder Breite in ordentliche Spalten einreihen, statt in eine ungleichmäßige Zeile umzubrechen.- Aktionen Anwenden / Zurücksetzen erstrecken sich über das ganze Raster in einer eigenen Zeile, durch eine Haarlinie getrennt und rechtsbündig. Der alte Trick mit verstecktem Label + der innere Flex-Wrapper in
scan.jswurden entfernt.
Hinweise
- Nur CSS + eine kleine DOM-Bereinigung — jede Filter-id (
#scan-filter-*,#scan-apply) und dieSR.render()-Verdrahtung sind unverändert, der Playwright-Ablauf bleibt also unberührt. Keine neuen i18n-Schlüssel. - Im Browser verifiziert (0 Konsolenfehler); abgesichert durch
tests/scan-filters-grid.test.mjs. - Suite: 2381 Tests (+3:
tests/scan-filters-grid.test.mjs).
[1.147.0] — 2026-08-12
Hermes & Telegram — der In-App-Hilfeabschnitt + die cvstart.org-Fläche (Phase 5b, Teil 2) — der zweite und letzte Teil der Hermes-Dokumentationsarbeit: die Anleitung lebt jetzt im eigenen Hilfeleitfaden der App, in allen 17 Sprachen, und der eingebaute Dokumentations-Assistent beantwortet Hermes-Fragen daraus. Weiterhin nur Dokumentation — der Hermes-LLM-Provider-Pfad bleibt geplant / noch nicht angebunden (Phase 5).
Hinzugefügt
- In-App-Hilfe §30 „Hermes & Telegram” × 17 Sprachen — ein neuer Leitfaden-Abschnitt (was Hermes ist + die zwei Integrationsformen; Betrieb auf einem Cloud-Server; Telegram via Hermes + die Regel „was NICHT exponiert werden darf”), erreichbar über
#/help. Das Grounding vondocs-assistant/DocsFabgreift ihn automatisch auf, da beidedocs/help/<lang>.mdlesen. - cvstart.org — ein Link zum Hermes-Leitfaden, der auf das Dokument auf GitHub zeigt.
Geändert
- Hilfe-Bundle-Gate angehoben 29 → 30 H2 / 105 → 108 H3 (
canonical-docs-coverage,help-ui,help-ru-config-section); §30 fügt 3 H3 hinzu.
Hinweise
- Noch ruft nichts Hermes auf. Der neue Canary
tests/help-hermes-section.test.mjsstellt sicher, dass jede Sprache die §30 mit ihren sprachunabhängigen Ankern enthält (docs/integrations/HERMES.md,hermes-bridge,#/help,127.0.0.1, Telegram). Der Provider bleibt bis zum API-Vertrag aus Phase 5 blockiert. - Das schließt das Dokumentations- + Skill-Ergebnis von Phase 5b ab; die Provider-Integration (Phase 5) bleibt ein separater, blockierter Punkt.
- Suite: 2378 Tests (+2:
tests/help-hermes-section.test.mjs).
[1.146.0] — 2026-08-12
Hermes-Agent + Telegram — der Integrationsleitfaden + eine Skill (Phase 5b, Teil 1) — Sie können career-ops-ui auf einem Cloud-Server betreiben und dessen Events (ein abgeschlossener Scan, ein neuer Report, ein dringender Follow-up) über einen Hermes-Agent von Nous Research zu Telegram überbrücken. Diese Version liefert die Design- + Deployment-Dokumentation und eine hermes-bridge-Skill; der Hermes-LLM-Provider-Pfad bleibt geplant / noch nicht angebunden (blockiert durch den API-Vertrags-Spike der Phase 5). Dokumentation bewusst vor dem Code.
Hinzugefügt
docs/integrations/HERMES.md— die Tiefenanalyse: die zwei Integrationsformen (OpenAI-kompatibler Endpoint vs. Agent-Runtime), Cloud-Server-Deployment (Reverse Proxy + HTTPS + systemd, der Read-only-Vertrag mit dem Parent auf einer Headless-Maschine), Telegram via Hermes, und eine Bedrohungsmodell-Liste „was NICHT exponiert werden darf” (kein Lebenslauf / Gehalt / Report-Inhalt / Keys in den Kanal).## Hermes agent + Telegram-Teaser im README — ein kurzer Hinweis + Link, im englischen README und in allen vollständig übersetzten lokalisierten READMEs gespiegelt.- Eine
hermes-bridge-Skill (.claude/skills/hermes-bridge/), die den Leitfaden operationalisiert — Prüfungen von Voraussetzungen und Geltungsbereich (Node ≥ 18, Keys vorhanden, Erreichbarkeit des Endpoints über den SSRF-sicheren Pfad), schreibt niemals Secrets auf Disk/in Logs und verweigert das Erfinden eines Hermes-Endpoints oder die Behauptung, der Provider sei angebunden. - Ein Integrations-Abschnitt in
docs/architecture/OVERVIEW.mdverlinkt den Leitfaden.
Hinweise
- Noch ruft nichts Hermes auf. Ein Canary-Test (
tests/hermes-docs.test.mjs) prüft die Ehrlichkeits-Marker „geplant / noch nicht angebunden” sowie, dassllm-dispatch.mjskeinen Hermes/Nous-Zweig hat — das spätere Anbinden des Providers muss also Dokumentation + Roadmap in derselben Änderung aktualisieren. - Verschoben auf v1.147.0 (Phase 5b, Teil 2): der In-App-Hilfeabschnitt „Hermes & Telegram” H2 × 17 Sprachen und die Marketing-Fläche von cvstart.org.
- Suite: 2376 Tests (+4:
tests/hermes-docs.test.mjs).
[1.145.0] — 2026-08-12
Aufschlussreiche Statistiken (Forts.): ein neu baubares Diagramm — der Tab „Zielrollen-Trend” auf #/stats hat jetzt ein Diagramm erstellen-Widget: eine Metrik × Dimension wählen und es zeichnet sich live neu. Ein nutzergewünschtes UX-Feature (ohne parent-sync).
Hinzugefügt
- Neu baubares Metrik × Dimension-Diagramm — wählen Sie eine Metrik (Stellen / Median-Gehalt / Durchschnittsgehalt) und eine Dimension (Nach Land / Nach Rolle), und das Balkendiagramm zeichnet sich sofort neu. Gehalts-Metriken beachten Währung + Pro-Jahr ⇄ Pro-Monat-Umschalter; Stellen sind eine einfache Zählung.
- 8 neue i18n-Schlüssel × 17 Sprachen; Snapshot 1200 → 1208.
Hinweise
- Im Browser verifiziert (0 Konsolenfehler). Suite: 2372 Tests (+2).
[1.144.0] — 2026-08-12
Einstellungen & Filter (Phase 4, Teil 1): verfolgte Portale aktivieren/deaktivieren — Sie können ein beobachtetes Unternehmen jetzt auf #/portals ein- oder ausschalten, und der Scanner beachtet das. Ein nutzergewünschtes UX-Feature (ohne parent-sync).
Hinzugefügt
- Aktivieren/Deaktivieren-Schalter pro Unternehmen auf
#/portals— ein Klick schaltet ein Portal aus (der EN-Scanner überspringt bereits Unternehmen mitenabled: false, sodass ein deaktiviertes Portal aus allen künftigen Scans fällt) oder wieder ein, mit einem optimistischen Toast. POST /api/portals/toggle— ein expliziter Nutzer-Write, der dasenabled-Flag eines Unternehmens inportals.ymlchirurgisch und parse-validiert umschaltet (Kommentare, Reihenfolge und übrige Felder bleiben erhalten). 5 neue i18n-Schlüssel × 17 Sprachen; Snapshot 1195 → 1200.
Hinweise
- Die Scanner-Änderung war null —
en-scanner.mjsfiltert bereitsenabled !== false. Suite: 2370 Tests (+3).
[1.143.0] — 2026-08-12
Verständlich (Forts.): ?-Hinweise auf den zentralen Arbeitsansichten — das Hilfe-? deckt jetzt die neun wichtigsten Aktionsseiten ab, in allen Sprachen. Eine nutzergemeldete UX-Anpassung (ohne parent-sync).
Hinzugefügt
?-Hilfehinweis auf 9 weiteren Ansichtstiteln —#/scan,#/evaluate,#/cv-studio,#/tracker,#/config,#/deep,#/batch,#/auto,#/applyerhalten ein Inline-?(viaHelpHint.title), das ein lokalisiertes „was es tut / wie man es nutzt / was zu erwarten ist”-Popover öffnet — dieselbe CSP-sichere Komponente wie in v1.139.0.- 9 neue i18n-Schlüssel × 17 Sprachen (
help.hint.scan/…/apply); Snapshot 1186 → 1195.
Hinweise
- Im Browser verifiziert (0 Konsolenfehler). Suite: 2365 Tests (+1).
[1.142.0] — 2026-08-12
Korrektur: kein “Unknown”-Karrierearchetyp mehr — #/orientation ordnet jetzt immer den acht benannten Karrierevektoren zu, statt gelegentlich “Unknown” zu antworten und zu empfehlen, darauf “zu setzen”. Eine nutzergemeldete Korrektur (ohne parent-sync).
Behoben
#/orientation— der KI-Prompt verbietet jetzt einen Archetyp außerhalb des Sets. Das Modell MUSS die Top 3 aus genau den acht benannten Vektoren wählen und darf nie “Unknown”/“N/A”/“unzureichende Daten” antworten oder ein Label erfinden. Bei dünnem Lebenslauf benennt es dennoch die drei nächsten mit geringerer Sicherheit und nennt die fehlende Evidenz.
Hinweise
- Nur Server-Prompt-Änderung (
buildOrientationPrompt); keine i18n-/Schema-Änderung. Suite: 2364 Tests (+1).
[1.141.0] — 2026-08-12
Aufschlussreiche Statistiken (Forts.): Anreicherung finanzierter Unternehmen — #/funded ist jetzt visueller: Firmenlogos, ein Diagramm nach Finanzierungsbetrag und Karten mit Runde / Betrag / Discovery-Score / vorgeschlagener Aktion. Eine nutzergemeldete UX-Anpassung (ohne parent-sync).
Geändert
#/funded— flache Tabelle → Kartenraster. Jedes kürzlich finanzierte Unternehmen ist nun eine Karte mit Logo (aus dem Namen viaCompanyLogoabgeleitet, Buchstaben-Avatar als Rückfall), Runde- + Betrag-Chips, dem Discovery-Score und der vorgeschlagenen Aktion des Elternprojekts sowie Link und Datum der Finanzierungsnews.- Visualisierung des Finanzierungsbetrags — ein horizontales Balkendiagramm der größten Unternehmen nach offengelegtem Betrag; Freitext-Beträge (“$120M”/“€1.5B”) werden per neuem
parseAmountin eine Größe geparst. 3 neue i18n-Schlüssel × 17 Sprachen.
Hinweise
- Weiterhin nur lesend über
GET /api/company-funded; Beschreibung und Gehaltsspanne fehlen in der Finanzierungsquelle. Suite: 2363 Tests (+2).
[1.140.0] — 2026-08-12
Aufschlussreiche Statistiken: reichere Gehaltszahlen — die Gehaltsaufschlüsselung unter „Meine Pipeline” auf #/stats zeigt jetzt den Durchschnitt (nicht nur den Median), einen pro Jahr ⇄ pro Monat-Umschalter und eine Min · Ø · Median · Max-Tabelle je Land. Erster Teil von Phase 3. Eine nutzergemeldete UX-Anpassung (ohne parent-sync).
Hinzugefügt
- Durchschnittsgehalt —
RoleStats.salaryStatsliefert nunavgUsdnebenminUsd/medianUsd/maxUsd. Der Median trotzt Ausreißern, der Durchschnitt zeigt die Schiefe — zusammen lesen sie sich als Verteilung. - Pro-Jahr ⇄ Pro-Monat-Umschalter und eine Min · Ø · Median · Max-Tabelle je Land im Gehaltsbereich, gesteuert von Währungs- und Zeitraum-Auswahl. 8 neue i18n-Schlüssel × 17 Sprachen.
Hinweise
- Die Zahlen stammen weiterhin nur aus Anzeigen mit lesbarem Gehalt und werden auf USD normalisiert (Richtwerte). Suite: 2361 Tests (+1).
[1.139.0] — 2026-08-12
Verständlich: ?-Hilfehinweise — eine wiederverwendbare, CSP-sichere ?-Schaltfläche, die beim Klick „was es tut / wie es funktioniert / was zu erwarten ist” in Ihrer Sprache erklärt. Eine nutzergemeldete UX-Anpassung (ohne parent-sync).
Hinzugefügt
?-Hilfehinweis-Popover (window.HelpHint) — ein rundes?neben einer Überschrift öffnet ein leichtes, themenbewusstes und in RTL gespiegeltes Popover, das eine lokalisierte Erklärung überUI.md()rendert; barrierefrei (role="tooltip",aria-expanded, Schließen mit Escape/Klick außerhalb, Fokus wiederhergestellt) und CSP-sicher.?auf den 5#/stats-Tabs und auf 8 KI-/Analyse-Ansichtstiteln (career-plan, Orientierung, two-pager, Networking, Mock-Interview, Speicher, funded, Wochenzusammenfassung) — 14 neue i18n-Schlüssel × 17 Sprachen.
Hinweise
- Alle Ansichten hatten bereits einen einzeiligen Untertitel; das
?ergänzt die tiefere Erklärung bei Bedarf und macht leere Zustände selbsterklärend. Suite: 2360 Tests (+4).
[1.138.0] — 2026-08-12
Generierung in deiner Oberflächensprache — jede KI-Generierung antwortet nun in der im UI gewählten Sprache, plus Review-getriebene Test-Härtung. Eine nutzergemeldete UX-Anpassung (ohne parent-sync).
Geändert
- KI-Generierungen respektieren jetzt die UI-Sprache. Ist die Oberfläche auf Russisch, Spanisch, Japanisch, … eingestellt, kommt der generierte Text in dieser Sprache zurück statt immer auf Englisch. Die Ausgabesprach-Direktive läuft durch alle Generierungs-Endpunkte — Karriereplan, Orientierung, Marktbericht, Mock-Interview, Networking-Plan, „Frag die Doku“, den Memory-Notiz-Vorschlag und den Two-Pager-Entwurf. Code und Bezeichner bleiben englisch (z. B. die YAML-Schlüssel des Two-Pagers); nur Prosa, Überschriften und Stichpunkte werden lokalisiert.
Behoben
- CSS-Farbrollen-Wächter (
tests/css-role-tokens.test.mjs) — ein statischer Kanarienvogel, dass die Dark-Mode-Alias-Tokens aus v1.137.0 ihre Rolle nie umkehren: Text-Rollen-Tokens (--fg/--danger/--ok/…) nie alsbackground, Flächen-Tokens (--card/--panel/--line/…) nie als Text-color, über das gesamte CSS und die Inline-Styles der SPA. UI.md()-XSS-Loader-Selbsttest — der Test, dermd()ausapi.jslädt, prüft jetztmd('<script>…')direkt nach der Extraktion und wirft, wenn das Escaping fehlt, sodass ein künftiger Fehlschnitt laut fehlschlägt, statt die Sicherheits-Suite auf einer abgeschnittenen Funktion grün zu färben.- Scroll-Wächter auf
#/career-plan— dasscrollIntoViewnach der Generierung läuft nur, wenn die Vorschau noch mit dem Dokument verbunden ist.
Hinweise
docs/UX-ROADMAP.mdaktualisiert: die?-Hilfe-Hinweise + Seitenbeschreibungen + Leerzustände sind nun v1.139.0; ein Nous Research / Hermes-Provider — mit Cloud-Server- + Telegram-Deployment-Guide und einem Hermes-Skill — wird als Phase 5 / 5b geführt.- Suite: 2356 Tests (+5).
[1.137.0] — 2026-08-11
Lesbarkeits- und Rendering-Fixes — Dark-Mode-Kontrast, Diagrammbeschriftungen und der Karriereplan. Ein nutzergemeldeter UX-Durchgang (kein Parent-Sync).
Behoben
- Dark-Mode Weiß-auf-Weiß / Schwarz-auf-Schwarz auf vielen Bildschirmen — fünfzehn CSS-Custom-Properties, auf die mehrere Ansichten verwiesen (
--fg,--panel,--panel-2,--ok,--danger,--card, …), waren nie deklariert und fielen daher auf hartcodierte Hell-/Schwarz-Werte zurück: im Light-Mode unproblematisch, im Dark-Mode unlesbar (die Übersichts-Chips von#/pipeline, der aktive Tab von#/stats, „Aktiv / Schlüssel“ + „✓ gesetzt“ in#/config, die Abschnitte von#/two-pager, die Fragenblase von#/mock-interview, Fehlertext). Sie sind jetzt auf die tatsächlichen themenfähigen Tokens aliasiert und folgen damit automatisch dem Theme — 0 WCAG-AA-Kontrastfehler über alle 29 Ansichten, verifiziert durch einen automatisierten Prüfer; der aktive Tab von#/configwechselte zu einem gut lesbaren, getönten Stil. Eine Regressions-Absicherung (tests/dark-theme-tokens.test.mjs) hält sie aliasiert. - Diagrammbeschriftungen in
#/statswurden mitten im Wort abgeschnitten („Senior Backend Engineer“ → „…Enginee“) — sie werden jetzt mit Auslassungspunkten gekürzt, wobei die vollständige Beschriftung als Hover-Tooltip erhalten bleibt. #/career-planzeigte den generierten Plan als rohes Markdown an — er wird jetzt automatisch als formatierter, lesbarer Text gerendert (das editierbare Markdown bleibt im Textfeld; „Vorschau“ schaltet um).
Hinweise
#/career-plan,#/two-pager,#/statsund der wöchentliche Interview-Digest sind nicht defekt — sie zeigen Leerzustände an, bis Sie einen Plan generieren bzw. Daten vorliegen. Klarere Hinweise auf der Seite und?-Hilfe-Tooltips sind als Nächstes geplant (docs/UX-ROADMAP.md).
[1.136.0] — 2026-08-11
Parität mit dem übergeordneten Projekt career-ops v1.26.x (nachgelagerter v1.26.0-Mainline-Stand) — eine neue Quelle ohne Authentifizierung sowie eine Welle von Qualitäts- und Robustheits-Ports für die web-ui-Spiegel. Die Registry umfasst nun 79 Quellen = 74 englische + 5 russische (ALL_ADAPTERS 74).
Hinzugefügt
eightfold(Eightfold AI, #2684) — Talent-Acquisition-Boards über die authentifizierungsfreiehttps://<tenant>.eightfold.ai/api/apply/v2/jobs-API, host-gepinnt auf*.eightfold.ai(der gebrandetecareers.<company>.com-CNAME wird absichtlich abgelehnt); paginiert mit einer Sicherheitsobergrenze, Tote-Board-Throw, URL-Dedup. Quelle + Adapter + CI-isolierte Test-Suite; erscheint im#/scan-Quellenfilter und auf der Landingpage.
Behoben
- Unicode-fähige Dedup- und Rollen-Schlüssel (#2569 / #2587 / #2667) — ein neues gemeinsames
normalizeTextKey(NFKC, behält Buchstaben/Diakritika/Ziffern jeder Schrift) ersetzt die rein ASCII-basierten Schlüssel:detect-repostsgruppiert nun Breiten-/Interpunktions-Firmenvarianten („Acme, Inc.“ ≡ „Acme Inc“) und fasst niemals unterschiedliche nicht-lateinische Arbeitgeber zusammen, währendrole-matcherHalbbreiten-/Vollbreiten-Titel zusammenführt und nicht-lateinische Rollen-Tokens beibehält, statt sie zu löschen. fetchJsonWithRetrywiederholt einen abgelehnten Redirect nicht mehr (#2657) — eineredirect:'error'-Absicherung, die auf einen 3xx trifft, ist deterministisch, daher ist dies jetzt nicht wiederholbar und schlägt sofort fehl, statt das Wiederholungsbudget zu verbrauchen.title_filter.positive-UND-Gruppen (#2552) — ein durch Leerzeichen begrenztes+innerhalb eines positiven Eintrags verlangt nun, dass jeder Begriff im Titel vorkommt, in beliebiger Reihenfolge.oraclecloudakzeptiert die durchnummerierten Tenant-Apex-Domainsoraclecloud1.com … oraclecloud99.com(#2683) — eine begrenzte Familie (keine führende Null, ≤ 2 Ziffern), niemals eine Wildcard-Apex-Domain.workablegehärtet (#2675) — Wiederholungsversuche, browserähnliche Header und Anfrage-Serialisierung gegenüber dem Cloudflare-vorgeschalteten Host.personioweicht auf ein HTML-Scraping aus, wenn der XML-Feed deaktiviert ist, statt nichts zurückzugeben.states-FALLBACK-Aliase erneut synchronisiert mit dem übergeordneten Projekt (#2615).
Hinweise
- Nicht portiert (von web-ui nicht gespiegelt, oder nur CLI-relevant): reply-matcher (#2672), jd-similarity (#2661), jd-skill-gap (#2686), das Parsen von scan env-path (#2568) /
--flag=value(#2589) sowie Änderungen an Anschreiben/CV-Vorlage/doctor/ollama/generate-pdf. Die HIGH-Advisories fürjs-yaml/nanoidim Web wurden bereits in web-ui v1.135.0 gepatcht.
[1.135.0] — 2026-08-11
Parität mit dem übergeordneten Projekt career-ops v1.26.0 — fünf neue Scan-Quellen ohne Authentifizierung sowie Korrekturfixes für vier Boards, die web-ui bereits unterstützt. Die Registry umfasst nun 78 Quellen = 73 englische + 5 russische (ALL_ADAPTERS 73).
Hinzugefügt
- Fünf neue Scan-Quellen (jeweils eine Quelle + ein Adapter + eine CI-isolierte Test-Suite; sie erscheinen im
#/scan-Quellenfilter und auf der cvstart.org-Landingpage):join(JOIN) — das JOIN-Board eines Unternehmens aus den Next.js-__NEXT_DATA__unterjoin.com/companies/<slug>(host-gepinnt, seitenbegrenzt).getro(Getro) — Portfolio-Boards von VC-„Talent-Network“-Programmen über die öffentlicheapi.getro.com-POST-API, paginiert nach neuesten zuerst; jede Stelle wird dem Portfolio-Arbeitgeber zugeordnet, nicht dem Fonds.consider(Consider) — VC-Portfolio-Boards von getconsider.com über eine Same-Origin-POST-Anfrage; der konfigurationsgesteuerte Host wird durch eine strukturelle SSRF-Absicherung gepinnt (nur öffentliche HTTPS-Hosts).joinup(JOINUP) — das Schweizer Board joinup.ch, liest die serverseitig gerenderte neueste Seite aus; schlägt bei einem Scraper-Bruch sicher fehl (fail-closed).remotli(Remotli) — remotli.ch, Remote-Stellen bei Schweizer Unternehmen (Gehälter in CHF); gibt die eigene Bewerbungs-URL des ATS des Arbeitgebers aus, sodass Cross-Postings dedupliziert werden.
Behoben
- a16z Speedrun bricht das gesamte Board nicht mehr wegen eines vorübergehenden Ausfalls ab — Seitenabrufe laufen jetzt über ein gemeinsames
fetchJsonWithRetry(begrenzte Wiederholungsversuche nur bei vorübergehenden 429/5xx/Timeout-Fehlern, niemals bei einem dauerhaften 4xx), und das Seitenbudget wurde für die 50-Stellen-Seite neu bemessen. - arbeitsagentur wurde auf die v6-Jobsuche-API (
/pc/v6/jobs) umgestellt — der alte v4-Endpunkt liefert jetzt 404; die Antwortstruktur wurde umbenannt, und die Remote-Filterung grenzt nun serverseitig ein. - thehub wurde auf die v2-
jobsandfeatured-API umgestellt; Einträge enthalten kein Veröffentlichungsdatum und sind vom Alters-Filter ausgenommen. - hackernews findet den monatlichen „Who is hiring?“-Thread jetzt zuverlässig, indem die Algolia-Abfrage auf das Konto-Tag
author_whoishiringgefiltert wird, statt auf eine Freitextsuche.
Hinweise
- Nicht portiert (web-ui ist bereits sicher, wird per Relay übernommen oder ist nur CLI-relevant): die Unicode-Schlüssel für Rollen-Deduplizierung/Firmen-Abgleich (die Repost-Gruppierung von web-ui verwendet für den Firmenschlüssel bereits ein einfaches Kleinschreibungs-Schema, sodass unterschiedliche nicht-lateinische Arbeitgeber niemals zusammenfallen); das Ablehnungs-Latenz-Signal für Follow-ups + die company-funded-Feinschliffe (schreibgeschützt weitergeleitet, fail-soft); über Umgebungsvariablen überschreibbare Scan-Pfade und das Parsen von
--flag=value(web-ui führt die Scanner in-process aus); das Refactoring zur Konsolidierung des User-Agent (web-ui zentralisiert dies bereits); sowie reine CLI-Punkte (Liste nicht vertrauenswürdiger Inhalte, oferta/offer-prep, doctor, Änderungen an Anschreiben-/Lebenslauf-Vorlagen).
[1.134.1] — 2026-08-05
Validierungs-Härtung — durch ein vollständiges Projekt-Audit aufgedeckte Fehlerbehebungen.
Behoben
successfactorsverwirft bei einem Fehlschlag mitten im Scan nicht mehr die bereits gesammelten Stellen (Regression aus dem v1.134.0-Port des Tote-Boards-Throw) — seine Paginierungsschleife hatte keintry/catch, sodass ein Fehlschlag auf Seite 2 oder später (nachdem Seite 1 erfolgreich war) einen Fehler warf und alles bereits Gesammelte verwarf; und wenn dieser Fehlschlag ein404war (ein außerhalb des Bereichs liegendesstartrow), quarantänierteen-scannereinen aktiven Tenant tagelang als tot. Spiegelt nunphenom/radancy: Ein Fehlschlag auf Seite 0 wirft weiterhin einen Fehler (totes Board), aber ein späterer Seitenfehlschlag behält die Teilergebnisse.- Die
#/scan-Filter-Chips sind jetzt per Tastatur bedienbar (WCAG 2.1.1) — die Facetten-Chips (und der „Zurücksetzen“-Chip) waren Spans mit einem Klick-Handler, aber ohnetabindex/Rolle, sodass Tastatur- und Screenreader-Nutzer sie weder erreichen noch umschalten konnten. Sie tragen nunrole="button",tabindex="0",aria-pressedund Enter/Leertaste-Aktivierung. - Drei hartcodierte englische Zeichenketten sind jetzt lokalisiert — der
#/scan-Vertrauens-Badge-Tooltip, die#/scan-Umzugs-Spaltenüberschrift und die#/dashboard-Punktzahl-Überschrift waren literale Zeichenketten, die das i18n-Paritätsgate nicht erkennen konnte (sie waren nie Schlüssel), sodass sie in jeder nicht-englischen Sprachversion englisch blieben. Jetztscan.trustTip+scan.col.reloc(2 neue Schlüssel) + eine Wiederverwendung vontrack.col.score, mit einer quellcode-statischen Absicherung.
[1.134.0] — 2026-08-05
Parität mit dem übergeordneten Projekt career-ops v1.25.0.
Hinzugefügt
- Neue Scan-Quelle: getManfred (
manfred) — ein board-weiter Feed spanischer/EU-Tech-Stellen mit veröffentlichten Gehältern, vonwww.getmanfred.com/api/v2/public/offers(ohne Auth, host-gepinnt + nur HTTPS, vollständiger Katalog in einer einzigen Anfrage). Quelle + Adapter + eine CI-isolierte Suite (tests/sources-manfred.test.mjs); die Registry umfasst nun 73 Quellen = 68 englische + 5 russische (ALL_ADAPTERS68). Erscheint im#/scan-Quellenfilter und auf der cvstart.org-Landing.
Behoben
- Der a16z-Speedrun-Feed wurde stillschweigend auf 50 Stellen gekürzt (#2404) — der Feed begrenzt eine Seite auf 50, aber die Quelle forderte
PER_PAGE = 100an, sodass die Paginierung nach Seite 1 stoppte. Auf 50 korrigiert. - Tote Boards werfen jetzt einen Fehler, statt als „aktiv, aber leer“ gelesen zu werden (#2379) —
cryptocurrencyjobs,phenom,radancy,successfactors: Ein Fetch-Fehlschlag, bei dem keine einzige Anfrage jemals aufgelöst wurde, wirft nun einen Fehler (sodass die#/portals-Zustandsprüfung und der Scan einen echten Fehlschlag protokollieren), statt ihn stillschweigend zu einer leeren Liste zu verschlucken; ein Fehlschlag mitten im Scan nach mindestens einem Erfolg behält die Teilergebnisse. - workable nutzt jetzt die öffentliche Widget-API (#5ab8425) — umgestellt auf
apply.workable.com/api/v1/widget/accounts/<slug>, die die vollständige Stellenliste eines großen Kontos in einer einzigen Anfrage liefert, sodass große Konten nicht mehr gekürzt werden.
Hinweise
- Nicht portiert (nur CLI oder von web-ui nicht gespiegelt): die Perf-Überarbeitung des Titel-Bucketings von
detect-reposts#2389; die Unicode-Firmenschlüssel-Fixes (die eigene Tracker-Deduplizierung von web-ui ist bereits nicht-lateinisch-sicher);scan --since;cv-facts; der CV-Vorlagen-/PDF-Audit-Durchlauf;doctor; die Direktive zu nicht vertrauenswürdigen Inhalten in den Modi.
[1.133.1] — 2026-08-02
Behoben
#/funded(Finanzierte Unternehmen) zeigt jetzt Ergebnisse an — zwei Fehler sorgten dafür, dass die Tabelle immer „keine finanzierten Unternehmen“ anzeigte, selbst wenncompany-funded.mjsdes Elternprojekts eine vollständige Liste zurückgab. (1) Die Ansicht las die Ergebnisse unterres.candidates, aber das Elternprojekt liefert sie untercompanies(jeweils{ company, amount, round, funding: { sources: [{ source, url, observed_date }] } }); der Client liest nun den richtigen Schlüssel und bildet die tatsächliche Belegstruktur ab. (2) Die Ergebnistabelle übergab ihre Zellen als Varargs anUI.el('tr', {}, …), aberUI.el(tag, attrs, children)erwartetchildrenals einzelnen Knoten oder Array, sodass nur die erste Spalte (Unternehmen) gerendert wurde — Zellen werden jetzt als Array übergeben. In einem echten Browser verifiziert: 11 Unternehmen aus den vier Feeds werden mit den Spalten Unternehmen / Finanzierungssignal / Quelle / Datum sowie funktionierenden Belegs-Links gerendert, ohne Konsolenfehler. Ein leerer Durchlauf zeigt nun auch die Pro-Quelle-Diagnose an, sodass sich ein ruhiger Nachrichtentag von einem blockierten Feed unterscheiden lässt.- Regressions-Absicherungen in
tests/parity-routes-v1133.test.mjs: Das simulierte Skript des Elternprojekts liefert nun die tatsächlichecompanies-Ausgabeform (die ursprüngliche Fixture spiegelte fälschlich diecandidates-Form wider — genau deshalb konnte der Fehler mit grüner Suite ausgeliefert werden), zusätzlich quellcode-statische Prüfungen, dassfunded.jsres.companiesliest (niemalsres.candidates) und Tabellenzeilen mit Array-Children baut (+1 → 2144).
[1.133.0] — 2026-08-01
Hinzugefügt
- Erkennung frisch finanzierter Unternehmen (
#/funded, Parent-Parität #2117) — eine neue schreibgeschützte Ansicht, die das Skriptcompany-funded.mjsdes Elternprojekts career-ops überGET /api/company-fundedweiterleitet: eine zur Durchsicht bereitgestellte Liste kürzlich finanzierter Unternehmen, ermittelt aus öffentlichen, host-gepinnten Finanzierungs-Feeds (TechCrunch, PR Newswire, The Guardian, Hacker News). Das Relay führt das Skript mit--json --dry-runaus (JSON auf stdout, keine Dateischreibvorgänge), leitet Benutzereingaben niemals in--sourcesweiter, unterliegt Rate-Limiting und wird ausschließlich durch den Nutzer ausgelöst (eine „Entdecken“-Schaltfläche, niemals beim Laden der Seite). Neues Routenmodulserver/lib/routes/funded.mjs+public/js/views/funded.js, unter Sourcing. - Wöchentlicher Interview-Digest (
#/interview-digest, Parent-Parität #2129/#2130) — eine neue schreibgeschützte Ansicht, die das LLM-freie Skriptweekly-digest.mjsdes Elternprojekts überGET /api/interview/weekly-digestweiterleitet: eine mechanische Zusammenfassung der Interview-Sitzungsnotizen — mit welchen Unternehmen und in welchen Runden Sie diese Woche ein Interview hatten, wiederkehrende Kompetenzen und nach bestem Ermessen ermittelte offene Lücken. Der optionale?from=&to=-Zeitraum wird nur weitergeleitet, wenn BEIDE Werte gültigeYYYY-MM-DD-Daten sind; ein leerer Zeitraum ergibt einen gültigenavailable:true-Digest. Ergänzt inserver/lib/routes/interview.mjs+public/js/views/interview-digest.js, unter Analytics. - Beide Relays folgen dem etablierten Fail-soft-
available:false-Vertrag, wenn das Elternskript fehlt (CI, eigenständige Installationen). 26 neue i18n-Schlüssel ×17 Sprachversionen; CI-isolierte Suitetests/parity-routes-v1133.test.mjs(+5 → 2143).
Hinweise
- Das Elternprojekt career-ops ist über v1.24.0 hinaus fortgeschritten — mit der Follow-up-Tracker-Seite (#1422) der Next.js-Web-App und dem Backend-PDF-Rendering (#2182) — nicht portiert: web-ui verfügt bereits über ein eigenes Follow-up-Relay und eigene PDF-Runner, und die zugrunde liegende Härtung von
followup-cadence.mjskommt über das Shell-out-Relay ohnehin kostenlos mit. Die Änderungen anset-status.mjs/tracker-utils.mjssind CLI-intern und werden nicht gespiegelt.
[1.132.0] — 2026-07-31
Geändert
#/scan-Ergebnis-Rendering-Subsystem nachpublic/js/lib/scan-results.jsextrahiert (File-Size-Contract-Schuld —public/js/views/scan.jswar auf ~1254 LOC angewachsen). Das Subsystem (renderResults,buildChipRow,getRows, die Zeilen-/Facetten-Builder, die Options-Painter und derFALLBACK_SOURCES-Registry-Spiegel) wurde in einewindow.ScanResults.create(ctx)-Factory verschoben, die über ein vom View bereitgestelltes Kontextobjekt schließt. Keine Verhaltensänderung — die Funktionen wurden unverändert verschoben, die Closure-Variablen aufctx.*umverdrahtet;scan.jsumfasst nun ~906 LOC (ein zweiter Extraktionsdurchgang in Richtung des 800-LOC-Ziels ist geplant).- Quellcode-statische Tests lesen beide Dateien über
tests/helpers/scan-src.mjs::loadScanSrc();tests/scan-fallback-sources.test.mjsliest den Registry-Spiegel nun ausscan-results.js. - Neues Regressions-Gate im Browser —
tests/playwright-scan-filters.mjssetzt ein vorgefertigtesdata/last-scan.jsonund steuert jeden#/scan-Filter, wobei exakte Zeilenanzahlen geprüft werden (npm run test:e2e:browser); stabile Filter-IDs (#scan-filter-*,#scan-apply) wurden hinzugefügt. - Das README-Banner „Latest release“ wurde auf eine einzeilige Zusammenfassung + einen Link zum vollständigen Changelog verschlankt (die lange, versionsübergreifende Fließtext-Wand entfällt). Angewendet in allen 17 Sprachversionen.
[1.131.2] — 2026-07-31
Geändert
app.cssin drei geordnete Stylesheets aufgeteilt (File-Size-Contract-Schuld — die einzelne Datei war auf ~1990 LOC angewachsen, weit über dem harten 800-LOC-Ziel). Sie ist nunapp.css(~672 — a11y, Design-Tokens/Theme, Sidebar, Main, Buttons, Content-Shell),components.css(~595 — Karten, Grids, Paginator, Badges, Tabellen, Formulare, Log/Konsole, Markdown, Sprachumschalter, Chip-Filter, Verbindungsbanner) undoverlays.css(~737 — Toast, Benachrichtigungs-Drawer, Modal, Sonstiges/Responsive, der[dir="rtl"]-Spiegel, docs-fab, usage-hud), jede innerhalb des harten Limits.- Der Schnitt ist zusammenhängend und in Reihenfolge, sodass die Kaskade byte-für-byte identisch zur Datei vor der Aufteilung ist;
index.htmllädt die drei als geordnete<link>s. Keine Verhaltens-, Markup- oder i18n-Änderung. - CSS-prüfende Tests lesen die Verkettung nun über einen gemeinsamen
tests/helpers/css.mjs::loadAppCss()-Helper. Der neuetests/css-modularization.test.mjsfixiert die Aufteilung (Dateien existieren · jede ≤ 800 LOC ·index.html-Link-Reihenfolge) → Suite 2138. Im Browser verifiziert: Alle drei Stylesheets werden geparst und ihre Regeln greifen.
- Der Schnitt ist zusammenhängend und in Reihenfolge, sodass die Kaskade byte-für-byte identisch zur Datei vor der Aufteilung ist;
[1.131.1] — 2026-07-31
Behoben
- Adapter-Host-Pinning-Konsistenz bei den beiden v1.130.0-Quellen (Nachträge aus dem Code-Review, Defense-in-Depth; kein Verhaltensunterschied bei gültigen Eingaben):
a16z-speedrun-talent-Adapter validiert dasapi:- /a16z-speedrun-talent:-Override jetzt erneut inbuildEndpoint(HTTPS + exakter Hostspeedrun-talent-network.com) und fällt bei Fehlschlag auf den kanonischen Feed zurück — Parität mit demcryptocurrencyjobs-Adapter, sodass ein Host-fremder Wert nie den Fetch-Slot erreicht (zuvor verließ er sich ausschließlich auf die Fetch-Zeit-AbsicherungassertSpeedrunUrl). Die exakte Host-Prüfung ist nun eine einzige exportierteSPEEDRUN_TALENT_HOST_RE, die sich Guard und Adapter teilen.cryptocurrencyjobs-Parser —cleanUrlverwendet nun denselben exakten Host-Guard wieassertCryptocurrencyJobsUrlund das Adapter-Override (zuvorendsWith, was Subdomains akzeptierte). Der Parser ist nie großzügiger als der SSRF-Guard: Einsub.cryptocurrencyjobs.co-Item-Link wird verworfen.- +2 Tests → Suite 2135.
[1.131.0] — 2026-07-31
Hinzugefügt
#/tracker-CRM-Stage-Tab-Board (portiert aus der/pipeline-Ansicht der Web-App des Elternprojekts). Die Funnel-Chip-Leiste + das Status-Dropdown des Trackers werden durch eine Stage-Tab-Leiste ersetzt: ein Alle-Tab plus ein Tab pro kanonischem Status — Evaluated · Applied · Responded · Interview · Offer · Rejected · Discarded · SKIP · Hired — jeweils mit einer live berechneten Gesamtverlaufs-Anzahl, einschließlich Stufen mit null Treffern, sodass der vollständige Funnel stets sichtbar bleibt (der CRM-Look). Der aktive Tab steuert den Filter; erneutes Klicken setzt ihn zurück auf Alle. Zeilen behalten ihren Score-Ton, Legitimitäts-, PDF- und Report-Hinweise, und die Firmen-Zelle zeigt jetzt ein Markenlogo, wenn Logos aktiviert sind (standardmäßig aus → keine zusätzlichen Anfragen).- Neue schreibgeschützte Route
GET /api/tracker/stagesliefert den kanonischen Funnel (Labels in Reihenfolge) + eine Alias-Faltungs-Map, gespeist ausserver/lib/states.mjs(templates/states.yml, mit dem eingebauten Fallback) — sodass der Client die Status-Whitelist niemals hartcodiert. Die Legacy-Antwort vonGET /api/trackerohne Parameter bleibt unverändert (nur{ rows }). - Neue reine, unit-getestete Client-Lib
public/js/lib/tracker-stages.jsordnet Zeilen den Stufen des Servers zu und toleriert dabei verirrte Markdown-Fettschrift sowie lokalisierte Aliase (z. B.aplicado→Applied). Die Tabs sind barrierefrei (Rolle tablist/tab, aria-selected, ≥44 px Trefferfläche, Anzahl im barrierefreien Namen jedes Tabs). Keine neuen i18n-Schlüssel. Suite 2133.
- Neue schreibgeschützte Route
[1.130.0] — 2026-07-31
Hinzugefügt
- Zwei neue Scan-Quellen aus dem Elternprojekt career-ops v1.24.0 portiert (in-process, keine neuen Abhängigkeiten; beide erscheinen im
#/scan-Quellenfilter und auf der cvstart.org-Landing):- a16z Speedrun (
a16z-speedrun-talent, #2231) — der board-weite JSON-Feed des a16z-Speedrun-Talent-Netzwerks. Host-gepinnt aufspeedrun-talent-network.com, nur HTTPS, 0-indizierte Paginierung mit Seitenobergrenze, Per-Firma-q/Konfigurations-Threading, fail-soft. - Cryptocurrency Jobs (
cryptocurrencyjobs) — das Web3-Jobportalcryptocurrencyjobs.co, eingelesen über seinen öffentlichen RSS-2.0-Feed (ohne Auth). Zweistufige XML-Entity-Dekodierung, ausschließlich Remote-Angebote, Arbeitgeber aus dem Titel-Suffix"… at <Company>"geparst. - Die Registry umfasst nun insgesamt 72 Quellen = 67 englische + 5 russische (
ALL_ADAPTERS= 67 englische Portal-Adapter).
- a16z Speedrun (
Behoben
echojobs— Hybrid-Stellen bleiben von Remote unterscheidbar (spiegelt Parent #2258). Ein case-insensitiverhybrid-Marker liefert nun"<Stadt> · Hybrid"(oder ein bloßesHybrid, wenn keine Stadt vorhanden ist) sowieworkplaceType: 'Hybrid', statt inRemotezusammengefasst zu werden.radancy— Legacy-TalentBrew-Markup + JSON-Ergebnisfragment-Transport (spiegelt Parent a3e6df9), abgesichert über ein injizierbaresopts.fetchJson.
Hinweise
- Nicht portiert — nur CLI-seitige Funktionen des Elternprojekts. Die umfangreiche CLI-/Modus-Fläche von career-ops v1.24.0 bleibt außerhalb von web-ui, da dieses eine Ansicht + dünner Write-Through ist, kein Modus-Host: die Compliance-/Zuständigkeits-Tabellen, das Kontakte-Telefonbuch + vCard, Interview-Transkript-Debriefing/Call-Plattform-Erkennung, Ledger-Statuswechsel, Ergebnis-Erfassung, zweistufige Triage, jd-similarity, das versionierte CV-Artefakt-Schema der Bewerbung, die Playwright-MCP-Erkennung von doctor sowie
portals/fix-slugs.mjs. Scan-Orchestrierungsänderungen, die inscan.mjsdes Elternprojekts leben — der Interamt.de-Playwright-Scanner, die iCIMS-Reverse-ATS-Komplettsuche, der Länder-Eligibility-Remote-Filter, das DNS-Lookup-Pacing, die StepStone-rltr-Deduplizierung sowie die normalisierte Firmenspalte im Scan-Verlauf — gelten nicht: web-ui führt die EN-/RU-Scanner in-process aus und ruftscan.mjsnicht auf. - Bereits abgedeckt. Der Akzentfaltungs-Fix von
role-matcher(#2209) wurde bereits in v1.127.0 portiert, ist hier also ein No-op.
[1.129.1] — 2026-07-29
Behoben
- KI-Review-Nachträge zu den Web-Ports aus v1.128/v1.129 (alle beratend, an der Quelle behoben): Level-Präzedenz in
job-facets.js(ein expliziter Modifikator schlägt nun ein Management-Wort —Senior Engineering Manager→senior, zuvorlead); der Fallback instates.mjswird nicht mehr fixiert (ein erfolgreiches Lesen wird memoisiert, der Fallback ungecacht zurückgegeben — ein beim Boot kurz nicht verfügbares Elternprojekt wird beim nächsten Aufruf neu gelesen) +console.warnbei einer vorhandenen, aber fehlerhaften Datei;score-tone.js— eine Zeile ohne Score ist neutral (muted), nicht rot;domainFromName()überspringt Nicht-ASCII-Slugs vor/api/logo; +ein Isolations-Guard intests/states.test.mjs. +4 Tests → 2073.
career-ops-ui v1.267.1 · page 4/10 · mirror of the project changelog for cvstart.org