feat: personalize scoring and add skills radar

This commit is contained in:
Jens
2026-07-22 19:33:29 +02:00
parent 029df89265
commit a30ecbc553
33 changed files with 1529 additions and 114 deletions
+87
View File
@@ -1488,6 +1488,93 @@ tasks:
completed_at: '2026-07-22'
note: 'Volledige code- en browseraudit: deterministische IT-focus, laatste gebruikersscore, premium Stitch-feed/detail
en adaptieve 320-2560px-layout; 225 tests groen en browsermatrix geslaagd.'
- id: VR-207
title: Cv-gestuurd field- en infrastructuurprofiel
status: done
priority: P0
requirement_ids:
- PR-002
- PR-040
- PR-041
- NFR-002
- NFR-004
depends_on:
- VR-206
summary: Breid de begeleide profielconfiguratie uit voor een ervaren IT field-/infrastructuurprofiel en voorkom
dat een brede, relevante skillset de matchscore kunstmatig verlaagt. Persoonlijke cv-data blijft uitsluitend
in de gebruikersdatabase en komt niet in repositoryfixtures of documentatie.
acceptance_criteria:
- Rollen en skills zijn in begrijpelijke categorieën selecteerbaar voor field service, infrastructuur, Microsoft
365/endpoint, netwerk/security, back-up/monitoring, virtualisatie, VoIP en automation.
- Relevante IT-ervaring is via een selectielijst configureerbaar en wordt deterministisch vergeleken met expliciet
gevraagde ervaringsjaren; onbekende ervaring leidt niet tot uitsluiting.
- Ambigue field-/implementatietitels gelden alleen als IT wanneer de vacaturetekst tevens een sterk technisch
contextsignaal bevat; niet-IT field service blijft gefilterd.
- Meer relevante cv-skills aanvinken verwatert de skillscore niet onbeperkt en niet-vermelde voorkeurskills worden
niet als bewezen tekort gepresenteerd.
- Bestaande vrije profielwaarden blijven selecteerbaar en persoonlijke gegevens uit cv's worden niet gecommit.
verification:
- uv run pytest tests/unit/test_relevance.py tests/unit/test_scoring.py tests/unit/test_profiles.py tests/integration/test_profile_preferences.py
- uv run python manage.py makemigrations --check --dry-run
- ./scripts/codex_verify.sh
primary_paths:
- apps/profiles/forms.py
- apps/profiles/models.py
- apps/profiles/taxonomy.py
- apps/jobs/services/relevance.py
- apps/jobs/services/scoring.py
- templates/profiles/edit.html
- static/css/app.css
result:
completed_at: '2026-07-22'
note: Cv-gestuurde gegroepeerde profielconfiguratie, ervaringsband, begrensde skill-evidence, contextgebonden
fieldrelevantie en lokale profielrescore geverifieerd; 232 tests groen en browsercontrole op ultrawide/390
px geslaagd.
- id: VR-208
title: Skillsvraag- en leerkansenradar zonder ervaringsscore
status: done
priority: P0
requirement_ids:
- PR-002
- PR-040
- PR-041
- PR-043
- PR-050
- NFR-004
depends_on:
- VR-207
summary: Maak ervaringsduur volledig informatief en bouw uit de actuele, relevante vacatures een uitlegbare marktvraaganalyse
met profieldekking, skillsfilters en concrete bijleerkansen.
acceptance_criteria:
- Ervaringsjaren en senioriteitslabels hebben geen invloed op score, aanbeveling of harde uitsluiting; de profielwaarde
is uitsluitend informatieve context en bestaande senioriteitsgewichten worden veilig genegeerd en opgeruimd.
- De analyse gebruikt alleen actieve IT-vacatures die voor het actieve profiel niet hard uitgesloten zijn en blijft
strikt gebruikersgescopeerd.
- Een deterministische, uitbreidbare skillcatalogus toont per technologie of capability in hoeveel vacatures een
expliciet tekstsignaal voorkomt en onderscheidt profieldekking van mogelijke leer-/bijscholingskansen.
- Het profiel biedt extra relevante skills als gegroepeerde checkboxes; de inzichtspagina biedt categorie- en
dekkingsfilters en links naar de onderliggende vacatures.
- Feiten, tekstinferenties en onbekende gegevens zijn in de Nederlandstalige UI duidelijk onderscheiden; lege
toestanden en layouts werken van 320 tot 2560 px zonder horizontale paginaoverflow.
verification:
- uv run pytest tests/unit/test_scoring.py tests/unit/test_skill_demand.py tests/integration/test_skill_insights.py
tests/integration/test_profile_preferences.py
- uv run python manage.py makemigrations --check --dry-run
- ./scripts/codex_verify.sh
- Browsercontrole op 2560x1440, 1440x900 en 390x844
primary_paths:
- apps/jobs/services/scoring.py
- apps/jobs/services/skill_demand.py
- apps/jobs/views.py
- apps/profiles/taxonomy.py
- templates/jobs/skill_insights.html
- static/css/app.css
- docs/architecture/SCORING_ENGINE.md
result:
completed_at: '2026-07-22'
note: Ervarings- en senioriteitsinvloed uit score en learning verwijderd; gebruikersgescopeerde Skillsradar
met actuele bronselectie, vraagbewijs, profieldekking, leerkansen, uitgebreide skillfilters en 2560/1440/390-browsercontrole
voltooid.
- id: VR-301
title: Multi-tenant SaaS, teams en billing
status: deferred
+32 -1
View File
@@ -1,7 +1,7 @@
# Projectstatus
- Laatst bijgewerkt: 2026-07-22
- Repositoryversie: 0.2.11 premium IT-radar en ultrawide Stitch-cockpit
- Repositoryversie: 0.2.13 persoonlijke skillsvraag- en leerkansenradar
- Uitvoeringsmodus: autonome backlog
- Eerste uitvoerbare taak: controleer met `python scripts/backlog.py next`
@@ -140,6 +140,25 @@ VR-206-herverificatie op 2026-07-22:
- de Stitch-cockpit benut maximaal 2240 px met tweekoloms matchfeeds op ultrawide; de zes kernroutes zijn handmatig gecontroleerd op 320, 390, 1024, 1440, 1920 en 2560 px zonder horizontale paginaoverflow;
- dark/light, gelabelde velden, mobiele drawer, score-/confidencecopy, archieffilters en inline bewaren zijn in de geïntegreerde browser gecontroleerd.
VR-207-herverificatie op 2026-07-22:
- 232 geslaagde tests en 2 optioneel overgeslagen pytest-Playwrightvarianten; HTML/a11y-fallback geslaagd;
- 84,59% branch-aware codedekking; Ruff, Django system check, migratiecontrole, taakledger en repositoryvalidatie geslaagd via `scripts/codex_verify.sh`;
- het profiel bevat gegroepeerde field-/infrastructuur-, Microsoft/endpoint-, netwerk/security-, back-up/monitoring-, virtualisatie-, VoIP- en scriptingkeuzes plus een ervaringsband;
- de skillcomponent bereikt zijn maximum bij vier aangetroffen cv-skills en presenteert niet-vermelde voorkeurskills niet meer als tekort;
- ambigue field-/implementatietitels vereisen een onafhankelijk IT-contextsignaal en titeluitsluitingen respecteren woordgrenzen en eenvoudige Engelse meervouden;
- de lokale actieve auditprofielen zijn zonder persoonsgegevens in Git afgestemd op 1014 jaar ervaring, 27 relevante roltitels en 46 cv-skills; na herscoring blijven 14 plausibele field-/infrastructuurkansen zichtbaar;
- geïntegreerde browsercontrole bevestigde de categorie-editor op ultrawide en 390 px, één mobiele categoriekolom, geldige profielselecties en geen horizontale paginaoverflow.
VR-208-herverificatie op 2026-07-22:
- 240 geslaagde tests en 2 optioneel overgeslagen pytest-Playwrightvarianten; HTML/a11y-fallback geslaagd;
- 84,73% branch-aware codedekking; Ruff, Django system check, migratiecontrole, taakledger en repositoryvalidatie geslaagd via `scripts/codex_verify.sh`;
- ervaringsduur en senioriteitslabels hebben geen invloed meer op deterministische score, AI-score, aanbeveling, uitsluiting of feedbacklearning; migratie 0006 ruimt het oude gewicht op;
- de persoonlijke Skillsradar analyseert alleen actieve IT-vacatures met een niet-verborgen score voor de actuele profielversie en laat records van uitsluitend uitgeschakelde bronnen buiten beschouwing;
- de lokale radar toont 9 onderzochte vacatures, 5 herkenbare vraagsignalen, 2 gedekte skills en 3 mogelijke leerkansen zonder een tekstsignaal als harde eis te presenteren;
- geïntegreerde browsercontrole bevestigde filters, 88 profielskillcheckboxes, één `h1`, lege console en geen horizontale paginaoverflow op 2560×1440, 1440×900 en 390×844.
## Deploymentstatus
- `main` is via de bestaande Gitea-SSH-sleutel naar `NuklearRabbit/VacatureRadar` gepusht.
@@ -150,6 +169,18 @@ VR-206-herverificatie op 2026-07-22:
## Laatste uitgevoerde backlogtaak
- 2026-07-22: `VR-208` voltooid.
- Ervaringsjaren zijn alleen nog profielcontext; alle score-, recommendation-, concern-, evidence- en learninginvloed is verwijderd.
- Een gebruikersgescopeerde vraaganalyse brengt actuele skillfrequentie, bewijskwaliteit, profieldekking en niet-blokkerende leer-/bijscholingskansen in kaart.
- De profielcatalogus en nieuwe responsieve Skillsradar ondersteunen Microsoft, netwerk/security, monitoring/platform, ITSM en digitale adoptie met begeleide filters.
- Volgende taak: geen uitvoerbare `ready` taak; `VR-202`, `VR-203` en `VR-204` blijven `blocked-external`.
- 2026-07-22: `VR-207` voltooid.
- De twee aangeleverde cv's zijn visueel en tekstueel lokaal beoordeeld; alleen afgeleide technische profielkeuzes zijn in de lokale gebruikersdatabase opgeslagen.
- Relevante ervaring, rollen, skills en doelgerichte uitsluitingen zijn toegepast en alle 336 actieve vacatures zijn opnieuw gescoord voor beide lokale auditprofielen.
- De profiel- en scorelogica is regressiegedekt; afwezige cv-skills verlagen een breed profiel niet onbeperkt en worden niet als bewezen tekort getoond.
- Volgende taak: geen uitvoerbare `ready` taak; `VR-202`, `VR-203` en `VR-204` blijven `blocked-external`.
- 2026-07-22: `VR-206` voltooid.
- Niet-IT-vacatures en commercieel/recruitmentmisleidende IT-titels zijn standaard uit Vandaag en de vacaturefeed verwijderd zonder bronhistoriek te wissen.
- Matchsortering, radar-/archieffilters, score-evidence en gebruikersgescopeerde dashboardscores maken de dagelijkse selectie beslisbaar.
+9 -6
View File
@@ -24,6 +24,7 @@ Ondersteund of gepland:
- uitgesloten regio/gemeente;
- afstand boven maximum, behalve remote;
- uitgesloten verplichte skill;
- een titelgestuurde IT-grens; ambigue field-/implementatietitels vereisen daarnaast een sterk IT-contextsignaal in de vacaturetekst;
- expliciete rijbewijs-/reis-/taalvereisten wanneer betrouwbaar geëxtraheerd;
- verlopen of niet-actieve vacature buiten de ranking.
@@ -35,15 +36,16 @@ Standaardgewichten, totaal 100:
| Component | Gewicht | Kernsignalen |
|---|---:|---|
| Content | 25 | titelovereenkomst, taken, weinig ongewenste support |
| Skills | 20 | gewenste skills in expliciete velden/tekst |
| Locatie | 15 | afstand, remote/hybrid, voorkeursregio |
| Content | 30 | titelovereenkomst, taken, weinig ongewenste support |
| Skills | 25 | gewenste skills in expliciete velden/tekst |
| Locatie | 20 | afstand, remote/hybrid, voorkeursregio |
| Voorwaarden | 10 | toegestane contract-/werkvorm |
| Werkgever | 10 | directe bron versus recruiter |
| Senioriteit | 10 | gevraagde ervaring versus profiel |
| Voorkeuren | 10 | publieke sector en andere soft signals |
| Voorkeuren | 5 | publieke sector en andere soft signals |
Bij aangepaste gewichten worden componentbijdragen genormaliseerd op de totale som.
- De profielervaring is uitsluitend informatieve context. Gevraagde ervaringsjaren en senioriteitslabels veranderen de score, aanbeveling en uitsluitingen nooit.
- Een breed cv-profiel wordt niet bestraft omdat veel relevante skills zijn geselecteerd: maximaal vier aangetroffen profielskills volstaan voor de volledige skillcomponent. Niet-aangetroffen voorkeurskills blijven evidence, maar worden niet als bewezen tekort of concern gepresenteerd.
- AI-boost is opt-in via profielinstelling en telt alleen mee als profielgewicht > 0.
- De AI-component is softwarematig begrensd (maximale bijdrage via `ai`-gewicht) om dominantie te vermijden.
@@ -91,6 +93,7 @@ Een score bewaart:
Copyregels:
- zeg "niet teruggevonden" in plaats van "ontbreekt" wanneer brondata onvolledig is;
- presenteer niet-vermelde cv-skills niet als tekort; alleen expliciet aangetroffen skills zijn positieve evidence;
- label inference als inference;
- toon maximaal enkele kernredenen bovenaan en volledige details uitklapbaar;
- geef geen kanspercentage op aanwerving zonder gevalideerd model.
@@ -119,7 +122,7 @@ Offline evaluatie is beschikbaar via `scripts/feedback_learning_report.py` met f
Toegestaan:
- support-/consultancy-/travelratio schatten;
- senioritylabel;
- senioritylabel als informatieve extractie, zonder score-invloed;
- korte Nederlandse samenvatting;
- evidencefragmenten selecteren;
- ambiguïteitswarnings.
+1 -1
View File
@@ -97,7 +97,7 @@ De IDs zijn stabiel en worden gebruikt in tests en traceability.
### Matching en ranking
- **PR-040** — Harde regels worden vóór scoring toegepast en zijn uitlegbaar.
- **PR-041** — Scorecomponenten omvatten inhoud, skills, locatie, voorwaarden, werkgever, senioriteit en voorkeuren.
- **PR-041** — Scorecomponenten omvatten inhoud, skills, locatie, voorwaarden, werkgever en voorkeuren. Ervaringsduur en senioriteitslabels blijven uitsluitend informatieve context en beïnvloeden score, aanbeveling of uitsluiting niet.
- **PR-042** — Onbekende data verlaagt confidence en wordt niet automatisch als negatief feit behandeld.
- **PR-043** — Iedere score bewaart componenten, positives, concerns, uitsluitingen en evidence.
- **PR-044** — Profielversie en model-/promptversie worden aan een score gekoppeld.
+8 -7
View File
@@ -7,7 +7,7 @@ Legenda: **I** = geïmplementeerd en getest in de huidige MVP; **P** = gedeeltel
| ID | Status | Primaire implementatie | Bewijs/tests | Vervolgtaak |
|---|---|---|---|---|
| PR-001 | I | `profiles/models.py`, forms/views | `test_profiles.py`, `test_views.py` | — |
| PR-002 | I | `SearchProfile`, defaults/form, geocodeparser | `tests/unit/test_geocoding.py`, `tests/integration/test_import_geodata.py`, profiel- en viewtests | VR-105 verfijnt afstand |
| PR-002 | I | `SearchProfile`, begeleide skilltaxonomie, informatieve ervaringscontext, defaults/form en geocodeparser | `tests/unit/test_geocoding.py`, `tests/integration/test_profile_preferences.py`, profiel- en viewtests | VR-105/VR-207/VR-208 |
| PR-003 | I | `ProfileRevision`, profile services | `test_profiles.py` | — |
| PR-004 | I | begrensde feedbackservice/velden | `tests/unit/test_feedback_learning.py`, `test_profiles.py` | VR-110 uitgevoerd |
| PR-005 | I | `bootstrap_instance`, defaults | task/viewtests | — |
@@ -32,14 +32,14 @@ Legenda: **I** = geïmplementeerd en getest in de huidige MVP; **P** = gedeeltel
| PR-031 | I | conservatieve fuzzy dedupe | `tests/unit/test_dedupe_lifecycle_feedback.py`, `scripts/benchmark.py`, `tests/benchmark/test_benchmark.py` | VR-116 benchmark |
| PR-032 | I | direct-sourcepreferentie/alias | pipeline- en dedupetests | VR-108 resolver |
| PR-033 | I | canonical constraints/transacties | replaytests | — |
| PR-040 | I | features/scoring + deterministische IT-relevantie vóór AI | `tests/unit/test_scoring.py`, `tests/unit/test_relevance.py`, viewtests | VR-206 |
| PR-041 | I | scorecomponenten | `tests/unit/test_features_distance.py`, `tests/unit/test_scoring.py` | VR-105 afgerond |
| PR-040 | I | features/scoring + deterministische IT-relevantie vóór AI, inclusief contextgebonden fieldtitels | `tests/unit/test_scoring.py`, `tests/unit/test_relevance.py`, viewtests | VR-206/VR-207 |
| PR-041 | I | scorecomponenten met begrensde skill-evidence; ervaring/senioriteit aantoonbaar zonder score-invloed | `tests/unit/test_features_distance.py`, `tests/unit/test_scoring.py` | VR-105/VR-207/VR-208 |
| PR-042 | I | unknown/confidencegedrag | `tests/unit/test_features_distance.py`, `tests/unit/test_scoring.py` | VR-105 |
| PR-043 | I | `ScoreRun` | pipeline/scoringtests | — |
| PR-043 | I | `ScoreRun` plus uitlegbare skillvraag-/dekkingsanalyse | pipeline-/scoringtests, `tests/unit/test_skill_demand.py` | VR-208 |
| PR-044 | I | profiel/modelversievelden | scoring/profiletests | VR-109 promptversie |
| PR-045 | I | optionele Ollamaservice/fallback | `test_ai.py` | VR-109 |
| PR-046 | I | geen tools + guardrails | AI/securitytests | VR-109/115 evaluaties |
| PR-050 | I | dashboard/list views + Stitch-dominante cockpitshell/feed/rail en ultrawide compositie | viewtests, VR-119/206 browsermatrix | VR-114/118/119/206 e2e/a11y |
| PR-050 | I | dashboard/list/skillsradar + Stitch-dominante cockpitshell/feed/rail en ultrawide compositie | viewtests, skill-insighttests, VR-119/206/208 browsermatrix | VR-114/118/119/206/208 e2e/a11y |
| PR-051 | I | detailview/template/provenance + scorehero/intelligence-strip | viewtests, VR-119 screenshots | VR-114/118/119 |
| PR-052 | I | feedbackendpoint/UI | feedback/viewtests | — |
| PR-053 | I | applicationmodel/serviceflow | `tests/integration/test_dedupe_lifecycle_feedback.py`, `tests/integration/test_applications.py` | VR-113 uitgebreid dossier |
@@ -59,7 +59,7 @@ Legenda: **I** = geïmplementeerd en getest in de huidige MVP; **P** = gedeeltel
| NFR-001 | I | policy-, URL- en fetchersecuritytests + settings/rate-limit tests | `tests/unit/test_fetcher.py`, `tests/unit/test_rate_limit.py`, `tests/unit/test_settings_security.py`, `tests/integration/test_views.py`, `tests/integration/test_sources_manual_import.py` |
| NFR-002 | P | raw-retentie, minimale modellen, privacyrunbooks | VR-113/115 |
| NFR-003 | I/P | replay-, mail- en outboxtests; per-bronfouten | VR-103/112 |
| NFR-004 | I | ScoreRun, provenance, UI-copy | VR-109 uitgebreid evidence |
| NFR-004 | I | ScoreRun, provenance, skillvraag met expliciet veld-/tekstonderscheid en UI-copy | VR-109/208 uitgebreid evidence |
| NFR-005 | I | domeinapps/services/adapters/ADRs | continue review |
| NFR-006 | I | offline pytest + coveragegate | VR-114 verbreedt e2e |
| NFR-007 | P | `scripts/benchmark.py`, `tests/benchmark/test_benchmark.py` | VR-116 |
@@ -99,4 +99,5 @@ Iedere backlogtaak die een requirement wijzigt, werkt in dezelfde commit deze ma
- VR-201 activeert Gemeente Mol en zeven bijkomende Kempen-werkgevers na menselijke voorwaardenreview, fixtures, fail-closed locatie-/routefilters en twee livecycli. Twaalf interessante werkgevers zonder stabiele actieve ingang staan afzonderlijk en niet-scanbaar op de UI-waaklijst. Bewijs staat in de livecatalogus, seeddata, `KempenEmployerAdapter`, bronruns en adapter-/seed-/viewtests.
- VR-205 laadt de officiële Belgische GeoNames-postcodedataset 2026-04-03 onder CC BY 4.0, documenteert bron- en afgeleide checksums en lost 2400 Mol op naar het benaderende postcodecentrum. Bewijs staat in `config-data/geodata/README.local.md`, het importlog, geocodingtests en de opnieuw berekende profiel-vacaturescores.
- VR-206 voegt een titelgestuurde IT-relevantiegrens vóór scoring/AI toe, maakt de persoonlijke radarselectie de standaard en benut Stitch-panelen dynamisch tot 2560 px. Bewijs staat in `apps/jobs/services/relevance.py`, de score-/viewtests en `docs/design/validation/VR-206_AUDIT.md`.
- VR-207 breidt het profiel uit met gegroepeerde field-/infrastructuurrollen, cv-skills en een ervaringsband. Skill-evidence is op vier treffers begrensd, afwezigheid wordt niet als tekort gepresenteerd en ambigue fieldtitels vereisen een onafhankelijk IT-contextsignaal. Persoonlijke cv-waarden staan uitsluitend in de lokale gebruikersdatabase; repositorytests en documentatie blijven gesaneerd.
- VR-208 maakt die ervaringsband uitsluitend informatief en verwijdert ook senioriteitsinvloed uit de AI-component en feedbacklearning. De gebruikersgescopeerde Skillsradar analyseert actuele niet-uitgesloten IT-vacatures van actieve bronnen, onderscheidt skillveldbewijs van tekstinferentie en toont profieldekking en mogelijke leerkansen met categorie-/dekkingsfilters.