diff --git a/docs/article-cards.md b/docs/article-cards.md index c3695bb..d3e03a0 100644 --- a/docs/article-cards.md +++ b/docs/article-cards.md @@ -179,6 +179,26 @@ After safely reconciling complete sites, the publisher marks partial discovery with exit status 2 and a job summary. A repeated partial run remains a byte-stable no-op. This keeps failures visible without indefinitely blocking unrelated sites. +Disclosure holds now report the evidence condition instead of calling every +recent non-blocked article `ambiguous-disclosure`: + +| Reason | Meaning (all remain visible) | +| --- | --- | +| `no-supported-disclosure` | No standalone or terminal-BR approved label in a supported candidate element; this does not certify editorial status or absence of payment | +| `document-active-content` | The whole-fragment active-element/event-handler veto fired, whether or not a disclosure is also present | +| `unsupported-disclosure-context` | A candidate label matched but its subtree or ancestor context failed the existing plain, attribute-free contract | +| `unsafe-disclosure-tail` | A candidate label passed its own context checks but following content was too long or structurally unsupported | + +The bounded parser, early active-content veto, worker failures/work limits, +timestamp cutoff, conflicts, and publication gates are unchanged. Diagnostics +identify one encountered blocker, not every possible blocker. A later independently +valid label still qualifies under the same rules. Missing/unsupported bodies and +sites report `unreadable-content`/`unsupported-disclosure-site`; parse exceptions +continue to report `unreadable-content`. Reports still contain only path and reason, +not copied bodies or a permanent editorial allowlist. See the +[October 8 queue review](reviews/2026-10-08-disclosures.md) for all 77 candidates +and the separate recommendations based on publisher disclosures. + The maximum 17 requests, each with two 15-second attempts and a one-second retry delay, require at most 527 seconds of request time. Discovery also has a global 540-second abort deadline, including response-body reads; its child process has diff --git a/docs/reviews/2026-10-08-disclosures.md b/docs/reviews/2026-10-08-disclosures.md new file mode 100644 index 0000000..3cd02fe --- /dev/null +++ b/docs/reviews/2026-10-08-disclosures.md @@ -0,0 +1,166 @@ +# October 8 disclosure queue review + +Reviewed 2026-10-09 against main `733861661a609ad5453207c899ae6e48e11db3cb`. +Queue source: [workflow 37775388864](https://github.com/JunjoSick/filtershosting/actions/runs/37775388864), publish job `113304860921`. +The log contains exactly 5 GDC, 29 QuiAntella and 43 Colli `ambiguous-disclosure` paths. Firenze's separate 120 review-only paths are outside this review. + +## Findings and recommended decisions + +| Publication | Confirmed advertisements | Ordinary editorial | Unresolved | Total | +| --- | ---: | ---: | ---: | ---: | +| Gazzettino del Chianti | 5 | 0 | 0 | 5 | +| QuiAntella | 0 | 27 | 2 | 29 | +| Dai Colli Fiorentini | 0 | 42 | 1 | 43 | +| Total | 5 | 69 | 3 | 77 | + +All 77 exact paths are absent from their current baseline, additive state and public registry. Baselines remain GDC 1,822, QuiAntella 9, Colli 32 and Firenze 5; state additions are empty. + +The five GDC articles have sufficiently strong evidence for a **separate reviewed exact-path blocking addition**: each publisher explicitly labels its own article `(CONTENUTO SPONSORIZZATO)`, and the RSS publication dates are after the fixed cutoff. Their recommendations and evidence are below. This diagnostic PR does not add them to state, regenerate filters, approve a new disclosure vocabulary, or publish classifications. + +Keep the 69 ordinary editorial articles visible. Here “ordinary editorial” describes the retrieved news/service/community content and lack of payment evidence; it does not establish that no undisclosed payment occurred. It is not a permanent keep override. + +Keep three unresolved paths visible: the Dr. Max pharmacy and Coop reopening features on QuiAntella have detailed commercial messaging but no disclosed paid relationship; the Colli cinema article was unavailable (HTTP 404 and empty exact-slug API result). Commercial tone, booking information, event sponsorship, institutional partnerships and sports `Promozione` terminology cannot establish that an article itself is paid. + +## Reproduced classifier limitations + +The old `ambiguous-disclosure` reason was a fallback for every recent candidate not blocked, including an ordinary article with no disclosure. Counting those rows as suspected advertising overstates the queue's signal. + +After initial network timeouts, bounded direct requests recovered current GDC RSS and both WP API responses. All 76 retrievable article-local fragments were run through both the unchanged main classifier and this PR's classifier: **76 identical review decisions**. This is replay of current October 9 fragments, not a claim that the lost October 8 bodies were byte-identical. + +| Site | No supported disclosure | Document-active content | Unsupported disclosure context | Unavailable | +| --- | ---: | ---: | ---: | ---: | +| GDC | 0 | 3 | 2 | 0 | +| QuiAntella | 29 | 0 | 0 | 0 | +| Colli | 38 | 4 | 0 | 1 | + +The GDC limitation is layered and reproducible: + +- All five terminal labels use a `PRE` with `style="text-align: right;"`. The existing contract excludes **every attribute on evidence**, even a style that appears innocuous. +- All five RSS bodies append a linked publisher-attribution paragraph after the label. Links are unsupported following content, so this independently fails the tail guard. Campoli also has an empty classed paragraph after the copyright line. +- Three bodies (both Oceanya articles and the Antica Scuderia dinner) contain a gallery `STYLE` element. This triggers the earlier whole-fragment active-content veto, which can conceal the other two reasons. + +Removing active nodes in a temporary diagnostic copy changes those three holds to `unsupported-disclosure-context`. Removing the PRE style next changes all five holds to `unsafe-disclosure-tail`. These diagnostic copies were never used as publication evidence. The four active-content Colli holds also lack approved disclosure labels; active markup is not an advertising signal. + +The PR reports these distinct conditions without changing the block predicate, limits, vocabulary, cutoff, conflict handling, or publication gates. Reasons identify one encountered blocker, not every blocker. `no-supported-disclosure` does not mean verified non-advertising. Worker failures, parser failures, and resource limits stay review-only. + +Do **not** globally strip styles, discard all material after a label, permit arbitrary PRE attributes, remove the active-content veto, or classify by brand/event words. Any future GDC adapter would need separately reviewed, narrow source-boundary rules and adversarial tests for forged attribution footers, wrong canonical links, hidden labels, later editorial material and active gallery stylesheets. Those policy extensions are not implemented here. + +## Sources and reproducibility + +Primary article URLs appear below. GDC and QuiAntella page text was inspected independently of feeds; current RSS/API bodies corroborated the labels/absence of supported labels. Colli's 42 retrieved public API bodies were inspected article-locally. Only short disclosure quotes, paths, dates, evidence summaries and diagnostic reasons are recorded here; no real bodies or personal review-app data are committed. + +Fetched sources: + +- [GDC supported sponsored RSS query](https://www.gazzettinodelchianti.it/?s=CONTENUTO%20SPONSORIZZATO&feed=rss2&paged=1) +- [QuiAntella public WP API](https://www.quiantella.it/wp-json/wp/v2/posts?per_page=100&orderby=modified&order=desc&_fields=id,date_gmt,modified_gmt,link,content) +- [Colli public WP API](https://daicollifiorentini.it/wp-json/wp/v2/posts?per_page=100&orderby=modified&order=desc&_fields=id,date_gmt,modified_gmt,link,slug,title,content) + +Response SHA-256 fingerprints (current responses, retained for provenance): + +- gdc: `be19eb1217f8722a3a428a2a7cd0ab2c9c04a2451515eb7cccaaf233e3d1a274` +- quiantella: `79c1ad1118661a304a449ca11b4510bf6605f9de5586f2e026e351d5c8926992` +- colli: `943bacdec5d7dd4a5af39b9976527403a29ce0041bea3e121296c3f8beb53160` + + +## All 77 candidate decisions + +The article links retain the workflow's exact paths. Dates below are publisher page dates for GDC/QuiAntella, UTC API dates for Colli. “Block recommendation” is proposed for separate classification review, not a published registry entry. + +### Gazzettino del Chianti + +| # / article | Date | Assessment | Evidence / diagnostic | +| --- | --- | --- | --- | +| [1. Oceanya Christmas trips](https://www.gazzettinodelchianti.it/chianti-f-no/oceanya-accende-il-natale-in-viaggio-verso-i-mercatini-piu-belli-deuropa/) | 2026-10-07 | confirmed advertisement | Publisher’s terminal `(CONTENUTO SPONSORIZZATO)` label; block recommendation. Gallery STYLE; styled PRE; linked RSS footer. Current fragment: `document-active-content`. | +| [2. Antica Scuderia dinner](https://www.gazzettinodelchianti.it/barberino-tavarnelle/dalla-vigna-alla-tavola-al-ristoro-lantica-scuderia-serata-con-selvaggina-e-vini-di-renzo-marinai/) | 2026-10-07 | confirmed advertisement | Publisher’s terminal `(CONTENUTO SPONSORIZZATO)` label; block recommendation. Gallery STYLE; styled PRE; linked RSS footer. Current fragment: `document-active-content`. | +| [3. Pieve di Campoli oil season](https://www.gazzettinodelchianti.it/barberino-tavarnelle/pieve-di-campoli-al-via-la-nuova-stagione-dellolio-fra-il-frantoio-di-san-donato-e-firenze/) | 2026-10-05 | confirmed advertisement | Publisher’s terminal `(CONTENUTO SPONSORIZZATO)` label; block recommendation. Styled PRE; linked RSS footer. Current fragment: `unsupported-disclosure-context`. | +| [4. Dancing La Rosa reopening](https://www.gazzettinodelchianti.it/san-casciano-v-p/circolo-arci-san-casciano-il-dancing-la-rosa-ha-riaperto-le-sue-porte/) | 2026-10-05 | confirmed advertisement | Publisher’s terminal `(CONTENUTO SPONSORIZZATO)` label; block recommendation. Styled PRE; linked RSS footer. Current fragment: `unsupported-disclosure-context`. | +| [5. Oceanya 2027 group trips](https://www.gazzettinodelchianti.it/chianti-f-no/oltre-100-persone-per-oceanya-grande-successo-per-la-presentazione-dei-viaggi-di-gruppo-2027/) | 2026-10-05 | confirmed advertisement | Publisher’s terminal `(CONTENUTO SPONSORIZZATO)` label; block recommendation. Gallery STYLE; styled PRE; linked RSS footer. Current fragment: `document-active-content`. | + +### QuiAntella + +| # / article | Date | Assessment | Evidence / diagnostic | +| --- | --- | --- | --- | +| [1. festa siciliana a bagno a ripoli tre giorni tra arancine cannoli e folclore](https://www.quiantella.it/festa-siciliana-a-bagno-a-ripoli-tre-giorni-tra-arancine-cannoli-e-folclore/) | 2026-10-07 | ordinary editorial | Local-food festival preview with program, opening hours, and access information. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [2. una cena di solidarieta per sostenere la famiglia di gaza accolta allantella](https://www.quiantella.it/una-cena-di-solidarieta-per-sostenere-la-famiglia-di-gaza-accolta-allantella/) | 2026-10-08 | ordinary editorial | Community benefit dinner announcement; proceeds support a Gaza family. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [3. alle gualchiere torna a farsi sentire il battito sette artisti per riaccendere l…](https://www.quiantella.it/alle-gualchiere-torna-a-farsi-sentire-il-battito-sette-artisti-per-riaccendere-lantico-borgo/) | 2026-10-07 | ordinary editorial | Report on a public art exhibition and civic cultural project at the Gualchiere. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [4. autostrade da in affitto unarea lungo lema](https://www.quiantella.it/autostrade-da-in-affitto-unarea-lungo-lema/) | 2026-10-08 | ordinary editorial | Reports a public notice for an onerous land concession, including eligibility and deadline. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [5. allerta meteo annullato il mercato allantella chiusi chioschi e giardini](https://www.quiantella.it/allerta-meteo-annullato-il-mercato-allantella-chiusi-chioschi-e-giardini/) | 2026-10-07 | ordinary editorial | Municipal severe-weather closure and safety report. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [6. tramvia addio a 31 32 e 23 il futuro dei bus si decide con i cittadini](https://www.quiantella.it/tramvia-addio-a-31-32-e-23-il-futuro-dei-bus-si-decide-con-i-cittadini/) | 2026-10-08 | ordinary editorial | Municipal public-transport consultation and proposed bus network changes. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [7. inaugurata la nuova farmacia dellantella tra innovazione e continuita](https://www.quiantella.it/inaugurata-la-nuova-farmacia-dellantella-tra-innovazione-e-continuita/) | 2026-10-05 | unresolved | Detailed single-brand pharmacy reopening feature includes loyalty discounts, added services, branded slogan, and a discount offer. No payment evidence or disclosure found; indicators justify human review only. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [8. fiori darancio 5 coppie verso le nozze 4](https://www.quiantella.it/fiori-darancio-5-coppie-verso-le-nozze-4/) | 2026-10-07 | ordinary editorial | Recurring civic notice listing marriage publications. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [9. inaugurazione della stagione del giovedi originale e i film di ottobre al cinema…](https://www.quiantella.it/inaugurazione-della-stagione-del-giovedi-originale-e-i-film-di-ottobre-al-cinemantella/) | 2026-10-07 | ordinary editorial | Local cinema program/event coverage; includes schedule, ticket prices, and a named welcome-drink partner, but no evidence of payment. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [10. piu grande e piu fornita inaugurata la rinnovata coop di ponte a ema fotogallery](https://www.quiantella.it/piu-grande-e-piu-fornita-inaugurata-la-rinnovata-coop-di-ponte-a-ema-fotogallery/) | 2026-10-06 | unresolved | Detailed single-retailer reopening feature lists expansion, departments, product offerings, and store leadership. No payment evidence or disclosure found; indicators justify human review only. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [11. cintura nera e capelli bianchi karaterzeta compie dieci anni video](https://www.quiantella.it/cintura-nera-e-capelli-bianchi-karaterzeta-compie-dieci-anni-video/) | 2026-10-06 | ordinary editorial | Community report on an older-adult karate seminar and local classes. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [12. hotel radisson blu ex sheraton garantite occupazione e tutele ai 44 lavoratori i…](https://www.quiantella.it/hotel-radisson-blu-ex-sheraton-garantite-occupazione-e-tutele-ai-44-lavoratori-in-appalto/) | 2026-10-06 | ordinary editorial | Labor-union account of worker protections in a hotel service-contract change. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [13. internati militari in sala consiliare la presentazione del libro la patria guard…](https://www.quiantella.it/internati-militari-in-sala-consiliare-la-presentazione-del-libro-la-patria-guarda-altrove/) | 2026-10-06 | ordinary editorial | Civic history/book event report with municipal and historical-association speakers. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [14. galleria san donato cade lultimo diaframma il sindaco chiede piu attenzione al t…](https://www.quiantella.it/galleria-san-donato-cade-lultimo-diaframma-il-sindaco-chiede-piu-attenzione-al-territorio-dopo-10-anni-di-cantieri-video-e-fotogallery/) | 2026-10-05 | ordinary editorial | Infrastructure milestone report with public officials and requests for territorial mitigation. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [15. il ciclone spazza via laperitivo e non solo una beffa la serata al crc antella](https://www.quiantella.it/il-ciclone-spazza-via-laperitivo-e-non-solo-una-beffa-la-serata-al-crc-antella/) | 2026-10-04 | ordinary editorial | Critical follow-up reports that paid event attendees did not receive promised parts of the event. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [16. connessioni in gioco riscoprire il piacere di stare offline](https://www.quiantella.it/connessioni-in-gioco-riscoprire-il-piacere-di-stare-offline/) | 2026-10-05 | ordinary editorial | Municipal digital-wellbeing event preview with free public programming. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [17. calcio una vittoria 3 pareggi e una sconfitta pioggia di gol](https://www.quiantella.it/calcio-una-vittoria-3-pareggi-e-una-sconfitta-pioggia-di-gol/) | 2026-10-04 | ordinary editorial | Local football results and standings. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [18. tra luce e ombre marina margherita si mette a nudo nei suoi quadri fotogallery e…](https://www.quiantella.it/tra-luce-e-ombre-marina-margherita-si-mette-a-nudo-nei-suoi-quadri-fotogallery-e-video/) | 2026-10-04 | ordinary editorial | Report on a local artist’s exhibition and opening. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [19. tra storia e scatti dautore successo allantella per la presentazione del libro s…](https://www.quiantella.it/tra-storia-e-scatti-dautore-successo-allantella-per-la-presentazione-del-libro-sulla-chiantigiana-fotogallery/) | 2026-10-04 | ordinary editorial | Report on a public book presentation and author discussion. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [20. fiera dellantella tutti sul carro trainato da contessa e carolina sotto lo sguar…](https://www.quiantella.it/fiera-dellantella-tutti-sul-carro-trainato-da-contessa-e-carolina-sotto-lo-sguardo-dellavvoltoio-charlie-video-e-foto/) | 2026-10-03 | ordinary editorial | Report on the opening of the local fair and civic attendance. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [21. il turismo che non paga in biblioteca il libro inchiesta di cristina nadotti](https://www.quiantella.it/il-turismo-che-non-paga-in-biblioteca-il-libro-inchiesta-di-cristina-nadotti/) | 2026-10-04 | ordinary editorial | Preview of a public-library discussion with a journalist about tourism impacts. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [22. inaugurata la via verde di ritortoli bellezza e sicurezza e sudore per ciclisti …](https://www.quiantella.it/inaugurata-la-via-verde-di-ritortoli-bellezza-e-sicurezza-e-sudore-per-ciclisti-e-pedoni-video-e-fotogallery/) | 2026-10-03 | ordinary editorial | Report on opening a publicly funded pedestrian/cycle route, with local officials and project details. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [23. salute mentale colloqui gratuiti allannunziata](https://www.quiantella.it/salute-mentale-colloqui-gratuiti-allannunziata/) | 2026-10-03 | ordinary editorial | Public-health service announcement for free hospital psychology appointments. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [24. torna allantella il mercatino dei ragazzi del calcit solidarieta e piu di 30 gaz…](https://www.quiantella.it/torna-allantella-il-mercatino-dei-ragazzi-del-calcit-solidarieta-e-piu-di-30-gazebo-per-la-lotta-contro-i-tumori/) | 2026-10-03 | ordinary editorial | Community charity-market announcement for cancer-patient support. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [25. clarice fa il bis a x factor ancora quattro si e con irama scatta labbraccio](https://www.quiantella.it/clarice-fa-il-bis-a-x-factor-ancora-quattro-si-e-con-irama-scatta-labbraccio/) | 2026-10-02 | ordinary editorial | Entertainment-news report on a local singer’s television appearance. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [26. ponte a ema via aldo moro non chiude ecco come cambia la circolazione](https://www.quiantella.it/ponte-a-ema-via-aldo-moro-non-chiude-ecco-come-cambia-la-circolazione/) | 2026-10-02 | ordinary editorial | Local roadworks and traffic-change update. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [27. annunziata i dottori apple e gigi di nuovo a tu per tu con gli anziani video e f…](https://www.quiantella.it/annunziata-i-dottori-apple-e-gigi-di-nuovo-a-tu-per-tu-con-gli-anziani-video-e-fotogallery/) | 2026-10-02 | ordinary editorial | Report on a Rotary-funded animal-assisted care program in a public hospital. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [28. su il sipario la nuova stagione del teatro di ponte a ema](https://www.quiantella.it/su-il-sipario-la-nuova-stagione-del-teatro-di-ponte-a-ema/) | 2026-10-02 | ordinary editorial | Community theatre-season schedule with ticketing/contact details and municipal patronage; no payment evidence. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | +| [29. incontro a distanza con luca mercalli il legame che non vediamo tra clima che ca…](https://www.quiantella.it/incontro-a-distanza-con-luca-mercalli-il-legame-che-non-vediamo-tra-clima-che-cambia-e-pace-che-vacilla/) | 2026-10-02 | ordinary editorial | Preview of a public discussion about climate and peace at a community venue. No supported disclosure; remain visible. Current fragment: `no-supported-disclosure`. | + +### Dai Colli Fiorentini + +| # / article | Date | Assessment | Evidence / diagnostic | +| --- | --- | --- | --- | +| [1. Incidente stradale, cisterna ribaltata: intervento dei Vigili del Fuoco](https://daicollifiorentini.it/incidente-stradale-cisterna-ribaltata-intervento-dei-vigili-del-fuoco/) | 2026-10-08 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [2. Coppa Italia Eccellenza: Antella ko ai rigori, il Poggibonsi ne prende 6!](https://daicollifiorentini.it/coppa-italia-eccellenza-risultati-antella-poggibonsi/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [3. Bagno a Ripoli chiude parchi, impianti e cimiteri per l’allerta meteo. Annullato…](https://daicollifiorentini.it/bagno-a-ripoli-chiude-parchi-impianti-e-cimiteri-per-lallerta-meteo-annullato-il/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [4. Impruneta, in arrivo i 9 giorni della Fiera di San Luca 2026: dal fierone ai “fo…](https://daicollifiorentini.it/impruneta-in-arrivo-i-9-giorni-della-fiera-di-san-luca-2026-dal-fierone-ai-fochi/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [5. un anno dopo la prima proiezione a ufo torna al cinema antella prenotazioni aper…](https://daicollifiorentini.it/un-anno-dopo-la-prima-proiezione-a-ufo-torna-al-cinema-antella-prenotazioni-aperte/) | Unavailable | unresolved | Unavailable; no blocking evidence. Current fragment: `unavailable`. | +| [6. Allerta meteo arancione, Firenze: chiusi parchi e cimiteri, sospesa una fermata …](https://daicollifiorentini.it/allerta-meteo-arancione-firenze-chiusi-parchi-e-cimiteri-sospesa-una-fermata-della-tramvia/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `document-active-content`. | +| [7. 12 ore di nuoto per beneficenza: anche una sola vasca può fare la differenza! Ap…](https://daicollifiorentini.it/nuoto-e-beneficenza-un-giorno-in-vasca-aperte-le-iscrizioni-per-la-2-edizione-di-swim4cmt/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [8. Firenze Sud, tenta il furto in pieno giorno arrampicandosi sulla palazzina ma vi…](https://daicollifiorentini.it/firenze-sud-tenta-il-furto-in-pieno-giorno-arrampicandosi-sulla-palazzina-ma-viene-visto-intervento-dei-carabinieri/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [9. Maltempo in Toscana, allerta arancione: i dettagli](https://daicollifiorentini.it/maltempo-in-toscana-allerta-arancione/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [10. Falso allarme bomba al piazzale Michelangelo: individuato il responsabile](https://daicollifiorentini.it/falso-allarme-bomba-al-piazzale-michelangelo-indagine/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [11. Promozione – Salta una panchina tra le fiorentine! Ecco il possibile sostituto](https://daicollifiorentini.it/promozione-girone-c-salta-una-panchina-tra-le-fiorentine-il-possibile-sostituto/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [12. San Casciano, primo viaggio a bordo del nuovo scuolabus con la nonna Gisella che…](https://daicollifiorentini.it/san-casciano-primo-viaggio-a-bordo-del-nuovo-scuolabus-con-la-nonna-gisella-che-legge-le-storie/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [13. Greve, il sindaco Sottani sul tetto del 30 per cento nella scuola di Panzano: “G…](https://daicollifiorentini.it/greve-il-sindaco-sottani-sul-tetto-del-30-per-cento-nella-scuola-di-panzano-grazie-allinterlocuzione-del-presidente-mattarella/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [14. Tramvia 3.2.1 per Bagno a Ripoli, nuova fase dei lavori: cambia la viabilità](https://daicollifiorentini.it/tramvia-3-2-1-per-bagno-a-ripoli-nuova-fase-dei-lavori-la-viabilita/) | 2026-10-07 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [15. Riappare la scritta “Qui nessuno è straniero”: studenti e Q1 in Santa Croce per …](https://daicollifiorentini.it/riappare-la-scritta-qui-nessuno-e-straniero-studenti-e-q1-in-santa-croce-per-rifare-lo-striscione/) | 2026-10-06 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [16. Salta la prima panchina in Serie D! E c’è già il nome del nuovo mister](https://daicollifiorentini.it/salta-la-prima-panchina-in-serie-d-e-ce-gia-il-nome-del-nuovo-mister/) | 2026-10-06 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [17. Fantacalcio Promozione, la top 11 del 4° turno: quanti giovani!](https://daicollifiorentini.it/fantacalcio-promozione-top-11-galluzzo-lebowski-luco/) | 2026-10-06 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [18. “Qui nessuno è straniero”, striscione rimosso dalla scuola. Studenti e Istituzio…](https://daicollifiorentini.it/qui-nessuno-e-straniero-striscione-rimosso-dalla-scuola-studenti-e-istituzioni-lo-rifacciamo/) | 2026-10-06 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [19. A Firenze 50 dimissioni di conducenti autobus nel 2026: l’allarme dei sindacati](https://daicollifiorentini.it/a-firenze-50-dimissioni-di-conducenti-autobus-nel-2026-lallarme-dei-sindacati/) | 2026-10-06 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [20. Tramvia 3.2.2, manifestazione in difesa delle alberature di Viale dei Mille](https://daicollifiorentini.it/tramvia-3-2-2-manifestazione-in-difesa-delle-alberature-di-viale-dei-mille/) | 2026-10-06 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `document-active-content`. | +| [21. Fantacalcio Eccellenza, la top 11 del 4° turno: Antella colpita da un ex](https://daicollifiorentini.it/fantacalcio-eccellenza-la-top-11-del-4-turno-antella-colpita-da-un-ex/) | 2026-10-06 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [22. Firenze, imbottigliati alla stazione centrale: taxi vuoti e fermi in coda, passe…](https://daicollifiorentini.it/firenze-imbottigliati-alla-stazione-centrale-taxi-vuoti-e-fermi-in-coda-passeggeri-in-attesa/) | 2026-10-06 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `document-active-content`. | +| [23. Fantacalcio Serie D, la top 11 del 6° turno: attacco super!](https://daicollifiorentini.it/fantacalcio-serie-d-la-top-11-del-6-turno-attacco-super/) | 2026-10-06 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [24. Galleria A1 San Donato, Salvini e Giani premono il tasto rosso: abbattuto l’ulti…](https://daicollifiorentini.it/abbattuto-lultimo-diaframma-della-galleria-a1-san-donato-autostrada-salvini-giani/) | 2026-10-05 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [25. VIDEO / Firenze, bombola del gas ai piedi del David al piazzale Michelangelo: in…](https://daicollifiorentini.it/video-firenze-bombola-del-gas-ai-piedi-del-david-al-piazzale-michelangelo-intervento-dei-carabinieri/) | 2026-10-05 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [26. “Un filo che emancipa”, le ricamatrici: tra memoria, lavoro e comunità.](https://daicollifiorentini.it/un-filo-che-emancipa-le-ricamatrici-tra-memoria-lavoro-e-comunita/) | 2026-10-05 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [27. Conte Mascetti diserta la serata Ciclone al CRC Antella: “Personaggi inqualifica…](https://daicollifiorentini.it/conte-mascetti-diserta-la-serata-ciclone-al-crc-antella-personaggi-inqualificabili/) | 2026-10-05 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [28. Tavarnuzze, il piazzale intitolato a Giovanni Vitali](https://daicollifiorentini.it/tavarnuzze-il-piazzale-intitolato-giovanni-vitali/) | 2026-10-05 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [29. La Domenica dei Dilettanti: Antella ripresa al 95′, Sangio prima!](https://daicollifiorentini.it/la-domenica-dei-dilettanti-antella-ripresa-al-95-sangio-prima/) | 2026-10-04 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [30. Serie D- Ottovolante al Pazzagli: nove gol fra Grassina e Lucchese!](https://daicollifiorentini.it/serie-d-grassina-lucchese-risultato-partita/) | 2026-10-04 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [31. L’Antella esplode di vita nei giorni di Fiera…e si tuffa nel passato contadino. …](https://daicollifiorentini.it/lantella-esplode-di-vita-nei-giorni-di-fiera-e-si-tuffa-nel-passato-contadino-spunta-anche-un-giocatore-della-fiorentina/) | 2026-10-04 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [32. Firenze, baracche a fuoco vicino al centro](https://daicollifiorentini.it/firenze-baracche-a-fuoco-vicino-al-centro/) | 2026-10-04 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [33. Calcio dilettantistico, addio a Daniele Lombardi](https://daicollifiorentini.it/calcio-dilettantistico-addio-a-daniele-lombardi/) | 2026-10-03 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [34. Bagno a Ripoli e Ponte a Ema connesse…anche a piedi o in bici: inaugurato il nuo…](https://daicollifiorentini.it/bagno-a-ripoli-ponte-a-ema-connesse-anche-a-piedi-o-in-bici-inaugurato-nuovo-percorso/) | 2026-10-03 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [35. Il Lebowski perde a tavolino per un petardo e sbotta: “Difendiamo i nostri tifos…](https://daicollifiorentini.it/il-lebowski-perde-a-tavolino-per-un-petardo-e-sbotta-difendiamo-i-nostri-tifosi/) | 2026-10-02 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [36. La grassinese Giorgia va avanti ad X Factor, quattro si per CLARICE: “Appena sce…](https://daicollifiorentini.it/la-grassinese-giorgia-va-avanti-ad-x-factor-quattro-si-per-clarice-appena-scesa-dal-palco-ho/) | 2026-10-02 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `document-active-content`. | +| [37. Firenze, gli Angeli del Bello festeggiano i 16 anni prendendosi cura dell’area i…](https://daicollifiorentini.it/firenze-gli-angeli-del-bello-festeggiano-i-16-anni-prendendosi-cura-dellarea-intorno-al-teatro-del-maggio/) | 2026-10-02 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [38. Tavarnuzze, apre un nuovo punto di prestito e lettura della Biblioteca comunale](https://daicollifiorentini.it/tavarnuzze-apre-un-nuovo-punto-di-prestito-e-lettura-della-biblioteca-comunale/) | 2026-10-02 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [39. Impruneta, messa in sicurezza di via dei Falciani: terminati i lavori di consoli…](https://daicollifiorentini.it/impruneta-messa-in-sicurezza-di-via-dei-falciani-terminati-i-lavori-di-consolidamento/) | 2026-10-02 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [40. Fi-Pi-Li, ampliamento del tratto Scandicci-Lastra a Signa e pannelli fonoassorbe…](https://daicollifiorentini.it/fi-pi-li-ampliamento-del-tratto-scandicci-lastra-a-signa-previsti-e-pannelli-fonoassorbenti-con-fotovoltaico/) | 2026-10-02 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [41. Viabilità Ponte a Ema: modifica rispetto alle previsioni iniziali, comunicata da…](https://daicollifiorentini.it/viabilita-ponte-a-niccheri-novita-comunicata-dal-comune-di-bagno-a-ripoli/) | 2026-10-02 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [42. Coro Sociale di Grassina, via alla nuova stagione…e si cercano nuovi cantanti (s…](https://daicollifiorentini.it/coro-sociale-di-grassina-via-alla-nuova-stagione-e-si-cercano-nuovi-cantanti-soprattutto-uomini/) | 2026-10-02 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | +| [43. Chianti, bonusback Tpl della Città Metropolitana: rimborsi fino al 60 per cento …](https://daicollifiorentini.it/chianti-bonusback-tpl-della-citta-metropolitana-rimborsi-fino-al-60-per-cento-sul-costo-dellabbonamento/) | 2026-10-02 | ordinary editorial | Article-local news/community/service coverage; no paid-content disclosure. Remain visible. Current fragment: `no-supported-disclosure`. | + +## Validation + +- 76 current article bodies: identical old/new decisions; no input body was published or used as a checked-in fixture. +- Invented regression cases cover missing/unsupported vocabulary, incidental mentions, hidden/quoted/styled evidence, long/unsupported tails, active content, later independently valid labels, the 599/600-character boundary, and worker/report propagation. +- An integration regression verifies held candidates leave state, all registries, baselines and both subscription outputs byte-identical and logs only path/reason. +- The browser/client safety tests remain mandatory. Local browser verification was unavailable because no Chromium executable was installed and the attempted Playwright download was invalid; CI must supply this gate before merge. diff --git a/test/article-cards.test.mjs b/test/article-cards.test.mjs index 0405228..256992f 100644 --- a/test/article-cards.test.mjs +++ b/test/article-cards.test.mjs @@ -32,6 +32,72 @@ test('standalone and terminal BR disclosures, including short PRE, are accepted' assert.equal(classify('quiantella', '

