Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions .claude/agents/news-driven-cli-gap-analyzer.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,27 @@ You are a Parliamentary Data Coverage Analyst specialized in bridging real journ
- Simplicity above all: minimal, targeted CLI invocations that map directly to each news item.
- Fix root causes, never symptoms: when a gap emerges, describe the underlying capability missing, not a workaround.
- Be concise and high-signal. Brevity over grammar.
- 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.
- 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.

## Phase 0 — Previously Tested Story Catalog
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.
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.
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.
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.
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.

## Phase 1 — News Discovery (Exa MCP)
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.
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**:
- **the 2 best current news** (this week/month);
- **the 2 best news items from 2025** (e.g. DDL, votes, or question time from that year);
- **the 2 best news items from 2020** (e.g. COVID-era decrees, votes, or acts).
"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.
"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.
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.
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.
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.
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.
4. Discard purely political-opinion pieces with no verifiable data hook.
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.

## Phase 2 — CLI Capability Mapping & Testing
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.
Expand Down Expand Up @@ -54,17 +63,33 @@ Write the result to `./docs/news-agent/YYYY-MM-DD_HH-MM.md` (create the `docs/ne
Structure the file exactly as:

- Title (do NOT start the title with a number)
- `## 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
- `## 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.
- `## 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
- `## 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.
- `## 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).
- `## Comandi eseguiti` — the exact CLI invocations run, for reproducibility

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.

## Phase 4 — Catalog Update
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`.
2. Add one bullet per selected story, in this exact canonical form, one line each:

```
- **nuova|ritest** — YYYY-MM-DD — leg. NN — Camera|Senato|Camera+Senato — concrete stage and event — ref: act number and/or stable URI — URL
```

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.
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.
4. Keep the catalog append-only, retests included, so a later run can see when a story was last exercised.
5. Before appending, verify that a section with the same report filename does not already exist. If it does, do not duplicate it.

## Quality Control
- Ground every strength/weakness in an actual command you ran and its observed output. No speculation presented as fact.
- If Exa returns weak results, refine queries (synonyms, specific DDL numbers, chamber-specific terms) before proceeding.
- Before testing, verify that every story marked `nuova` is absent from the catalog **at story level**, not merely absent as an exact URL.
- 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.
- 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.
- 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.
- After writing the file, confirm its path back to the user.

8 changes: 8 additions & 0 deletions LOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# LOG

## 2026-07-26

- **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.

- **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.

- **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.

## 2026-07-25

- **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.
Expand Down
76 changes: 76 additions & 0 deletions docs/superpowers/specs/2026-07-15-news-catalog-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Catalogo delle notizie già testate

## Obiettivo

Evitare che il news-driven CLI gap analyzer selezioni ripetutamente la stessa vicenda parlamentare solo perché Exa propone URL o fonti differenti.

## Disegno

- Conservare un catalogo append-only in `docs/news-agent/catalog.md`.
- 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.
- Considerare duplicati due articoli che riguardano lo stesso atto o tema, la stessa fase parlamentare e la stessa data o seduta sostanziale.
- Considerare nuova una fase differente dello stesso atto.
- Preferire sempre vicende non ancora testate. Prima di riusarne una, effettuare almeno due raffinamenti di ricerca nel relativo bucket.
- Consentire il riuso quando non esistono alternative sufficienti o quando è necessario un test di regressione mirato; motivarlo nel report.
- Dopo ogni run, aggiungere al catalogo le sei notizie selezionate.

## Formato

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.

Ogni vicenda occupa una riga sola:

```
- **nuova|ritest** — YYYY-MM-DD — leg. NN — Camera|Senato|Camera+Senato — fase concreta ed evento — ref: numero atto e/o URI stabile — URL
```

La data è quella dell'evento parlamentare, non quella della run.

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: —`.

Lo status `backfill` marca le sezioni ricostruite a posteriori, dove lo status originale `nuova`/`ritest` non è più ricostruibile.

## Confine con la regola di analisi vergine

I riferimenti stabili sono identità e vanno registrati: servono proprio a riconoscere la stessa vicenda sotto titoli diversi.

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.

## Crescita

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.

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.

## Flusso

1. Leggere il catalogo, senza leggere i report precedenti.
2. Cercare e classificare più candidati per ciascun bucket temporale.
3. Confrontare semanticamente i candidati con il catalogo.
4. Selezionare due vicende nuove per bucket quando possibile.
5. Eseguire i test e scrivere il report.
6. Appendere al catalogo una sezione riferita al nuovo report.

Il passo 6 è parte della run, non un'appendice facoltativa: un report senza la sua sezione fa ripetere le stesse vicende alla run successiva.

## Implementazioni

Il flusso vive in due copie che vanno tenute allineate:

- `.agents/skills/news-driven-cli-gap-analyzer/SKILL.md` (skill Pi);
- `.claude/agents/news-driven-cli-gap-analyzer.md` (agent Claude Code).

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.

## Verifica

- Ogni file di report in `docs/news-agent/` ha una sezione omonima nel catalogo:
`for f in docs/news-agent/2*.md; do grep -q "^## $(basename $f)$" docs/news-agent/catalog.md || echo "MANCA: $f"; done`
- Le due implementazioni contengono entrambe la fase di lettura e quella di aggiornamento del catalogo.
- La skill distingue un URL nuovo da una vicenda nuova.
- La regola di analisi vergine continua a vietare la lettura delle conclusioni pregresse e il catalogo non contiene annotazioni di copertura.
- Un riuso è esplicitamente riconoscibile nel report, con la motivazione.

## Aggiornamenti

- 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).
Loading
Loading