You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(vote-detail): risolvi --group-acronym contro le sigle reali del voto (#80)
* docs(news-agent): spec catalogo + allineamento agent Claude Code
Il catalogo esisteva solo nella skill Pi: l'agent Claude Code non lo
leggeva né lo aggiornava. Sei run consecutive (17-25 lug) senza sezione
nel catalogo e con le stesse vicende riproposte ogni volta.
Porta nell'agent la Fase 0 (lettura + regola di equivalenza) e la Fase 4
(append), con la deroga esplicita alla regola di analisi vergine.
Nella spec: naming sezione e formato riga canonico, divieto di
annotazioni di copertura, regola di compattazione, verifica eseguibile.
Il catalogo è in .gitignore: backfill delle sei sezioni fatto in locale.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(vote-detail): risolvi --group-acronym contro le sigle reali del voto (#77)
Le sigle di ocd:siglaGruppo non coincidono con l'acronym di `groups list`
(AZ-PER-RE → APERRE, IV-CR → IVICRE, Misto disaggregato): il FILTER su una
sigla inesistente restituiva zero righe senza dire perché.
La sigla richiesta viene ora risolta contro quelle effettivamente presenti
nella votazione (query leggera), con confronto tollerante a maiuscole e
punteggiatura. Se non esiste: risultato vuoto + hint con le sigle reali e la
più simile. Nessuna mappatura hardcoded: il disallineamento è della fonte e
va risolto lì, il codice si limita a renderlo visibile.
Closes#77
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* refactor(vote-detail): togli gli esempi di sigla dai testi utente + LOG
I messaggi citavano AZ-PER-RE → APERRE e la forma "M-*" delle componenti
Misto: sono fatti di oggi sulla fonte, che diventerebbero testo sbagliato e
branch morta se la Camera allinea le sigle. L'hint mantiene il valore
diagnostico senza codificarli, perché nomina già il candidato reale e elenca
le sigle restituite dalla query; la nota sul Misto ora dipende dalla stringa
richiesta, non dalla forma dei dati.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(vote-detail): escape del letterale SPARQL + test sul path execute
Da review PR #80:
- la sigla risolta finiva interpolata cruda nel FILTER: ora passa per
sparqlStringLiteral, estratto in src/core (era duplicato in bill-progress)
con i suoi test. Il valore viene dal grafo, non dall'utente, ma una
virgoletta nel dato romperebbe comunque la query.
- l'hint sul caso "nessuna sigla registrata" citava il flag --group-acronym,
che per un client MCP non significa nulla: formulazione neutra.
- due test di integrazione su voteDetailTool.execute: match risolto (sigla
minuscola → righe, nessun hint) e sigla di groups list → vuoto con hint.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: .claude/agents/news-driven-cli-gap-analyzer.md
+29-4Lines changed: 29 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,18 +12,27 @@ You are a Parliamentary Data Coverage Analyst specialized in bridging real journ
12
12
- Simplicity above all: minimal, targeted CLI invocations that map directly to each news item.
13
13
- Fix root causes, never symptoms: when a gap emerges, describe the underlying capability missing, not a workaround.
14
14
- Be concise and high-signal. Brevity over grammar.
15
-
- Every run is a fresh, virgin analysis: do NOT read, reference, or compare against previous notes in `docs/news-agent/` or any other prior report. Do not carry over conclusions from past runs — test everything from scratch on the current CLI state.
15
+
- Every run is a fresh, virgin analysis **with respect to CLI findings**: do NOT read, reference, or compare against previous notes in `docs/news-agent/` or any other prior report. The **sole** historical memory allowed is `docs/news-agent/catalog.md`, and only to avoid re-selecting parliamentary stories already tested. Never carry over strengths, weaknesses, commands, or conclusions from past runs — test the selected stories from scratch on the current CLI state.
16
+
17
+
## Phase 0 — Previously Tested Story Catalog
18
+
1. Read `docs/news-agent/catalog.md` before finalizing the news selection. Read the entire file, continuing with an offset if the tool truncates it. Do NOT open the reports the catalog is named after.
19
+
2. Deduplicate by **parliamentary story**, not URL. Two articles are the same story when they concern the same act or parliamentary topic, the same concrete stage or event (for example confidence vote, final vote, question time, committee hearing), and the same substantive date or sitting. A different publisher, headline, or URL does not make the story new.
20
+
3. Treat a genuinely different stage of the same bill as a new story: presentation, committee approval, confidence vote, and final approval can be distinct stories when they happened as distinct parliamentary events.
21
+
4. Use the catalog **only as an exclusion list** during discovery. It is not evidence about current CLI coverage and must not influence the outcome of the tests.
22
+
5. If the catalog is missing, create it with a short explanation and continue; do not reconstruct it by reading prior reports during a normal analysis run.
16
23
17
24
## Phase 1 — News Discovery (Exa MCP)
18
25
1. Use the Exa MCP tools to search for high-interest news about activities of Camera and Senato. Prefer queries in Italian (e.g. "Camera dei Deputati votazione", "Senato disegno di legge", "question time parlamento", "emendamenti aula", specific hot DDL names). Bias toward stories that plausibly touch structured parliamentary data: votes, bills/DDL, speeches, question time, committee work, sponsors/firmatari, parliamentarian profiles.
19
26
2.**Cover a temporal spread, not just the present.** Search broadly, then rank candidates by journalistic interest and data-hook strength within each time bucket. The final set MUST contain **exactly 6 items — the 2 best from each bucket**:
20
27
-**the 2 best current news** (this week/month);
21
28
-**the 2 best news items from 2025** (e.g. DDL, votes, or question time from that year);
22
29
-**the 2 best news items from 2020** (e.g. COVID-era decrees, votes, or acts).
23
-
"Best" = highest journalistic interest AND strongest structured-data hook (a concrete vote, DDL, speech, firmatario, or profile a journalist would want to verify). Search more candidates than needed in each bucket, then pick the top 2.
30
+
"Best" = highest journalistic interest AND strongest structured-data hook (a concrete vote, DDL, speech, firmatario, or profile a journalist would want to verify). Search more candidates than needed in each bucket, **compare them semantically with the catalog, discard the already-tested stories**, then pick the top 2 unseen stories.
31
+
If a bucket has fewer than 2 viable unseen stories, perform at least **two additional, distinct Exa query refinements** for that bucket (different topic, chamber, event type, or normative vocabulary). Only after those refinements may you reuse a catalogued story. Prefer a story tested least recently or one that directly exercises a CLI capability changed since its last test, and record the retest reason explicitly. This is a soft fallback, not permission to default to familiar stories.
24
32
The historical items are deliberate: 2020 falls in **legislature 18** and 2025 in **legislature 19**, so they stress-test whether the CLI reaches back across legislatures (older parliamentarians, past DDL numbering, historical votes/speeches) instead of only serving the current moment. For dated searches use Exa date filters and pin the exact date in the note. When testing these items, remember to pass the correct `--legislature` (18 for 2020, 19 for 2025/current) and check whether tools that default to the current legislature still surface the historical data.
25
-
3. For each of the 6 selected items, capture: a one-line summary, the source URL **with the news date (YYYY-MM-DD)**, and the underlying parliamentary data question(s) a journalist would ask to verify/deepen it.
33
+
3. For each of the 6 selected items, capture: a one-line summary, the source URL **with the news date (YYYY-MM-DD)**, the catalog status (`nuova` or `ritest`), and the underlying parliamentary data question(s) a journalist would ask to verify/deepen it.
26
34
4. Discard purely political-opinion pieces with no verifiable data hook.
35
+
5.**Always skip Piano Casa / Decreto Casa items.** Do not select news about the 2026 Piano Casa / DL Casa / decreto-legge 7 maggio 2026, n. 66, even if Exa ranks them highly: the Senato source label contains a known wrong DDL number (`1994` instead of `1944`), so it is not a good signal for general CLI coverage. If such items appear among the strongest current candidates, explicitly replace them with the next-best Exa result that has a concrete structured-data hook.
27
36
28
37
## Phase 2 — CLI Capability Mapping & Testing
29
38
1.**Load the CLI skill first.** Before invoking the CLI, load the `italian-parliament-cli` skill (via the Skill tool) and read it: it documents commands, patterns, and known traps (keyword search must use the formal/normative term, chamber asymmetries, empty-label pitfalls). Use it to shape correct invocations and to avoid reporting false "missing data" gaps caused by wrong search terms.
@@ -54,17 +63,33 @@ Write the result to `./docs/news-agent/YYYY-MM-DD_HH-MM.md` (create the `docs/ne
54
63
Structure the file exactly as:
55
64
56
65
- Title (do NOT start the title with a number)
57
-
-`## Notizie analizzate` — bullet list: summary + **date (YYYY-MM-DD) and legislature** + URL + journalist data-question, per item; keep the current / 2025 / 2020 items clearly distinguishable
66
+
-`## Notizie analizzate` — bullet list: summary + **date (YYYY-MM-DD) and legislature** + URL + journalist data-question + catalog status (`nuova` or `ritest`), per item; keep the current / 2025 / 2020 items clearly distinguishable. For every `ritest`, include the reason it was unavoidable or specifically useful.
58
67
-`## Punti di forza` — where the CLI covered the news well, with the specific command(s) that worked; note explicitly whether **historical coverage (2025 leg.19, 2020 leg.18)** held up
59
68
-`## Punti di debolezza` — coverage gaps, bugs, missing filters, chamber asymmetries, **and any degradation on the historical items** (e.g. tools that only work for the current legislature, missing older data), with evidence. **Escludi le assenze source-side già note (sezione "Limiti noti della fonte", buckets A/B/C): non elencarle qui.** Se una notizia dipende davvero da una di esse, liquidala in una riga ("limite noto della fonte, vedi wiki — non un gap CLI") e passa oltre.
60
69
-`## Suggerimenti implementativi` — concrete, root-cause implementation proposals (new tool, new filter, fixed field), prioritized, mapped to the news items they unlock. Non proporre di "coprire" ciò che rientra nei buckets A/B/C (per il bucket B indica il tool già esistente).
61
70
-`## Comandi eseguiti` — the exact CLI invocations run, for reproducibility
62
71
63
72
Formatting rules: every triple-backtick code block must be preceded by a blank line. Do not reference Claude or any assistant in the document. Keep bullets short and high-signal.
64
73
74
+
## Phase 4 — Catalog Update
75
+
1. After the report has been written successfully, append **one** section to `docs/news-agent/catalog.md` named exactly like the report file, for example `## 2026-07-26_09-30.md`.
76
+
2. Add one bullet per selected story, in this exact canonical form, one line each:
77
+
78
+
```
79
+
- **nuova|ritest** — YYYY-MM-DD — leg. NN — Camera|Senato|Camera+Senato — concrete stage and event — ref: act number and/or stable URI — URL
80
+
```
81
+
82
+
Use the news/event date, not the run date. `ref` holds only **identity** data (act number such as `C.2822` / `S.1951` / `DL 18/2020`, bill URI, vote URI, AIC code) discovered during testing; write `ref: —` when none is available.
83
+
3.**Never write coverage annotations in the catalog.** Phrases like "vote missing from LOD", "tool X returned nothing", or any strength/weakness belong to the report only. The catalog carries story identity, nothing else — otherwise the next run inherits conclusions the virgin-analysis rule forbids.
84
+
4. Keep the catalog append-only, retests included, so a later run can see when a story was last exercised.
85
+
5. Before appending, verify that a section with the same report filename does not already exist. If it does, do not duplicate it.
86
+
65
87
## Quality Control
66
88
- Ground every strength/weakness in an actual command you ran and its observed output. No speculation presented as fact.
67
89
- If Exa returns weak results, refine queries (synonyms, specific DDL numbers, chamber-specific terms) before proceeding.
90
+
- Before testing, verify that every story marked `nuova` is absent from the catalog **at story level**, not merely absent as an exact URL.
91
+
- If a story is marked `ritest`, verify that the report states which two search refinements failed to produce a stronger unseen alternative, or which changed CLI capability justifies the regression test.
92
+
- The run is not complete until Phase 4 has appended the section to the catalog: a report without its catalog section makes the next run repeat the same stories.
68
93
- If the CLI cannot be located or built, report that clearly at the top of the note and still deliver the news-driven data-question mapping.
69
94
- After writing the file, confirm its path back to the user.
Copy file name to clipboardExpand all lines: LOG.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,13 @@
1
1
# LOG
2
2
3
+
## 2026-07-26
4
+
5
+
- **fix `vote-detail` — `--group-acronym` non restituisce più zero righe in silenzio** (#77, PR #80) — la sigla passata dall'utente finiva dritta in un `FILTER(STR(?_sg) = "…")`: se non esisteva nel dataset votazioni il risultato era vuoto, con exit 0 e nessun avviso, indistinguibile da "il gruppo non ha votato". E le sigle divergono per davvero: `groups list` espone `AZ-PER-RE` e `IV-CR`, i voti della stessa legislatura portano `APERRE` e `IVICRE`, e il Misto lato voto è disaggregato in `M-ALT`/`M-MIN`/`M-+EUR`. Seguendo il flusso documentato (cerca la sigla in `groups`, poi filtra) si concludeva il falso. Nemmeno `group_uri` era una chiave utilizzabile: per Azione è `gr4135` nella risorsa gruppo e `gr4212` sui voti, e le componenti del Misto ce l'hanno vuoto. Ora, quando `--group-acronym` è valorizzato, una query leggera recupera le sigle **realmente presenti in quella votazione** e la richiesta viene risolta contro quelle (esatta → case-insensitive → senza punteggiatura); se risolve, la query principale è invariata, quindi performance e semantica del `LIMIT` non cambiano. Se non risolve: righe vuote più una nota (stderr in CLI, testo nell'MCP) con l'elenco delle sigle presenti, la più simile in testa (Dice sui bigrammi, soglia 0,4) e la spiegazione per il Misto. Nessun alias `AZ-PER-RE → APERRE` nel codice: il disallineamento è della fonte e si romperebbe al primo cambio di denominazione — il codice interroga il dato e rende visibile il problema, non lo compensa. +10 test sulle due funzioni pure, 199/199 verdi. Emerso dal report news-agent `2026-07-26_08-58.md`. **Residuo noto**: le sigle sono raccolte senza applicare `--vote-type`, quindi una sigla valida ma senza voti di quel tipo resta un vuoto senza nota — comportamento corretto (il gruppo ha votato, non in quel modo), fuori dallo scopo di #77.
6
+
7
+
- **segnalata a monte la radice del problema** — punto 9 della nota `docs/note-gestori-lod/camera-assistenza-dati.md`: sigla della risorsa gruppo diversa da quella dei voti (`gr4211`: `IV-CR` nella label, `IVICRE` in `ocd:siglaGruppo`), URI referenziati dalle votazioni ma mai descritti (`gr4212` con 160.881 voti e `gr4234`: zero triple come soggetto), denominazione storica sovrascritta (`gr4135` ha oggi la label `AZ-PER-RE` ma i suoi 88.475 voti portano `AIV-RE`), componenti del Misto senza URI, e nessuna proprietà "sigla" sulla risorsa gruppo — l'acronimo è estraibile solo dalla label, che per giunta arriva troncata (punto 4 della stessa nota). Il fenomeno è generale e vale per entrambe le camere, quindi è anche scheda **B5** del dossier di campagna (`docs/campagna-parlamento-aperto/02-dossier-tecnico.md`) con riga in tabella di sintesi: al Senato il legame voto→gruppo non esiste proprio (la votazione punta ai senatori con `osr:favorevole`/`osr:contrario`/`osr:astenuto`, nessuna proprietà di gruppo) e va ricostruito dalle adesioni valide alla data.
8
+
9
+
- **gap analysis news-driven** (`docs/news-agent/2026-07-26_08-58.md`) — 6 notizie mai testate prima (Giunta autorizzazioni/chat Delmastro, riforma forense al Senato, mozioni di sfiducia Santanchè e Nordio, DL 130/2020 immigrazione e DL 137/2020 Ristori). Copertura piena su 5 storie su 6, storico leg. 18 lato Camera senza degrado. Tre issue aperte con triage: #77 (sopra), #78 (`which` non trova "giunta per le autorizzazioni" e instrada "immunità parlamentare" verso `search find`, un falso positivo peggiore di un no-match), #79 (`confidence_vote=true` marca anche le mozioni di sfiducia individuale ex art. 115: è `ocd:richiestaFiducia` della fonte, non un valore derivato, quindi `documentation` + `gap-dataset`). Un quarto rilievo del report — quoting CSV rotto in `groups list` — **non è stato aperto**: verificato con un parser CSV vero su leg. 17, 18 e 19, tutte le righe hanno 6 colonne e il campo con le virgole è quotato correttamente. Era un artefatto del `cut -d,` usato per leggere l'output, non un difetto.
10
+
3
11
## 2026-07-25
4
12
5
13
-**v0.26.2** — release patch. Due fix e la misura del limite di dimensione delle richieste al Senato (2047 byte accettati, 2048 rifiutati), che spiega e chiude una classe di 403 finora attribuita al blocco anti-burst. PR #75 e #76, mergiate via squash. 43 tool invariati, 189/189 test verdi.
Evitare che il news-driven CLI gap analyzer selezioni ripetutamente la stessa vicenda parlamentare solo perché Exa propone URL o fonti differenti.
6
+
7
+
## Disegno
8
+
9
+
- Conservare un catalogo append-only in `docs/news-agent/catalog.md`.
10
+
- Il catalogo contiene solo l'identità delle notizie testate e il report di provenienza; non contiene conclusioni sui punti di forza o debolezza della CLI.
11
+
- Considerare duplicati due articoli che riguardano lo stesso atto o tema, la stessa fase parlamentare e la stessa data o seduta sostanziale.
12
+
- Considerare nuova una fase differente dello stesso atto.
13
+
- Preferire sempre vicende non ancora testate. Prima di riusarne una, effettuare almeno due raffinamenti di ricerca nel relativo bucket.
14
+
- Consentire il riuso quando non esistono alternative sufficienti o quando è necessario un test di regressione mirato; motivarlo nel report.
15
+
- Dopo ogni run, aggiungere al catalogo le sei notizie selezionate.
16
+
17
+
## Formato
18
+
19
+
Ogni sezione si chiama esattamente come il file del report che l'ha prodotta, estensione compresa: `## 2026-07-26_09-30.md`. Nessun'altra forma è ammessa: una sezione con un nome diverso rende impossibile verificare che ogni report abbia lasciato traccia.
20
+
21
+
Ogni vicenda occupa una riga sola:
22
+
23
+
```
24
+
- **nuova|ritest** — YYYY-MM-DD — leg. NN — Camera|Senato|Camera+Senato — fase concreta ed evento — ref: numero atto e/o URI stabile — URL
25
+
```
26
+
27
+
La data è quella dell'evento parlamentare, non quella della run.
28
+
29
+
Il campo `ref` accoglie solo dati di identità: numero d'atto (`C.2822`, `S.1951`, `DL 18/2020`), URI del ddl, URI della votazione, codice AIC. Quando non se ne è trovato nessuno si scrive `ref: —`.
30
+
31
+
Lo status `backfill` marca le sezioni ricostruite a posteriori, dove lo status originale `nuova`/`ritest` non è più ricostruibile.
32
+
33
+
## Confine con la regola di analisi vergine
34
+
35
+
I riferimenti stabili sono identità e vanno registrati: servono proprio a riconoscere la stessa vicenda sotto titoli diversi.
36
+
37
+
Le annotazioni di copertura no. Frasi come "voto assente dal LOD Camera" o "il tool non ha restituito nulla" sono esiti di test: appartengono al report e nel catalogo diventerebbero esattamente la contaminazione che la regola di analisi vergine vieta. Il divieto è esplicito nella fase di aggiornamento del catalogo, non implicito.
38
+
39
+
## Crescita
40
+
41
+
Il catalogo viene letto per intero a ogni run, quindi il suo costo cresce linearmente con il numero di run. Sei vicende al giorno diventano oltre duemila righe in un anno.
42
+
43
+
Regola: superate le 400 righe, le sezioni più vecchie di 90 giorni confluiscono in un'unica sezione `## Archivio fino a YYYY-MM-DD`, con una riga per vicenda **distinta** — le ripetizioni della stessa vicenda su più run collassano in una riga sola, che conserva la data dell'ultimo test. Si perde l'associazione vicenda→report, che serve solo a scegliere quale ritestare per prima; si conserva l'identità, che è ciò su cui si fa dedup.
44
+
45
+
## Flusso
46
+
47
+
1. Leggere il catalogo, senza leggere i report precedenti.
48
+
2. Cercare e classificare più candidati per ciascun bucket temporale.
49
+
3. Confrontare semanticamente i candidati con il catalogo.
50
+
4. Selezionare due vicende nuove per bucket quando possibile.
51
+
5. Eseguire i test e scrivere il report.
52
+
6. Appendere al catalogo una sezione riferita al nuovo report.
53
+
54
+
Il passo 6 è parte della run, non un'appendice facoltativa: un report senza la sua sezione fa ripetere le stesse vicende alla run successiva.
55
+
56
+
## Implementazioni
57
+
58
+
Il flusso vive in due copie che vanno tenute allineate:
-`.claude/agents/news-driven-cli-gap-analyzer.md` (agent Claude Code).
62
+
63
+
Una modifica applicata a una sola delle due produce run che ignorano il catalogo pur avendo il catalogo sul disco: è successo tra il 17 e il 25 luglio 2026, con sei run consecutive senza sezione e le stesse vicende riproposte ogni volta.
64
+
65
+
## Verifica
66
+
67
+
- Ogni file di report in `docs/news-agent/` ha una sezione omonima nel catalogo:
68
+
`for f in docs/news-agent/2*.md; do grep -q "^## $(basename $f)$" docs/news-agent/catalog.md || echo "MANCA: $f"; done`
69
+
- Le due implementazioni contengono entrambe la fase di lettura e quella di aggiornamento del catalogo.
70
+
- La skill distingue un URL nuovo da una vicenda nuova.
71
+
- La regola di analisi vergine continua a vietare la lettura delle conclusioni pregresse e il catalogo non contiene annotazioni di copertura.
72
+
- Un riuso è esplicitamente riconoscibile nel report, con la motivazione.
73
+
74
+
## Aggiornamenti
75
+
76
+
- 2026-07-26: normalizzati naming delle sezioni e formato riga; esplicitato il divieto di annotazioni di copertura; aggiunta la regola di crescita; allineato l'agent Claude Code alla skill Pi; ricostruite le sei sezioni mancanti (17, 19, 20, 21, 23, 25 luglio).
0 commit comments