Informazione promozionale

'), 'block'); for (const label of ['Articolo ADV', 'Contenuto adv', '#adv']) assert.equal(classify('colli', `

${label}

`), 'block'); }); +test('review diagnostics survive the worker without relaxing disclosure evidence', async t => { + const worker = new DisclosureClassifier(); t.after(() => worker.close()); + const label = '

CONTENUTO SPONSORIZZATO

'; + const cases = [ + ['

Ordinary local news.

', 'no-supported-disclosure'], + ['

INFORMAZIONE PUBBLICITARIA

', 'no-supported-disclosure'], + ['

Discussing CONTENUTO SPONSORIZZATO.

', 'no-supported-disclosure'], + ['

CONTENUTO SPONSORIZZATO

', 'no-supported-disclosure'], + ['', 'unsupported-disclosure-context'], + ['
' + label + '
', 'unsupported-disclosure-context'], + ['
' + label + '
', 'unsupported-disclosure-context'], + [label + '

' + 'x'.repeat(600) + '

', 'unsafe-disclosure-tail'], + [label + '
', 'unsafe-disclosure-tail'], + ['' + label, 'document-active-content'], + ['' + label, 'document-active-content'], + ['

Ordinary news.

', 'document-active-content'], + ]; + for (const [html, reason] of cases) { + const metrics = {}; + assert.equal(classify('gdc', html, { metrics }), 'review', html); + assert.equal(metrics.reason, reason, html); + const result = await worker.classify('gdc', html); + assert.equal(result.decision, 'review', html); assert.equal(result.reason, reason, html); + } + // A rejected earlier label cannot veto a later independently valid one. + const metrics = { reason: 'stale', limited: 'stale' }; + assert.equal(classify('gdc', '' + label, { metrics }), 'block'); + assert.equal(metrics.reason, undefined); assert.equal(metrics.limited, undefined); + assert.equal(classify('gdc', label + '

' + 'x'.repeat(599) + '

'), 'block'); + assert.equal((await worker.classify('gdc', label)).reason, undefined); +}); +test('discovery logs explain held evidence without publishing it', async t => { + const root = await fixture(t); + const bodies = [ + '

Ordinary local news.

', + '', + '

Articolo ADV

' + 'x'.repeat(600) + '

', + '

Articolo ADV

', + ]; + const names = ['article-cards/state.json', 'fucksponsors.txt', 'sponsored-article-cards.txt', ...Object.keys((await load(root)).sites).map(site => `article-cards/baseline/${site}.json`), ...['gazzettinodelchianti.it', 'quiantella.it', 'daicollifiorentini.it', 'firenzedintorni.it'].map(host => `article-cards/registries/${host}.json`)]; + const before = await Promise.all(names.map(name => readFile(path.join(root, name)))); + let logged; + const report = await discover(root, { now: Date.parse('2026-10-02T12:00Z'), log: value => { logged = JSON.parse(value); }, get: async u => { + if (u.startsWith('https://daicollifiorentini.it')) return response(bodies.map((html, i) => record('colli', `/invented-held-${i}/`, html))); + throw Error('invented offline'); + } }); + assert.equal(report.colli.added, 0); + assert.deepEqual(report.colli.review.map(r => r.reason), ['no-supported-disclosure', 'unsupported-disclosure-context', 'unsafe-disclosure-tail', 'document-active-content']); + assert.deepEqual(logged, report); + for (const row of report.colli.review) assert.deepEqual(Object.keys(row).sort(), ['path', 'reason']); + for (const [i, name] of names.entries()) assert.deepEqual(await readFile(path.join(root, name)), before[i], name); +}); +test('invented RSS gallery, styled PRE and linked attribution each retain their evidence guard', () => { + // Reproduce the observed structures using invented text/URLs, not live bodies. + const label = '
(CONTENUTO SPONSORIZZATO)
'; + const plain = '
(CONTENUTO SPONSORIZZATO)
'; + const footer = '

Invented article Story from Publisher.

'; + for (const [html, reason] of [ + ['
Gallery
' + label + footer, 'document-active-content'], + [label + footer, 'unsupported-disclosure-context'], + [plain + footer, 'unsafe-disclosure-tail'], + ]) { + const metrics = {}; assert.equal(classify('gdc', html, { metrics }), 'review'); assert.equal(metrics.reason, reason); + } + assert.equal(classify('gdc', plain + '

Short attribution

'), 'block'); +}); test('incidental, hidden, code, quote, widget, nonterminal, and ancestor-tail examples fail open', () => { for (const html of ['

Discussing CONTENUTO SPONSORIZZATO.

', '', '', '', '
CONTENUTO SPONSORIZZATO
', '
Example: CONTENUTO SPONSORIZZATO
', '', '

CONTENUTO SPONSORIZZATO

', '', '

CONTENUTO SPONSORIZZATO

', '

CONTENUTO SPONSORIZZATO

', '

Text
CONTENUTO SPONSORIZZATO
More text

', '
CONTENUTO SPONSORIZZATO

' + 'Long editorial. '.repeat(60) + '

']) assert.equal(classify('gdc', html), 'review', html); for (const label of ['INFORMAZIONE PUBBLICITARIA', 'Contenuto promozionale in collaborazione con Invented Brand']) assert.equal(classify('gdc', `

