Skip to content

Commit e0ba02b

Browse files
authored
Merge pull request #47 from ondata/feat/amendments-akn-fallback
feat(amendments): fallback bulk AKN GitHub + proponenti dal testo AKN
2 parents 7de4fd9 + 11530c6 commit e0ba02b

12 files changed

Lines changed: 823 additions & 25 deletions

File tree

LOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## 2026-07-10
44

5+
- **feat `amendments` — fallback bulk AKN GitHub + proponenti** (P1 dell'analisi fonti non-LOD; issue #45→#38+#30, branch `feat/amendments-akn-fallback`). Nuovo `src/core/akn.ts` (Worker-compatible, fetch nativo): path atto, listing cartelle via endpoint JSON web-UI GitHub (troncamento a 1000 gestito via totalCount, errore esplicito su finestra irraggiungibile), parser AKN. Il tool: (1) espone `akn_xml_url` su ogni riga LOD (conversione `URLTestoXml`→raw, `flagCommissione` decide emend/emendc); (2) con `ddlUri` e LOD vuoto fa fallback sul bulk (`source=akn`); (3) `--with-proponents` estrae primo firmatario e cofirmatari dal testo AKN (docProponent/TLCPerson, doppia variante markup Assemblea/Commissione, preferito `showAs` col nome completo). **Scoperta in corsa**: il LOD osr:Emendamento si è riallineato tra il 7 e il 10 lug (Piano Casa 0→799, match esatto col bulk 400+399) — freschezza intermittente, il fallback resta rete di sicurezza; trappola nuova `dataPresentazione` xsd:string sui DDL recenti (wiki aggiornato, 3 pagine + log). Verificato: Amidei em. 1.30 ddl/56260 (caso wiki, prima solo via browser WAF), Piano Casa con proponenti da entrambe le sedi. 114/114 test verdi (+11), tsc pulito. Skill CLI e MCP aggiornate. Idea futura annotata: estrattore AKN bulk in Rust per analisi offline (docs/future-ideas.md).
6+
57
- **Analisi fonti non-LOD** in `docs/analisi-fonti-non-lod.md`: le 3 fonti (listasommcomm #33, AKN bulk GitHub #45, RSS per-DDL #13) valutate contro forza/debolezza degli output LOD correnti. Criterio discriminante: il WAF — in un progetto MCP-first una fonte non fetchabile dal Worker vale solo come URL emesso. Priorità: P1 AKN (unica senza WAF, verificata oggi: raw 200 + listing JSON 200) → `amendments` fallback post-2024 + proponente, `bill-text` link AKN; P2 RSS → `rss_url` su `bills`/`bill` (già emesso da 3 tool), niente parsing server-side; P3 listasommcomm → solo colonna `sommari_json_url`, niente fetch (WAF + rate). Commentate le 3 issue con gli esiti.
68

79
- **Wiki LOD**: recepite (spersonalizzate) le conferme del gestore del repository LOD Camera via scambio email — ontologia OCD ferma al 2009-2011, RDF pubblicato a lotti alla ricezione delle triple, emendamenti assenti dal repository, audizioni non strutturate. Nuova sezione "provenienza" in `freschezza-e-autorevolezza.md`, note di conferma in `camera/assenti.md` e `camera/audizioni.md`.

docs/lod-wiki/log.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## 2026-07-10
44

5+
* **SVOLTA + Update**: [emendamenti-freschezza](/senato/emendamenti-freschezza.md) — il dataset `osr:Emendamento` **si è riallineato** tra il 7 e il 10 luglio: Piano Casa `ddl/60233` da 0 a **799** record (682 E + 114 G + 3 Q), match esatto col bulk AKN (400 `emend/` + 399 `emendc/`). Freschezza quindi **intermittente**, non garantita. Trappola nuova: la `osr:dataPresentazione` dei DDL recenti è ora tipizzata **`xsd:string`** (non `xsd:date`) — la query canonica del cutoff con literal tipizzato sottoconta (9 vs 799+); la regola "date Senato sempre xsd:date" non vale più uniformemente.
6+
* **Update**: [emendamenti-firmatario](/senato/emendamenti-firmatario.md) — gap di tooling RISOLTO: `amendments --with-proponents` estrae i proponenti dal bulk AKN senza WAF (conversione `URLTestoXml`→raw). Documentate le due varianti markup (`emend/` testo diretto, `emendc/` nome in `an:span`; preferire `TLCPerson@showAs`, nome completo) e i **file stub vuoti** (200 OK, ~295 byte, zero contenuto).
7+
* **Update**: [akn-bulk-data](/senato/akn-bulk-data.md) — sezione implementazione (`src/core/akn.ts`) + quirks: listing web-UI **troncato a 1000** voci con `totalCount` reale nel payload; `emendc/` usa lo stesso suffisso `-em.akn.xml`; forma payload `.payload.codeViewTreeRoute.tree.items[]`.
8+
59
* **Update**: [freschezza e provenienza](/freschezza-e-autorevolezza.md), [assenti Camera](/camera/assenti.md), [audizioni Camera](/camera/audizioni.md) — recepite (spersonalizzate, come evidenze sul dato) le conferme del **gestore del repository LOD Camera** ricevute via scambio email. Tre punti: (1) l'**ontologia OCD è ferma al 2009-2011** per la parte centrale, con soli sviluppi parziali sulle votazioni — è la causa a monte degli ambiti non modellati; (2) gli **emendamenti non sono presenti** nel repository RDF (conferma dell'assenza già verificata su endpoint, issue #19); (3) le **audizioni non sono maggiormente strutturate** (conferma del recupero solo-da-titolo). Aggiunta a `freschezza-e-autorevolezza.md` la sezione "provenienza": il RDF è l'ultimo anello di un processo distribuito, pubblicato solo alla ricezione delle triple dai singoli produttori dei database sorgente → spiega perché non esiste un "as-of" affidabile. Conferma reciproca: osservazione empirica e provenienza dichiarata convergono.
610

711
## 2026-07-09

docs/lod-wiki/senato/akn-bulk-data.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ I file si scaricano da `raw.githubusercontent.com` con un semplice `curl` — a
3030

3131
# Gap noti che colma (verificati 2026-07-10)
3232

33-
- **Emendamenti fermi ad agosto 2024 nel LOD** ([[emendamenti-freschezza]]): `emend/` del Piano Casa (`Atto00060233`, DDL del 2026) contiene i file AKN degli emendamenti. Il bulk data è fresco dove `osr:Emendamento` è morto. Anche il **proponente** ([[emendamenti-firmatario]]) sta nei file `-em.akn.xml`, ora raggiungibili senza WAF.
33+
- **Emendamenti fermi ad agosto 2024 nel LOD** ([[emendamenti-freschezza]]): `emend/` del Piano Casa (`Atto00060233`, DDL del 2026) contiene i file AKN degli emendamenti. Il bulk data è fresco dove `osr:Emendamento` è morto. Anche il **proponente** ([[emendamenti-firmatario]]) sta nei file `-em.akn.xml`, ora raggiungibili senza WAF. *(Aggiornamento 2026-07-10: il LOD si è nel frattempo riallineato — Piano Casa 799 record, match esatto col bulk — ma la freschezza LOD resta intermittente, quindi il bulk resta il fallback; il proponente invece è SOLO qui.)*
3434
- **Votazioni COVID 2020 assenti dal LOD** ([[votazioni-covid-2020]]): `Leg18/Atto00052873/resaula/01150035-ra.akn.xml` è il resoconto d'Aula del **9/4/2020** e contiene la proclamazione della fiducia sul Cura Italia con i contatori (presenti 246, votanti 245, …). Il dato però è **testo narrativo** dentro `<an:p>` ("Proclamo il risultato della votazione nominale…"), non campi strutturati: recuperabile con parsing, non con query.
3535
- **Testi DDL dietro WAF**: `ddlpres/` dà il testo presentato in XML senza passare dal fascicolo PDF del sito.
3636

@@ -43,6 +43,21 @@ Il **path della cartella** è interamente deducibile: `Leg<leg>/Atto<id ddl zero
4343

4444
Nota: `osr:testoPresentato`/`osr:testoApprovato` del LOD sono URN NIR, **non** ID_TESTO — non aiutano a costruire i filename.
4545

46+
# Implementato nel tool `amendments` (2026-07-10)
47+
48+
Il tool `amendments` usa questo bulk in due modi (helper in `src/core/akn.ts`, Worker-compatible):
49+
50+
1. **Colonna `akn_xml_url` su ogni riga LOD**: conversione `osr:URLTestoXml` → URL raw (via 1 sopra), con `osr:flagCommissione` a scegliere `emend/` vs `emendc/`.
51+
2. **Fallback automatico**: con `ddlUri` e LOD vuoto, listing di `emend/`+`emendc/` via endpoint JSON web-UI (via 2 sopra) e righe `source=akn`.
52+
3. **`withProponents`**: fetch puntuale dei singoli XML e parsing di `docProponent`/`TLCPerson` (primo = primo firmatario; dettagli markup in [[emendamenti-firmatario]]).
53+
54+
Quirks verificati implementando:
55+
56+
- Il listing web-UI **tronca a 1000 voci** per cartella; `totalCount` nel payload dà il totale reale (es. `Leg18/Atto00052873/emend`: items 1000, totalCount 1658). Da gestire esplicitamente, non silenziosamente.
57+
- Anche `emendc/` usa il suffisso `-em.akn.xml` (non un suffisso proprio).
58+
- Esistono **file stub vuoti** (~295 byte, solo `akomaNtoso` autochiuso): HTTP 200 ma zero contenuto (es. odg G1.17 del Piano Casa).
59+
- La forma del payload JSON del listing è `.payload.codeViewTreeRoute.tree.items[]` (endpoint non documentato: validare la forma e fallire esplicito se cambia).
60+
4661
# Limiti
4762

4863
- Organizzato **per Atto Senato**: copre solo documenti legati a un DDL. Le **audizioni** (Ufficio di Presidenza, indagini conoscitive) NON ci sono — per quelle resta solo l'HTML "Audizioni e documenti acquisiti" ([[sedute-commissione]]).

docs/lod-wiki/senato/emendamenti-firmatario.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,26 @@ Il **primo** `an:docProponent` è il primo firmatario, i successivi i cofirmatar
3737

3838
Trappola accesso: `www.senato.it` è **dietro AWS WAF**`curl` diretto restituisce 403 (301→CloudFront in HTTP, 403 in HTTPS). Il recupero richiede un fetch browser-class (agente browser con token WAF), non `curl`.
3939

40-
# Conseguenza per il tooling
40+
# Conseguenza per il tooling — RISOLTO (2026-07-10)
4141

42-
Il tool `amendments` (Senato) oggi non espone il firmatario perché non è nel LOD. Il tool `camera-amendments` (Camera) invece **lo espone** (`first_signatory`) facendo scraping fuori dal LOD (app HTML `documenti.camera.it`). L'asimmetria è quindi di **tooling** — un ramo esce dal LOD, l'altro no — su un limite LOD condiviso (nessun firmatario emendamento nel LOD di nessuna delle due camere). È colmabile allo stesso modo: parsing dell'AKN `URLTestoXml`, con il primo `docProponent` come primo firmatario.
42+
Il tool `amendments` ora espone il proponente con `withProponents`/`--with-proponents`: il testo AKN si recupera **senza WAF** dal bulk GitHub del Senato ([[akn-bulk-data]]) convertendo `osr:URLTestoXml` in URL raw (pura sostituzione di stringa: ultimo segmento → `<path atto>/emend[c]/<id>-em.akn.xml`, con `osr:flagCommissione` a decidere `emend/` vs `emendc/`). Simmetria raggiunta con `camera-amendments` (`first_signatory`). Il limite LOD a monte resta: nessun firmatario emendamento nel grafo di nessuna delle due camere.
43+
44+
Colonne emesse: `first_proponent`/`proponents` (nomi) **e** `first_proponent_uri`/`proponents_uri` (URI `dati.senato.it/<id>` da `an:TLCPerson`, stesso ordine dei nomi): l'URI è ciò che permette il join con altri tool (es. risalire alla scheda del senatore), il nome da solo non basta (omonimie, forma non normalizzata).
45+
46+
## Due varianti del markup docProponent (verificate 2026-07-10)
47+
48+
- **File d'Assemblea** (`emend/`): nome come testo diretto del tag — `<an:docProponent ...>DI GIROLAMO</an:docProponent>`.
49+
- **File di Commissione** (`emendc/`): nome annidato in un `<an:span>` dentro il tag. In entrambi i casi `an:TLCPerson` (via `refersTo`) dà l'`href` (URI persona `dati.senato.it/<id>`) e `showAs` col **nome completo** ("Bartolomeo Amidei" contro "Amidei" nel testo): preferire `showAs`.
50+
51+
## File stub vuoti
52+
53+
Alcuni file del bulk sono **stub vuoti** (solo l'elemento `akomaNtoso` autochiuso, ~295 byte): es. `Leg19/Atto00060233/emend/01511907-em.akn.xml` (odg G1.17). Il file esiste (HTTP 200) ma non ha numero né proponenti: gap della fonte, non dell'estrazione. `parseAknAmendment` non lancia mai su questi file (torna solo campi vuoti) — per design, indistinguibile da un vero fallimento di fetch a livello di singola riga.
54+
55+
## Outage sistematico vs vuoto legittimo
56+
57+
`enrichProponents` (in `amendments.ts`) distingue i due casi a livello di finestra: un singolo fetch fallito (rete, 404) lascia la riga vuota senza bloccare le altre; se **tutti** i fetch della finestra falliscono, è quasi certamente un'irraggiungibilità di GitHub (es. dal Worker, cfr. [[akn-bulk-data]] "verifiche pendenti") e il tool lancia un errore esplicito invece di restituire righe silenziosamente vuote indistinguibili dal caso legittimo.
4358

4459
# Citations
4560

4661
[1] Verifica 2026-07-05: proprietà di `osr:Emendamento` (campione 200) e assenza legame senatore→emendamento; endpoint `dati.senato.it/sparql`. Testo AKN `emendamento/1067383` recuperato via agente browser (WAF): 5 `an:docProponent`.
62+
[2] Verifica 2026-07-10: `amendments list --ddl-uri http://dati.senato.it/ddl/56260 --with-proponents` → em. 1.30 "Bartolomeo Amidei" + 5 proponenti (stesso caso di [1], ora senza browser); Piano Casa `ddl/60233` con proponenti da `emend/` (testo diretto) e `emendc/` (span annidato).

docs/lod-wiki/senato/emendamenti-freschezza.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
11
---
22
type: Gotcha
3-
title: Emendamenti al Senato — dataset fermo da agosto 2024
4-
description: osr:Emendamento non ha alcun collegamento (via osr:oggetto/osr:relativoA) a DDL presentati dopo il 9 agosto 2024; il tool amendments restituisce vuoto per qualunque provvedimento più recente, a prescindere dal DDL usato.
3+
title: Emendamenti al Senato — freschezza intermittente (fermo ago 2024 → refresh lug 2026)
4+
description: osr:Emendamento è rimasto ~2 anni senza collegamenti a DDL presentati dopo il 9 agosto 2024, poi un refresh (rilevato 2026-07-10) lo ha riallineato. La freschezza non è garantita nel tempo; il tool amendments ha un fallback sul bulk AKN GitHub.
55
resource: https://dati.senato.it/sparql
66
tags: [senato, osr, emendamenti, freschezza, assenti]
7-
timestamp: 2026-07-07
7+
timestamp: 2026-07-10
88
---
99

10-
Il tool `amendments` (Senato) restituisce **sempre vuoto** sui DDL più recenti — verificato su DL Sicurezza 2025 (`ddl/59201`) e Piano Casa 2026 (`ddl/60233`) — mentre funziona su provvedimenti anche molto vecchi (Cura Italia 2020, `ddl/52873`, 3.827 emendamenti; DL Dic. 2022, `ddl/56260`, 119 emendamenti).
10+
# AGGIORNAMENTO 2026-07-10: il dataset è stato aggiornato (refresh tra il 7 e il 10 luglio)
11+
12+
La verifica del 2026-07-07 (sotto, mantenuta come storia) trovava **0** emendamenti per il Piano Casa (`ddl/60233`). Il 2026-07-10 lo stesso conteggio dà **799** (682 tipo `E`, 114 `G`, 3 `Q`) — che combacia esattamente col bulk AKN GitHub (400 in `emend/` + 399 in `emendc/`). Il dataset `osr:Emendamento` è quindi tornato vivo dopo ~2 anni di stallo.
13+
14+
Due conseguenze operative:
15+
16+
1. **La freschezza è intermittente, non garantita**: il dataset è rimasto fermo per quasi due anni ed è ripartito senza alcun segnale di versioning (vedi [freschezza e autorevolezza](../freschezza-e-autorevolezza.md)). Non assumere né che sia fermo né che sia aggiornato: verificare sul provvedimento.
17+
2. **Trappola nuova sulla query canonica del cutoff**: la query sotto (FILTER su `dataPresentazione` con literal `^^xsd:date`) oggi restituisce **9**, non 799+ — perché la `osr:dataPresentazione` dei DDL recenti (es. `ddl/60233`) è ora tipizzata **`xsd:string`**, non `xsd:date`, e il confronto tipizzato la esclude. La regola "date Senato = sempre xsd:date tipizzato" non vale più uniformemente: il refresh ha introdotto date string. Per conteggi affidabili confrontare con `STR(?data)`.
18+
19+
Il tool `amendments` resta protetto in entrambe le direzioni: se il LOD è indietro, con `ddlUri` fa fallback sul bulk AKN GitHub ([[akn-bulk-data]]), che è aggiornato quotidianamente.
20+
21+
---
22+
23+
# Storia (verifica 2026-07-07): dataset fermo da agosto 2024
24+
25+
Il tool `amendments` (Senato) restituiva **sempre vuoto** sui DDL più recenti — verificato su DL Sicurezza 2025 (`ddl/59201`) e Piano Casa 2026 (`ddl/60233`) — mentre funzionava su provvedimenti anche molto vecchi (Cura Italia 2020, `ddl/52873`, 3.827 emendamenti; DL Dic. 2022, `ddl/56260`, 119 emendamenti).
1126

1227
# Non è un problema di lettura/ddl_uri sbagliato
1328

skills/italian-parliament-cli/references/commands.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,11 @@ italianparliament bill-committees list --bill-uri http://dati.camera.it/ocd/atto
161161
```
162162

163163
### `amendments list`
164-
Emendamenti Senato; `--ddl-uri` per gli emendamenti a un DDL specifico.
164+
Emendamenti Senato; `--ddl-uri` per gli emendamenti a un DDL specifico. Ogni riga espone `akn_xml_url` (testo AKN raw dal bulk GitHub del Senato, senza WAF). Se il LOD è indietro, con `--ddl-uri` il tool passa da solo al bulk AKN (`source=akn`). `--with-proponents` aggiunge primo firmatario e cofirmatari (nome + URI persona, colonne `first_proponent`/`first_proponent_uri`/`proponents`/`proponents_uri`) dal testo AKN (il proponente NON è nel LOD; un fetch per emendamento, più lento: richiede `--limit<=100`, errore esplicito oltre). Popola anche la colonna `date` (data di presentazione) quando il LOD non ce l'ha. `type` (E/G/Q, dal LOD) e `sede` (commissione/assemblea) sono colonne distinte: `type` resta vuota sulle righe `source=akn`.
165165
```bash
166166
italianparliament amendments list --legislature 19
167167
italianparliament amendments list --ddl-uri http://dati.senato.it/ddl/56260 --format jsonl
168+
italianparliament amendments list --ddl-uri http://dati.senato.it/ddl/60233 --with-proponents --limit 20
168169
```
169170

170171
### `camera-amendments list`

skills/italian-parliament-mcp/references/tools.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,12 @@ Commissioni a cui un DDL/atto è assegnato, **Camera o Senato** (il ramo è rico
119119
- `billUri` (required): URI del DDL/atto (Camera `attocamera.rdf/...` o Senato `ddl/...`)
120120

121121
### `amendments`
122-
Emendamenti Senato con DDL collegato.
122+
Emendamenti Senato con DDL collegato. Ogni riga espone `akn_xml_url` (testo AKN raw dal bulk GitHub del Senato, senza WAF). Se il LOD è indietro, con `ddlUri` il tool passa da solo al bulk AKN (`source=akn`).
123123
- `legislature`: numero legislatura
124124
- `ddlUri`: filtra gli emendamenti a un DDL specifico
125+
- `withProponents`: aggiunge primo firmatario e cofirmatari (nome + URI persona, colonne `first_proponent`/`first_proponent_uri`/`proponents`/`proponents_uri`) dal testo AKN (il proponente NON è nel LOD; un fetch per emendamento, più lento: richiede `limit<=100`, errore esplicito oltre). Popola anche la colonna `date` (data di presentazione) quando il LOD non ce l'ha.
126+
127+
`type` (E/G/Q, dal LOD) e `sede` (commissione/assemblea, da entrambe le fonti) sono colonne distinte: `type` non è deducibile in modo affidabile dal solo bulk AKN e resta vuota nelle righe `source=akn`.
125128

126129
### `camera-amendments`
127130
Emendamenti (proposte emendative) a un atto **Camera**, per sede (referente/Assemblea). Fonte: app HTML `documenti.camera.it` (gli emendamenti Camera non sono nel LOD), via scraping. Output per emendamento: `sede`, `article`, `number`, `first_signatory`, `person_id`, `identical`, `text_url`.

src/cli.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,12 @@ const amendmentsList = defineCommand({
10241024
args: {
10251025
legislature: { type: "string", description: "Legislature number" },
10261026
"ddl-uri": { type: "string", description: "Filter amendments to a specific bill (Senato ddl URI)" },
1027+
"with-proponents": {
1028+
type: "boolean",
1029+
default: false,
1030+
description:
1031+
"Enrich rows with proponents from the Senato AKN bulk data (one fetch per amendment, slower)",
1032+
},
10271033
limit: { type: "string", default: "100" },
10281034
offset: { type: "string", default: "0" },
10291035
format: { type: "string", default: "csv" },
@@ -1032,6 +1038,7 @@ const amendmentsList = defineCommand({
10321038
const result = await runTool(amendmentsTool, {
10331039
legislature: parseIntFlag(args.legislature as string, "legislature"),
10341040
ddlUri: (args["ddl-uri"] as string) || undefined,
1041+
withProponents: Boolean(args["with-proponents"]),
10351042
limit: parseIntFlag(args.limit as string, "limit") ?? 100,
10361043
offset: Number(args.offset ?? 0),
10371044
});

0 commit comments

Comments
 (0)