feat(amendments): fallback bulk AKN GitHub + proponenti dal testo AKN#47
Conversation
- src/core/akn.ts (Worker-compatible): path atto, listing via endpoint JSON web-UI GitHub (troncamento 1000 gestito via totalCount), URL raw, parser AKN (FRBRnumber/name/date, docProponent/TLCPerson con doppia variante markup Assemblea/Commissione, preferito showAs) - amendments: colonna akn_xml_url su righe LOD (URLTestoXml->raw, flagCommissione decide emend/emendc); fallback source=akn con ddlUri e LOD vuoto; withProponents/--with-proponents (concorrenza 4) - hint doppia-fonte; emptyHint senza claim "fermo ad ago 2024" (LOD riallineato tra 7 e 10 lug: Piano Casa 0->799, match esatto bulk) - wiki: emendamenti-freschezza (refresh + trappola dataPresentazione xsd:string), emendamenti-firmatario (risolto, markup, stub vuoti), akn-bulk-data (implementazione + quirks); skill CLI e MCP aggiornate - test: +10 unit akn, +3 integrazione; 114/114 verdi, tsc pulito Closes #38, closes #30. Rif. #45. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
| Filename | Overview |
|---|---|
| src/core/akn.ts | New module: AKN bulk data helpers (aknAttoPath, listAknDir, parseAknAmendment, mapLimit, fetchAknFile). Two-pass attribute extraction addresses previous review concerns; listing sorted for determinism; explicit errors on format/truncation changes. |
| src/tools/amendments.ts | Extends the amendments tool with akn_xml_url on every LOD row, automatic fallback to AKN bulk when LOD is empty with ddlUri, and withProponents enrichment; truncation guard and all-failures detection are correctly implemented. |
| src/core/akn.test.ts | New offline unit tests covering path construction, URL conversion, AKN parsing (incl. attribute-order inversion regression), deduplication, and mapLimit concurrency semantics. |
| src/tools/tools.test.ts | Adds integration tests for akn_xml_url presence, AKN fallback with hint, withProponents extraction, limit guard, all-failures detection, and checkAknTruncation variants (online + offline). |
| src/cli.ts | Adds --with-proponents boolean flag to amendments list command, correctly wired to withProponents input parameter. |
Reviews (8): Last reviewed commit: "fix(amendments): hint distinto per pagin..." | Re-trigger Greptile
…tile) - FRBRdate e TLCPerson: two-pass (isola il tag, poi estrae ogni attributo) invece di assumere un ordine date=/name= o id=/href=/showAs= fisso, non garantito dallo standard XML - rimosso claim obsoleto "fermo al 2024-08-09" da un commento interno (LOD osservato riallinearsi 7-10 lug, gia' riflesso nelle stringhe user-facing) - +1 test di regressione con attributi in ordine invertito 115/115 test verdi, tsc pulito. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
parseAknAmendment gia' restituiva l'URI per proponente, ma le colonne first_proponent/proponents scartavano tutto tranne il nome - impossibile il join con altri tool (es. risalire alla scheda senatore, disambiguare omonimie). Aggiunte first_proponent_uri/proponents_uri, inizializzate su entrambi i rami (LOD e fallback AKN) per coerenza JSONL. 115/115 test verdi, tsc pulito. Verificato live: DE CRISTOFARO -> dati.senato.it/22918. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- listAknDir: sort esplicito dei nomi file (l'ordine di tree.items non e' un contratto garantito dell'endpoint non documentato); senza sort la paginazione offset/limit rischiava duplicati/salti tra esecuzioni - mapLimit: limit<=0 normalizzato ad almeno 1 worker invece di tornare un array di holes in silenzio - test: accettano source lod|akn invece di assumere quale sorgente risponde (freschezza LOD intermittente); withProponents verifica "almeno una riga popolata" invece di rows[0] (esistono file AKN stub vuoti nella fonte) - +1 test mapLimit con limit 0 e negativo 116/116 test verdi, tsc pulito. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ioso enrichProponents intercettava ogni errore di fetch/parsing lasciando i campi proponenti vuoti, indistinguibili dai file AKN stub della fonte (nessun docProponent, ma HTTP 200). Se GitHub e' irraggiungibile (es. dal Worker, verifica ancora pendente) l'utente otteneva righe valide con proponenti vuoti senza segnale d'errore. Fix: la tolleranza per-file resta (un 404 isolato non affossa la finestra), ma se TUTTI i fetch della finestra falliscono viene lanciato un errore esplicito. enrichProponents esportata per test unitario mirato (404 reali su file inesistenti, deterministico). 117/117 test verdi, tsc pulito. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- hint fallback AKN: indica ora il nome parametro (legislature) e il flag CLI equivalente (--legislature), non solo "ripetere passando legislature" - skill CLI e MCP: menzionano la colonna date, popolata dai metadati AKN quando si usa withProponents/--with-proponents 117/117 test verdi, tsc pulito. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erente - type cambiava semantica in base a source: E/G/Q (osr:tipo) sul ramo LOD, "commissione"/"assemblea" sul ramo AKN fallback. Aggiunta colonna sede dedicata (popolata su entrambi i rami: LOD via osr:flagCommissione, AKN via emend/emendc); type resta E/G/Q e vuoto sulle righe source=akn (non deducibile in modo affidabile dal solo AKN) - aknAttoPath: messaggio d'errore diceva "atteso http://dati.senato.it/ ddl/<n>" ma la regex accetta qualsiasi URI con /ddl/<n> (http/https/ altro host); reso coerente 117/117 test verdi, tsc pulito. Verificato live: source=lod -> type=G, sede=assemblea. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…a/Commissione Il controllo unico "offset+limit > entries.length" non copriva il caso in cui SOLO il bucket Assemblea e' troncato: un offset oltre aula.names.length veniva letto come "Commissione" nell'array concatenato, ma potrebbe in realta' essere un elemento di Assemblea non visibile (posizione reale non determinabile nel bucket troncato). Bug di correttezza silenzioso, non solo di raggiungibilita'. Estratta checkAknTruncation (pura, esportata per test offline): guarda le due troncature separatamente, fallisce esplicito se la finestra richiesta rischia di attraversare il confine Assemblea/Commissione mentre Assemblea e' troncata. +4 test unitari (offset dentro/oltre il visibile, singola vs doppia troncatura, nessuna troncatura). 121/121 test verdi, tsc pulito. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/tools/amendments.ts:169
withProponentsesegue un fetch per emendamento, ma al momentolimitpuò arrivare a 1000: basta un uso “distratto” (es.--with-proponentssenza abbassare--limit) per innescare centinaia/migliaia di richieste HTTP, con alta probabilità di timeout/rate limit (specie nel Worker). Suggerirei di imporre un cap (o un errore esplicito) quandowithProponentsè true elimitsupera una soglia ragionevole (es. 100), lasciando invariato il caso senza proponenti.
async execute(input) {
// amendments interroga solo l'endpoint Senato: un ddlUri della Camera
// passerebbe il FILTER senza match, restituendo un CSV vuoto che si può
// scambiare per "nessun emendamento". In realtà gli emendamenti della
// Camera NON esistono come entità nel LOD OCD (nessuna classe emendamento):
Raccolto da un suggerimento a bassa confidenza soppresso dall'ultima review Copilot (mai pubblicato come commento, quindi nessun thread da risolvere, ma tecnicamente fondato): withProponents fa un fetch HTTP per riga, con limit fino a 1000 (max schema) sono centinaia/migliaia di richieste, rischio concreto di timeout/rate-limit specie dal Worker. Fix: errore esplicito se withProponents=true e limit>100, invece di un timeout silenzioso a metà esecuzione. Coerente con lo stile del progetto (errori espliciti, mai cap silenziosi). +1 test, 122/122 verdi, tsc pulito. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…genuino L'hint sul ramo fallback AKN diceva sempre "nessun emendamento né nel LOD né nel bulk" quando aknRows era vuoto - ma questo succede anche quando l'atto HA emendamenti e l'offset richiesto pagina oltre la fine (entries.length > 0, page.length === 0): un falso "assente" per un mero problema di paginazione. Estratta aknEmptyHint (pura, esportata per test offline): distingue vuoto genuino (entriesLength 0) da pagina oltre la fine (entriesLength > 0), con hint che indica il totale disponibile e l'offset valido. +1 test, 123/123 verdi, tsc pulito. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cosa fa
Implementa la priorità P1 dell'analisi fonti non-LOD (#45): il tool
amendmentsusa il bulk AKN GitHub del Senato (SenatoDellaRepubblica/AkomaNtosoBulkData, CC BY 4.0, senza WAF → funziona in CLI e Worker).akn_xml_urlsu ogni riga LOD — conversioneosr:URLTestoXml→ URL raw (pura sostituzione di stringa,osr:flagCommissionedecideemend/vsemendc/): testo machine-readable scaricabile con un curl.ddlUrie LOD vuoto, listing diemend/+emendc/via endpoint JSON web-UI GitHub, righesource=akn. Rete di sicurezza contro la freschezza intermittente del LOD.withProponents/--with-proponents— primo firmatario e cofirmatari (con URI persona) dal testo AKN: il proponente NON è nel LOD (amendments (Senato): aggiungere il proponente via parsing AKN (simmetria con camera-amendments) #30). Fetch puntuali, concorrenza 4, mai bulk.Valore giornalistico
Chi firma gli emendamenti di un provvedimento — finora dietro WAF, recuperabile solo a mano col browser — esce ora da un comando: verificato il caso wiki (em. 1.30 ddl/56260 → Bartolomeo Amidei + 5) e il Piano Casa (proponenti da entrambe le sedi).
Scoperta in corsa
Il dataset
osr:Emendamentodel LOD si è riallineato tra il 7 e il 10 luglio (Piano Casa 0→799, match esatto col bulk 400+399): il claim "fermo ad ago 2024" è superato e rimosso da description/emptyHint. Documentata nel wiki anche la trappola nuova:dataPresentazionedei DDL recenti ora tipizzataxsd:string(la query cutoff tipizzata sottoconta).Note tecniche
src/core/akn.tsWorker-compatible (solofetchnativo); listing troncato a 1000 gestito viatotalCountcon errore esplicito su finestra irraggiungibile (no cap silenziosi); forma payload validata con errore esplicito se GitHub cambia l'endpoint (non documentato).an:span; preferitoTLCPerson@showAscol nome completo); file stub vuoti della fonte → campi vuoti, non errore.Test
src/core/akn.test.ts, offline) e +3 integrazione; suite 114/114 verdi,tscpulito.Closes #38, closes #30. Rif. #45.
🤖 Generated with Claude Code