v1.15.0: filter vereenvoudigd naar drie regels — 30 semantische groepen i.p.v. families+whitelist+blacklist
- Strip de filter terug tot: (1) sterk signaal in de titel -> door; (2) score van unieke semantische groepen >= 3 met titel-signaal -> door; (3) anders weg. Geen whitelist (82 termen), geen blacklist, geen span-merge, geen dienststoring-titelanker meer; woordgrenzen/lookbehinds weren de bekende botsingen structureel (schoolbus/VW-bus/stationsstraat/stationair/ treinstraat/treinweg). - Lijsten 49 families + 82 whitelist + 2 blacklist = 133 -> 16 sterk + 14 ambigu = 30 groepen; filterzone 524 -> ~292 regels; match-methodes 4 -> 2. - Vijf historische uitzonderings-families geschrapt (busongeluk, sein, breng, hermes, inchecken, kaartje, rails, staking, e.d.) — die woorden leveren nu 0 signalen op en de bekende false positives blijven geweerd. - Completheids-audit ving de Maaslijn/Nedersaksenlijn/Kamperlijn/waterbus- regressie op (hersteld); resterende zero-hit-kandidaten geen wijziging. - validate_filter.py: invarianten 1-3 + 113 regressie-cases (90 onveranderd groen + 23 nieuw); prompt-matrix 27/27. - Gedragswijziging op 45 productiedagen: uitsluitend false positives extra geweerd (buitenlandse veerboot-rampen, Zwitsers busongeluk, delftopzondag tram+halte, Cox/RET, tram-blokkade); 0 recalls verloren. - README/AGENTS.md/vault bijgewerkt.
This commit is contained in:
parent
0c5a07071c
commit
ac30575660
6 changed files with 381 additions and 695 deletions
77
README.md
77
README.md
|
|
@ -38,53 +38,40 @@ Bestuurders: admins uit de config, of gebruikers met een powerlevel ≥ dat van
|
|||
RSS-state-event in die room (default 50 als geen level is ingesteld).
|
||||
Bij een room-tombstone worden abonnementen automatisch naar de vervangende room verplaatst.
|
||||
|
||||
## Het OV-matchfilter (v1.14.0)
|
||||
## Het OV-matchfilter (v1.15)
|
||||
|
||||
De volledige classificatie + de werkwijze voor nieuwe woorden staat in
|
||||
`buzzrss/bot.py`, boven `MATCH_FILTER_FAMILIES` — **dat blok is leidend** bij elke
|
||||
wijziging. Samengevat:
|
||||
`buzzrss/bot.py`, boven `MATCH_FILTER_STRONG` — **dat blok is leidend** bij elke
|
||||
wijziging. Samengevat, in drie regels:
|
||||
|
||||
```text
|
||||
score = Σ gewichten van unieke OV-termen over titel + samenvatting
|
||||
(één term = één signaal per artikel; overlappende familie-treffers wegen 1×
|
||||
met het hoogste gewicht — span-merge, besluit 2026-09-13)
|
||||
+ 2 als een whitelist-term óf een dienststoring-zin in de TITEL staat
|
||||
|
||||
doorlaten ⇔ score ≥ 3 én (titel-signaal ∨ geen zwakke term in de score)
|
||||
1. staat er een STERK signaal in de TITEL? -> PLAATSEN
|
||||
2. score = som unieke groeps-gewichten ≥ 3 én de titel bevat een signaal? -> PLAATSEN
|
||||
3. anders -> NIET PLAATSEN
|
||||
```
|
||||
|
||||
Stappen:
|
||||
|
||||
1. **Sterk titel-signaal — door.** Een whitelist-term (NS, ProRail, spoorstoring,
|
||||
perron, bushalte, ovpay, openbaar vervoer, …) of een dienststoring-zin
|
||||
(‹vervoerswoord› `rijdt/rijden … niet`, bv. 'sprinters rijden niet', 'metro rijdt niet')
|
||||
in de titel is voldoende.
|
||||
2. **Context — som ≥ 3.** Gewichten: **sterk (2)** = onmiskenbaar OV
|
||||
(vervoerders, spoorinfra, bus-samenstellingen, trein-storingsjargon, tram/metro/halte,
|
||||
storingszin, …), **zwak (1)** = dubbelzinnig, elk met een eigen familie
|
||||
(trein, bus, station(s), sprinter, reiziger, vervoerder, sein, overweg, breng, …)
|
||||
en alleen als combinatie geldig. Max-2-stelsel: geen enkele familie weegt meer dan 2,
|
||||
één sterke hit kan nooit solo doorlaten.
|
||||
3. **Titel-anker.** Zonder enig OV-signaal in de titel (geen familie-hit, geen
|
||||
whitelist-term, geen storingszin) mag de score geen zwak woord bevatten —
|
||||
'station' + 'pendelbus' + 'bus' in een samenvatting is geen OV-bewijs.
|
||||
Uitzondering die bewust blijft: **twee sterke termen in de samenvatting** (bv. de
|
||||
delftopzondag-bereikbaarheidszin 'tram 1, halte Buitenhofdreef', besluit 2026-09-13).
|
||||
|
||||
Zwarte lijst (`MATCH_FILTER_BLACKLIST`): gematchte woorden zonder OV-waarde —
|
||||
na de v1.14.0-opschoning alleen nog `treinstraat`/`treinweg`. De oudere
|
||||
stations\*-vormen (`stationsstraat`, `stationair`, `stationcar`, `stationeren`, …)
|
||||
zijn inert sinds de woordgrens-familie `\bstations?\b` en worden door tests bewaakt.
|
||||
|
||||
### Bekende bewust-geaccepteerde doorlatingen / weigeringen
|
||||
|
||||
- *Door*: 'met een tram en halte bereikbaar'-zinnen in lokale berichten (2 sterke
|
||||
termen, samenvatting) — kurk op de fles is het max-2-stelsel + titel-anker.
|
||||
- *Geweerd*: krant 'De Metro', café 'De Tram', atleet-'sprinter',
|
||||
'VW-bus'/'schoolbus' (koppelteken- en woordgrensregels), werkwoord 'brengen',
|
||||
- **Sterk (2 punten, titel = zelfstandig)**: vervoerders (NS, ProRail, Arriva,
|
||||
RET, GVB, Qbuzz, Deutsche Bahn, TESO, ...), spoorjargon (spoorstoring, spoorlijn,
|
||||
wisselstoring, treinstoring, ertms, perron, ...), bus-samenstellingen
|
||||
(bushalte, buslijn, busbaan, buschauffeur), tramverkeer/tramlijn, metrolijn,
|
||||
intercity/streekvervoer/veerdienst/buurtbus, conducteur, ov-chipkaart/ovpay,
|
||||
openbaar vervoer, lightrail, 'lijn 12', ICE-frasen, rangeer... én de
|
||||
dienststoring-zin ('sprinters rijden niet', 'metro rijdt niet').
|
||||
- **Ambugue (1 punt; halte/tram/metro/spoorbrug 2)** — contextafhankelijk,
|
||||
nooit zelfstandig voldoende, alleen als combinatie: `bus`, `trein`,
|
||||
`station(s)`, `reiziger`/`passagier`, `vervoer(der)`, `sprinter`,
|
||||
`pendelbus`/`shuttlebus`, `dienstregeling`, `ontsporen`, `spoor`.
|
||||
- **Semantische groepen tellen één keer per artikel**: 'bus' + 'buslijn' +
|
||||
'busvervoer' + 'busstation' is één bus-signaal (bus-samenstelling, bus,
|
||||
station — nooit vier onafhankelijke signalen).
|
||||
- **Geen whitelist, geen blacklist**: woordgrenzen en koppelteken-lookbehinds
|
||||
weren structureel 'schoolbus'/'VW-bus', 'stationsstraat'/'stationair'/
|
||||
'stationcar'/'treinstraat'/'treinweg'. Bekende false positives blijven geweerd:
|
||||
krant 'De Metro', café 'De Tram', atleet-'sprinter', werkwoord 'brengen',
|
||||
idioom 'goed met elkaar overweg kunnen', 'een wijk opwaarderen',
|
||||
brandweerjargon 'sein brandmeester', figuratief 'weer op de rails',
|
||||
achternaam 'Hermes' (Margraten), 'restaurant/woning naast busstation'.
|
||||
achternaam 'Hermes', buitenlandse veerboot-/busrampen, 'restaurant/woning naast
|
||||
busstation'.
|
||||
|
||||
## Tests
|
||||
|
||||
|
|
@ -92,13 +79,13 @@ zijn inert sinds de woordgrens-familie `\bstations?\b` en worden door tests bewa
|
|||
python3 validate_filter.py
|
||||
```
|
||||
|
||||
Vaste invarianten + regressie (momenteel **90 cases**):
|
||||
Vaste invarianten + regressie (momenteel **110 cases**):
|
||||
|
||||
1. dubbelzinnige woorden → alleen zwak (1), nooit whitelist;
|
||||
2. onmiskenbare OV-termen → sterk (2) of whitelist;
|
||||
3. alle families compileren, gewichten in {1, 2};
|
||||
4. elke whitelist-term zit óók in een familie én elke zwartgelijste term wordt door
|
||||
een familie gematcht (geen inert gewicht).
|
||||
1. gewichten geldig (sterk 2; ambigu in {1, 2}), drempel 3;
|
||||
2. trefwoorden matchen hooguit één groep per categorie (geen overlappende regexes);
|
||||
3. semantische varianten ('bus' + 'buslijn' + 'busvervoer', 'station'-reeks)
|
||||
leveren samen één signaal op;
|
||||
4. regressie: bekende positive/negative/combinatie-cases (precision-first).
|
||||
|
||||
**Verplicht vóór elke filterwijziging** (zie `AGENTS.md`): het classificatiebeleid in
|
||||
`buzzrss/bot.py` lezen, `validate_filter.py` groen, en de **compleetheids-audit**:
|
||||
|
|
|
|||
Loading…
Reference in a new issue