Repository navigation
fix(drift): missing solo con prova di assenza — regola unica, non patch per kind - #439
Merged
Merged
Conversation
…atch per kind
Il drift dichiarava `missing` quando un ref non si trovava nell'inventario,
assumendo che l'inventario descrivesse tutto ciò che la fonte pubblica. Non è
vero per 3 dei 5 kind, e ogni kind che poggia sull'assunzione perdeva:
- `ckan_resource`: l'inventario tiene UNA distribuzione per item, ma un
package CKAN ne ha in media decine → open-mur segnava 9 resource "sparite"
che invece esistono (verificato con `resource_show`);
- `ckan_dataset`: il matcher toglieva il placeholder e faceva `startswith`,
che funziona solo con la parte fissa in testa: `{year}-nome` non matchava
mai → 1 falso positivo su open-mur;
- `url`: già risolto con la verifica HTTP (#437), stesso principio.
Ora la regola è una sola, dichiarata in `drift.ABSENCE_EVIDENCE`: `missing`
solo con prova positiva di assenza — inventario **completo** per quel kind,
oppure verifica diretta dell'item. Un kind non dichiarato non può dichiarare
`missing`: al massimo `unknown`.
- drift.py: tabella `ABSENCE_EVIDENCE` (load-bearing in `_state_for`),
`_match_ckan_dataset` con placeholder come wildcard, nuovo
`_ckan_resource_state` (probe o `unknown`)
- build.py: `_CkanResourceProbe` — `resource_show` sull'endpoint CKAN della
fonte, cache per run, UA di config; 403/429/rete → non concludente
- runbook: la regola della prova di assenza, con la tabella per kind
Misurato: open-mur **10 missing → 0** (13/13 matched, 9 via `resource_show`);
nessuna regressione su appalti-pubblici (13/13), indice-pa (9/9), e il drift
**reale** di Consip resta segnalato (1 missing, il 404 del 2023).
Verifiche: 452 passed / 2 skipped, mypy e ruff puliti.
Follow-up dei finding della review su #439. - `_MATCHERS` non elenca più `ckan_resource` (kind a tre stati): ogni kind ha un solo percorso - `_state_for` consulta `ABSENCE_EVIDENCE` come **primo** passo: un kind non dichiarato non entra nel check, e la prova dichiarata decide se l'assenza può diventare `missing` - gate a **uguaglianza** (dichiarato ⇔ instradabile) invece che a sottoinsieme: copre anche "dichiarato ma non instradabile" - nuovo test: un kind fuori tabella non entra nel check Comportamento invariato, verificato su open-mur (13/13, 9 via resource_show), appalti-pubblici (13/13) e open-consip (1 missing reale). Verifiche: 453 passed / 2 skipped, mypy e ruff puliti.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sintesi
Il drift dichiarava
missingogni volta che un ref non si trovava nell'inventario, assumendo che l'inventario descrivesse tutto ciò che la fonte pubblica. Non è vero per 3 dei 5kind, e ognuno di quelli che poggia sull'assunzione produce falsi positivi.Emerso mergiando i catalog dei 9 repo:
open-mursegnava 10 item "spariti" che invece esistono.Questa PR sostituisce i rattoppi per
kindcon una regola sola.Cosa cambia
La regola:
missingsolo con prova positiva di assenza dell'item esatto. La prova richiesta è dichiarata perkindindrift.ABSENCE_EVIDENCE:kinddataflowinventoryckan_datasetinventoryckan_resourceprobeurlprobescript_typeinventoryUn
kindnon dichiarato non può dichiararemissing: al massimounknown. La tabella è il registro dei kind:_state_forla consulta come primo passo, e il gate (TestAbsenceEvidence) verifica che dichiarato e instradabile coincidano — un kind dichiarato ma non instradabile è una promessa vuota, un kind instradabile ma non dichiarato potrebbe diremissingsenza prova.Precisazione onesta su cosa decide cosa: la tabella decide se un kind può dichiarare
missing(e un kind fuori tabella non entra nemmeno nel check); come si ottiene la prova lo sceglie il kind — matcher sull'inventario, oppure probe (url→ HTTP,ckan_resource→resource_show). Perscript_typela voce èinventoryma il match resta un'euristica per token: il suomissingsignifica "la famiglia c'è, la variante no", non un'assenza provata come perdataflow.Due bug chiusi (entrambi su open-mur):
ckan_resource— l'inventario tiene una distribuzione per item (mur_ustat: media 10,9 resource per package, max 59). Non trovare un resource ID non prova nulla. Ora: inventario conferma →matched; altrimenti_CkanResourceProbechiede aresource_showsulla fonte CKAN (endpoint derivato dalbase_url); senza probe →unknown.ckan_dataset— il matcher toglieva il placeholder e facevastartswith: funziona solo con la parte fissa in testa. Con{year}-nomela parte fissa è un suffisso e il match falliva sempre. Ora i placeholder sono wildcard (fullmatch).Verifica
Il
missingresiduo di Consip è drift reale (consumi-in-convenzione-2023.csv→ 404): la regola non nasconde i problemi veri, toglie solo quelli inventati.open-mur: 10 missing → 0, con 9 resource confermate daresource_showe 1 package confermato dal matcher corretto.Note per chi revisiona
resource_probe), comeurl_probe:drift.pyresta puro, senza I/O. Il cablaggio sta inbuild.py.resource_showè una richiesta per resource non confermata (open-mur: 9), con cache per run. 403/429/rete → non concludente, coerente conurl_probe.probe_patternresta l'unico punto HTTP per gli URL; il probe CKAN è separato perché è un'API, non un file.