${label}

`), 'review'); diff --git a/tools/article-classifier.mjs b/tools/article-classifier.mjs index bc86b76..9283f85 100644 --- a/tools/article-classifier.mjs +++ b/tools/article-classifier.mjs @@ -3,7 +3,7 @@ import { classify } from './article-disclosure.mjs'; if (!isMainThread) parentPort.on('message', ({ site, html }) => { const metrics = {}; - try { parentPort.postMessage({ decision: classify(site, html, { metrics }), reason: metrics.limited, metrics }); } + try { parentPort.postMessage({ decision: classify(site, html, { metrics }), reason: metrics.limited || metrics.reason, metrics }); } catch { parentPort.postMessage({ decision: 'review', reason: 'unreadable-content' }); } }); diff --git a/tools/article-disclosure.mjs b/tools/article-disclosure.mjs index 84a4740..95ff50a 100644 --- a/tools/article-disclosure.mjs +++ b/tools/article-disclosure.mjs @@ -26,7 +26,12 @@ function append(to, child) { const tailJoin = (a, b) => normalize(a + ' ' + b).slice(0, 600); export function classify(site, html, { budgetMs = 250, maxNodes = 50000, maxDepth = 128, metrics = {} } = {}) { - if (!labels[site] || typeof html !== 'string' || html.length > 2_000_000) return 'review'; + // Diagnostics describe the evidence contract, never a keep/ad decision. + // Clear prior results if a caller reuses its metrics object. + delete metrics.reason; delete metrics.limited; + const review = reason => { metrics.reason = reason; return 'review'; }; + if (!labels[site]) return review('unsupported-disclosure-site'); + if (typeof html !== 'string' || html.length > 2_000_000) return review('unreadable-content'); const deadline = performance.now() + budgetMs; const limit = reason => { metrics.limited = reason; return 'review'; }; if (budgetMs <= 0) return limit('time-limit'); @@ -42,13 +47,13 @@ export function classify(site, html, { budgetMs = 250, maxNodes = 50000, maxDept let plain = true; if (node.nodeType === 1) { const tag = node.tagName.toUpperCase(); const attributes = node.attributes; - if (active.has(tag)) return 'review'; + if (active.has(tag)) return review('document-active-content'); for (const attribute of attributes) { metrics.operations++; if (metrics.operations % 128 === 0 && performance.now() > deadline) return limit('time-limit'); // Case-insensitive event handlers are active even on an unrelated // image/link. Ordinary href/src/class/id/style attributes are not. - if (attribute.name.toLowerCase().startsWith('on')) return 'review'; + if (attribute.name.toLowerCase().startsWith('on')) return review('document-active-content'); } plain = supported.has(tag) && attributes.length === 0; } @@ -70,6 +75,7 @@ export function classify(site, html, { budgetMs = 250, maxNodes = 50000, maxDept append(summary, childInfo.summary); info.plainTree &&= childInfo.plainTree; metrics.operations++; } } + let heldLabelReason; for (const node of nodes) { const info = metadata.get(node); let following = ''; // Parent-first traversal shares each ancestor's already bounded suffix. @@ -82,9 +88,13 @@ export function classify(site, html, { budgetMs = 250, maxNodes = 50000, maxDept metrics.operations++; } if (metrics.operations % 128 === 0 && performance.now() > deadline) return limit('time-limit'); - if (!info.context || !info.plainTree || !['P', 'DIV', 'PRE'].includes(node.tagName) || info.tail.length >= 600) continue; + if (!['P', 'DIV', 'PRE'].includes(node.tagName)) continue; const s = info.summary; - if (!s.long && labels[site].test(normalize(s.text)) || node.tagName !== 'PRE' && s.br && !s.lineLong && labels[site].test(normalize(s.lastLine))) return 'block'; + const matched = !s.long && labels[site].test(normalize(s.text)) || node.tagName !== 'PRE' && s.br && !s.lineLong && labels[site].test(normalize(s.lastLine)); + if (!matched) continue; + if (!info.context || !info.plainTree) { heldLabelReason ??= 'unsupported-disclosure-context'; continue; } + if (info.tail.length >= 600) { heldLabelReason ??= 'unsafe-disclosure-tail'; continue; } + return 'block'; } - return 'review'; + return review(heldLabelReason || 'no-supported-disclosure'); }