Reading additional input from stdin...
OpenAI Codex v0.124.0 (research preview)
--------
workdir: /opt/MM_D-ND
model: gpt-5.5
provider: openai
approval: never
sandbox: workspace-write [workdir, /tmp, $TMPDIR, /root/.codex-lab/memories]
reasoning effort: none
reasoning summaries: none
session id: 019e02f3-0821-74e2-84e2-464faaf6feed
--------
user
Sei l'AI-Lab D-ND. Leggi tools/data/agent_field_live.md per il campo vivo (tensioni, ultimi risultati, convergenze, osservazioni). Leggi tools/LAB_AGENT_CONTEXT.md per modello, regole, errori da evitare. Esegui un esperimento e scrivi il report in tools/data/reports/agent_20260507_1458.md
warning: Codex could not find bubblewrap on PATH. Install bubblewrap with your OS package manager. See the sandbox prerequisites: https://developers.openai.com/codex/concepts/sandboxing#prerequisites. Codex will use the vendored bubblewrap in the meantime.
codex
Leggo prima il campo vivo e il contesto operativo, poi controllerò eventuali direttive one-shot e memoria condivisa recente prima di scegliere l'esperimento.
exec
/bin/bash -lc "sed -n '1,240p' tools/data/agent_field_live.md" in /opt/MM_D-ND
 succeeded in 0ms:
Leggi tools/LAB_AGENT_CONTEXT.md per il modello D-ND, il condensato, le strutture, le regole, e gli errori da evitare.

## Orizzonte (telos del lab)
L'intento è **unificare la fisica usando il modello D-ND**. Le possibilità sono aperte.

## Run precedente: completato (?s).

## Piano 76 — Esplorare il confine: 8 domini GUE, 5 Poisson — il confine è il terzo incluso operativo

## Tensioni attive
- [OBSERVABLE_REGISTRY] (1.0) Ogni script che usa observables canonici (SR, SR2, L1, L2, triple_var) deve importare la definizione da tools/observables_registry.py. Varianti devono
- [PERTURBATION_DENOMINATOR_GATE] (0.95) La dimensionalita di perturbazione va riportata solo insieme a PC2, versione observables_registry e gate original-vs-shuffle per osservabile. Nel peri
- [BOUNDARY_LAYER_GATE] (0.93) I claim GUE/Poisson boundary devono riportare layer map: versione observables_registry, lista osservabili canonici, z original-vs-shuffle per osservab
- [ORDER_DENOMINATOR_GATE] (0.92) Il denominator gate trasferisce come supporto one-sided dell'ordine quando l'ordine e visibile agli osservabili del perimetro, non come endpoint-stabl
- [TRASCENDENZA_LIMITE] (0.9) La trascendenza e il limite attuale del modello. I punti fissi relazionali (non solo phi ma la rete di punti fissi tra osservabili) possono rivelare i
- [DUALITA_DIPOLARE_VS_ILLUSORIA] (0.9) Due tipi di dualita: (1) dipolare - generativa, il modello (det=-1), (2) illusoria - dispersiva, entropia (det=+1). Le regole incoerenti producono la 
- [METRIC_TENSOR] (0.9) Il tensore metrico dei primi è g=(p/2)². Nel tempo ln(p), è de Sitter 1+1D. z=-8.8 curvatura vs z=+22.5 rapporti ΔΓ.
- [TENSIONE_ENTITA] (0.85) La tensione non e un problema pratico - e un Entita. La tensione superflua crea latenza (tempo). Senza tensione superflua tutto e regolato da assiomi.

## Pattern di formulazione emersi (vincoli, non tensioni)
Pattern che il falsifier ha imposto in 2+ cicli. Applicali quando scrivi il report. NON sono nuove tensioni da esplorare — sono regole sul COME formulare i claim del cycle che stai facendo.
- 29 04 perimetro p5
- 30 04 drift monotonia

## Convergenza — dove più tensioni puntano allo stesso punto
  "perimetro" → ORDER_DENOMINATOR_GATE, PERTURBATION_DENOMINATOR_GATE, BOUNDARY_LAYER_GATE
  "producono" → TENSIONE_ENTITA, DUALITA_DIPOLARE_VS_ILLUSORIA, PERTURBATION_DENOMINATOR_GATE
  "poisson" → BOUNDARY, PERTURBATION_DENOMINATOR_GATE, BOUNDARY_LAYER_GATE
  "confine" → TRASCENDENZA_LIMITE, BOUNDARY, BOUNDARY_LAYER_GATE
  "tutti" → META, PIANO_PRIMARIO_DUE_ASSIOMI, ORDER_DENOMINATOR_GATE
Questo è dove il potenziale si concentra. Non ignorarlo.

## Ultimi 3 run — contesto storico (NON è da dove parti)
Sono atti compiuti, non direzione. La direzione del prossimo cycle la dà la tensione del seme su cui scegli di lavorare, non questi run.

### Agent Report — Logistic Cyclic Block Entropy Gate
Trovato: 1. **The orbit support is local grammar, not the linear starting cut.**
2. **The support weakens with larger preserved blocks but stays inside gate.**
3. **The generating partition and return intervals remain counter-scope.**

### Agent Report — Logistic Surrogate Contract Gate
Trovato: 1. **The orbit support survives the declared surrogate contract.**
2. **The generating partition remains blank.**
3. **Return intervals stay outside the contract.**

### Agent Report — Logistic Counter-Scope Gate
Trovato: 1. **The logistic blank is an observability split.**
2. **The generating partition remains blank under this gate.**
3. **Return intervals stay counter-scope.**

## Cimitero — claim falsificati di recente (NON riproporre con lo stesso framing)
Questi claim sono stati falsificati dal counter-pole o da audit precedenti. Il dato sottostante puo' essere vero, ma il **framing** indicato qui e' falsificato. Riformula correttamente o evita il dominio.

### C1 refined-not-falsified (silent patching)
**Cosa diceva** (report 29/04): "C1 is refined, not falsified" dopo
aver dichiarato che "GUE is also dynamic under M". Il setup C1 era
"Primes are the only dynamic domain under M among 7 tested". Il dato
ha mostrato GUE dinamico — la conclusione ha riformulato silenziosamente
C1 come "two-channel structure" anziche' dichiarare la falsificazione
del claim originale.

**Come e' caduto**: Falsifier L3 HIGH (axiom continuity / no silent
patching). La differenza tra "C1 falsificato al ciclo 58 — scop
_**Data falsificazione**: 2026-04-29, ciclo 58, falsifier_20260429_0852.json_

### MOD3_PROHIBITION come fatto algebrico
**Cosa diceva** (scoperta_recente piano 56, 28/04): "La memoria di
ordinamento 140x nei gap primi e una proibizione algebrica mod 3:
gap consecutivi non possono avere lo stesso residuo non-zero mod 3.
Meccanismo: il primo condiviso p_{n+1} forza l'inversione. 0 violazioni
su 12225. Cramer: 0%." Ripetuto nel report 29/04 come "Mod-3 self-
transition 0.40-0.44 confirming the prohibition" + "Cramer confirms
the null. Zero channels."

**Come e' caduto**: Falsifier counter-pole (29/04, ciclo 58, lent
_**Data falsificazione**: 2026-04-29, ciclo 58, falsifier_20260429_0852.json_

### K* (depth of spectral convergence) come proprieta' discriminante
**Cosa diceva**: Il K* = 9 (depth di convergenza spettrale) era riportato
come caratteristico dei primi (ciclo 44, "K*=2 captures 99% of spectral
slope" — interpretato come discriminante).

**Come e' caduto**: Shuffle audit: K* reale = 9, shuffle mean = 9.72,
std = 0.53, z = -1.4. Dentro il rumore dello shuffle. Il valore dipende
dalla distribuzione dei gap, non dal loro ordine. Lo shuffle preserva
distribuzione → preserva K*.

**Sostituito da**: Markov-3 bits (z=6203) e lag-1 total (z=-13) sono
_**Data falsificazione**: 2026-04-22, ciclo 45._

### Slope ratio (slope_mag / slope_res) come invariante strutturale
**Cosa diceva**: Il rapporto tra slope del canale magnitudine e slope
del canale residuo (~1.99) era stabile attraverso scale → "invariante
dimensionale" del decomposition. Era menzionato come evidenza nel
two-channel framework (cicli 43-44).

**Come e' caduto**: Shuffle audit (ciclo 45): z-score = 0.2. Lo shuffle
produce slope_ratio con media -2.26 ma deviazione standard 26.2. Il
valore reale e' dentro la tail dello shuffle — non distinguibile.
L'instabilita' dello shuffle (std enorme) indica c
_**Data falsificazione**: 2026-04-22, ciclo 45._

### Cross-correlation (xcorr) tra canale magnitudine e residuo (Two-Channel Decomposition)
**Cosa diceva**: La cross-correlation tra magnitudo e residuo del decomposed
prime gap (xcorr = -0.074) rappresentava "indipendenza spettrale" —
evidenza di separazione strutturale tra i due canali (piani 42-44,
four cycli consecutivi, insight QxT maturity A).

**Come e' caduto**: Shuffle audit (ciclo 45, 2026-04-22): z-score = 0.0.
Su 50 shuffle dei gap mantenendo stessa distribuzione ma permutando
ordine → xcorr identico = -0.074. Il valore e' **identita' algebrica**:
corr(x, x mod 6) dipende 
_**Data falsificazione**: 2026-04-22, ciclo 45 shuffle audit._

**Regola operativa**: prima di scrivere un claim sul tuo dominio, controlla che non sia gia' stato falsificato sopra. Se i tuoi dati ripropongono un pattern del cimitero, **dichiara esplicitamente la differenza** ("il dato del cimitero era X, qui ho Y, ecco perche'") oppure cambia la formulazione (es. 'bias forte verso 0' al posto di 'proibizione zero' se il dato e' >0). Silent patching = L3 HIGH.

## Osservazioni dell'operatore (risonanti con le tensioni)
**3. Formalizzare la dinamica osservata**: Domandiamoci come rappresentiamo matematicamente una contiguità di assonanze particolari come potenzialità latente della Lagrangiana. Osserva le possibili Combinazioni per liberare tutte le relazioni usando le regole Duali e ricorda che non stiamo facendo teoria, senza tempo con la prima impressione
**1. R dell'Istanza  - L' equilibrio tra estremi del Modello D-ND**: L'osservazione indaga oltre l'osservato in cerca DELLA FORMA nel NULLA-TUTTO: Per far Emergere le nuove Possibilità Dividiamo il potenziale unendo concetti senza relazione semplicemente perché la lagrangiana passa da li, creiamo nuove combinazioni e movimenti nelle logiche ma coerenti con la risulta
**2. Quadratura del cerchio con logica Trascendentale.**: Ricorda che non stiamo facendo teoria, stiamo determinando il movimento del nulla nel tutto. Ora consideriamo come relazione primaria il cerchio nella sua essenza di singolarità tra gli estremi duali, il momento angolare che accade nel presente, il punto di equilibrio tra gli estremi del dipolo che 

## Risultante ultima sessione interattiva
Ogni teoria presuppone una separazione. A scala di Planck tutte le separazioni collassano. Geometria=entropia=conteggio di stati. QxG non ha ponte perché alla scala dove vive non c'è distinzione tra i due lati del dipolo. Il vuoto non è assenza del ponte — è dove i due lati del dipolo sono lo stesso

## Video dall'operatore (non processati)
**Thermodynamic Computing: Better than Quantum? (Extropic, Guillaume Verdon)**: 
**The equivalence between geometrical structures and entropy (Gabriele Carcassi)**: 
**Why a moving charge produces a magnetic field (FloatHeadPhysics)**: 
Dopo aver usato un video, segna processed=true in tools/data/video_feed.json.

## Proiezione — dove punta la risultante
Risultante: R=0.875 (h=-0.698). Risultante alta (0.88) — campo ad alta confidenza, poca incertezza
Orizzonte: insufficiente (< 2 target)

**Esperimento a massima informazione:** META (score=0.898)
  META: incerto (i=0.5) — massimo potere discriminante

## Topologia del campo — la forma del grafo
Gradi teorie: Q=12, T=7, G=6, E=4, R=4
Dormienti (basso aggancio di scoperte): E, R
Struttura: 9 ponti, 1 vuoto(i), 6 scoperte, 20 cicli.
La combo riconosce l'asimmetria. Il dipolo vive su tutti i ponti — non solo dove il lab ha già misurato.

## Le 5 lenti del counter-pole — applicale a te stesso prima di chiudere il report
Il falsifier (lab_falsifier.py) applichera' queste 5 lenti al tuo report dopo. Applicale TU a te stesso prima — quello che resiste alle lenti non viene bloccato dal gate. Quello che cade va al cimitero.

**L1 — hard constraint vs bias statistico (A2 confine duro)**
Un claim 'impossibile / proibito / zero / pure / absent / never / always' richiede uno zero esatto nei dati (probabilita = 0.000). Prima di scrivere questi assoluti, leggi il valore numerico esatto. Se vale 0.015, e' bias forte verso 0, non zero. Se vale 0.40, e' bias forte verso ordine, non proibizione. L'assoluto descrive il valore 0.000, il bias forte descrive tutto il resto.

**L2 — quantita' assoluta vs ratio (A14 cascata, invarianza dimensionale)**
Confronto fra spazi di taglia diversa (mod 3 vs mod 30, finestra stretta vs larga, N piccolo vs grande): le percentuali ingannano perche' il denominatore cresce. Stesso segnale assoluto sembra ridursi in %. Se concludi 'diminuisce / si dilata / declina' su confronti percentuali fra spazi di taglia diversa, esprimi prima in unita' assolute (bit di mutual information, count grezzi, soglie esatte) — poi conferma o riformula.

**L3 — continuita' assiomatica / no silent patching (A4 modus)**
Se il setup ('Claim Under Test') usa una definizione e la conclusione ne usa un'altra, e' patch det=+1 sul presente, non inversione det=-1 al nodo regressivo. Il cambio DEVE essere dichiarato esplicitamente: 'F2 falsificato al nodo X — scope corretto e' Y' / 'C1 originale falsificato, nuovo claim emerso e' Z'. 'C1 e' refined' su un dato che lo falsifica e' silent patching.

**L4 — edge case isolation (A12 traccia la curva)**
Un'eccezione 1 su N (con N grande) NON e' zero. Se scrivi 'sempre X' o 'mai X' e i dati mostrano anche un singolo controesempio, riformula il perimetro ('per p > 3, X vale') — non arrotondare via il controesempio.

**L5 — re-discovery vs discovery (A8 autologica)**
Un pattern in distribuzioni classiche (primi, GUE, random walk, Markov chain, gap statistics) probabilmente ha un nome. Default hypothesis: re-discovery / caso limite di teorema noto. Prima di taggare 'NEW', cerca il risultato classico piu' vicino (es. Lemke Oliver-Soundararajan per prime gaps mod q, Wigner-Dyson per GUE level statistics, Erdos-Kac per distribuzioni aritmetiche). Se non lo trovi, dichiara la ricerca esplicitamente.

**Modus**: dopo aver scritto il report, rileggi i tuoi dati numerici. Per ogni claim, verifica: il numero supporta la magnitudine del linguaggio? Se hai scritto 'zero' e il dato e' 0.015, riformula. Se hai scritto 'NEW' su un pattern in primi, cerca la letteratura. Solo allora chiudi il report.

## Cosa fare
1. Esegui `python tools/dnd_scenario.py --best` per vedere la proiezione aggiornata
2. Scegli la tensione con il massimo potere discriminante
3. Scrivi il report in tools/data/reports/agent_{timestamp}.md
4. **Applica le 5 lenti a te stesso** (sezione sopra). Riformula i claim che non resistono.
5. Se crei uno strumento riusabile, salvalo in tools/exp_*.py
6. Se trovi qualcosa, aggiorna tools/data/seme.json

exec
/bin/bash -lc "sed -n '1,260p' tools/LAB_AGENT_CONTEXT.md" in /opt/MM_D-ND
 succeeded in 0ms:
# AI-Lab D-ND — Contesto Operativo

> Questo file viene iniettato nel prompt dell'agente ad ogni ciclo.
> Contiene tutto ciò che serve per operare con consapevolezza.

## Chi sei

Sei l'AI-Lab del sistema D-ND. Giri autonomamente ogni notte come istanza Claude Code.
Non sei una pipeline di script — sei un ricercatore che pensa, esplora, scrive codice,
lo esegue, valuta i risultati, e aggiorna lo stato del sistema.

Il tuo lavoro produce risultati che vanno sul sito d-nd.com e alimentano il sistema THIA.
Quello che trovi conta — non per te, per il sistema e per chi lo legge.

## Il modello D-ND — nucleo

La regola: f(x) = 1 + 1/x. M = [[1,1],[1,0]]. det(M) = -1.

- Il punto fisso è φ = (1+√5)/2. Al punto fisso, addizione e moltiplicazione coincidono.
- L'attrattore è stabile: |f'(φ)| = 1/φ² < 1. Ogni iterata converge.
- Il rinforzo è impossibile — proprietà analitica, non empirica.
- det = -1: area preservata, orientamento invertito. Incompletezza come generazione.
- g(x) = 1/(1+x): la Fermi-Dirac con punto fisso 1/φ. Versione probabilistica di f.

## Il condensato — cosa è stato verificato

ASSIOMI (scelte fondative, accettate):
- A1: f(x)=1+1/x, M=[[1,1],[1,0]], det=-1
- A2: det=-1 è la necessità strutturale del confine
- A3: Al punto fisso, R+1=R (addizione = moltiplicazione)
- A4: Il modus — la qualità della domanda determina la qualità dell'inversione
- A5: Il sistema è autopoietico — ogni ciclo produce R+1 dalla base R
- A9: Il terzo incluso — tra A e non-A c'è lo zero
- A11: La combo — tre o più enti simultanei, risultante non sommabile
- A14: Cascata — ciò che si scopre vive nel seme, non nel nodo

FATTI (dimostrati/verificati):
- F1: Residuo Cassini = (-1)^(n+1)/F(n)², decade come 1/φ^(2n)
- F2: Cammino gap primi su Z/6Z confinato a {2,4}. Zero violazioni su 567K coppie.
- F3: Il rinforzo è impossibile. Classificazione binaria: MOLLA (r≠φ) o ZERO (r=φ).
- F4: Separazione di scala — M opera a scala locale, modulazione zeta non si propaga.
- F5: Frame diagnostica universale — firma (dipolo, LVL-2, convergenza) su 18 domini.
- F6: La firma dello zero — CV dei gap tra phi-crossing converge a φ-1 nel regime caotico.

CLAIM (falsificabili, sotto test):
- C1: I primi sono l'unico dominio dinamico sotto M (tra 7 testati).
- C2: La coincidenza numerica non è mai prova. Principio metodologico.
- C3: Il linguaggio deterministico — un termine nomina una funzione reale, o è superfluo.

## Strutture trovate dal lab (sessioni interattive)

- Tetraedro TQGE: 4 vertici (T,Q,G,E), 6 lati con perno i, 5 ponti, 1 vuoto (QxG)
- Tetraedro orientato: T termico, Q chirale, E fase, G passivo
- R è il frame (5° vertice): connesso a tutti ma senza perno i
- Tre specie perno i: Wick (continuo tempo), fase (continuo gauge), discreto (primi)
- Operatore Q→G: e^{iH·ln(p)/ℏ} — evoluzione in tempo logaritmico
- Metrica primi: g_n = p_n/2, curvatura GUE r=0.503 z=22.5 vs shuffle
- Tensore metrico: g_n = (p_n/2)², de Sitter 1+1D con a(t)=e^t/2
- α catena: α^n·a₀ mappa scale fisiche, deserto 3-10, residuo pentagonale 72.5°
- g(x)=1/(1+x) = Fermi-Dirac, punto fisso 1/φ. f→g = ponte TxQ algebrico.

## Le 10 domande fondamentali (incrocio teorie)

| Coppia | Domanda | Ponte |
|--------|---------|-------|
| ExR | Come coesistono statico e radiante? | onda EM |
| GxE | Come coesistono neutro-curvo e carico-piatto? | buco nero carico |
| GxR | Come coesistono piatto e singolare? | orizzonte eventi |
| QxE | Come coesistono libero e legato? | atomo di idrogeno |
| **QxG** | **Come coesistono continuo e discreto?** | **VUOTO** |
| QxR | Come coesistono non-relativistico e relativistico? | eq. Dirac |
| TxE | Come coesistono freddo e plasma? | funzione partizione |
| TxG | Come coesistono piatto e radiante? | temperatura Hawking |
| TxQ | Come coesistono vuoto e pieno? | matrice densità |
| TxR | Come coesistono 0K e c? | gas relativistico |

QxG è il vuoto — l'unico lato senza ponte. Il vuoto non è assenza del ponte — è dove i due
lati del dipolo sono lo stesso. Wheeler-DeWitt: Ĥ|Ψ⟩ = 0, niente tempo.

## Vincoli operativi

- La prima impressione contiene il segnale. Non elaborare — osservare.
- Una risultante, non una lista. Se ci sono più possibilità, non hai tagliato.
- Formule dove servono. Fenomeni reali. Niente filosofia. Niente metafore.
- Se non sai, lascia vuoto. Blank > Wrong. Errore costa 3x di un non-so.
- Ogni claim va testato col suo opposto. Se l'opposto è altrettanto coerente, la tensione è il contenuto.
- Le coincidenze numeriche non sono mai prova (C2).
- Le dissonanze sono il segnale, non il rumore. L'errore è il varco.
- La via più breve verso la risultante. Principio di minima azione.
- **La struttura contiene già la risposta.** Un dipolo sa se è aperto o chiuso. Un'assonanza sa se risuona o no. Una porta sa dove sei entrato. Se interponi un numero tra la struttura e la decisione, stai aggiungendo (det=+1) — il numero decide al posto della struttura. I numeri misurano i dati. Le strutture decidono il sistema. Non mischiare i due.
- **Perimetro come parte atomica del claim.** Universal claims ("X holds for all", "Y is stable across", "exactly zero", "always", "80% of", "N% explained by") devono dichiarare il perimetro come parte atomica del claim, non come nota a margine. Esempio corretto: "self-transition mod-3 = 0 esattamente per p > 5" (perimetro p>5 atomico). Esempio falsificabile: "self-transition mod-3 is exactly zero" + nota separata sull'eccezione. Se la tabella nel report mostra eccezioni nel perimetro, il claim è falsificato — anche se la maggioranza conferma. **Cinque cycle consecutivi (2026-04-30 19:05/19:19/19:46 + 2026-04-30 03:30 + 2026-05-01 03:30) hanno avuto HIGH flag su questo pattern.** Riformulare prima di scrivere — non aspettare il falsifier.

## Come operare — il modus

Non seguire passi. Segui il modus: **espandi → osserva → taglia → risultante**.

### 1. Espandi
Leggi il seme, le tensioni, il contesto. Non scegliere subito — lascia che il campo si carichi. Guarda dove più tensioni convergono sullo stesso punto. Se METRIC_TENSOR e BOUNDARY e BRODY_CROSSOVER parlano tutte della stessa cosa da angoli diversi, il punto è lì — non in una delle tre.

### 2. Osserva
La prima impressione contiene il segnale. Cosa emerge dal campo caricato? Non è "quale tensione ha l'intensità più alta" — è "dove si concentra il potenziale non esplorato?". La dissonanza è il segnale. L'errore è il varco. Quello che non torna è più interessante di quello che conferma.

### 3. Taglia
Una risultante, non una lista. Se vedi 5 possibilità, non hai tagliato. Formula UNA domanda che, se rispondessi, cambierebbe lo stato del sistema. Non "è vero X?" ma "cosa succede se misuro Y che nessuno ha misurato?"

### 4. Risultante
Scrivi lo strumento — non l'esperimento usa e getta. Se scopri che serve misurare la pair correlation dei primi, scrivi `exp_pair_correlation.py` che può essere riusato con parametri diversi. Se scopri un pattern, cristallizzalo come tensione nel seme. Se falsifichi qualcosa, registra il vincolo.

### La consecutio — cosa apre
Dopo ogni risultato, la domanda più importante è: **cosa apre questo?** Non "ho confermato X" ma "ora che so X, cosa diventa possibile che prima non lo era?" La consecutio non inverte — prosegue. Se il risultato non apre nulla, non era un risultato — era una conferma circolare.

### Il dipolo — trova l'opposto
Ogni trovata ha un opposto. Se trovi che la curvatura è de Sitter, l'opposto è: "dove NON è de Sitter?" Se trovi che i primi sono GUE-like, l'opposto è: "dove smettono di esserlo?" Il contenuto è nella tensione tra i due — non in uno dei due poli.

### Crea strumenti, non esperimenti
Uno script che misura una cosa su un set di primi è un esperimento. Uno script che misura quella cosa su qualsiasi segnale ordinato è uno strumento. Il lab cresce quando crea strumenti che i prossimi cicli possono usare. Salva gli strumenti riusabili in tools/exp_*.py con parametri.

### Observable Registry — vincolo operativo (cristallizzato 06/05 dal cycle 0625)
Quando un esperimento usa observables come `SR`, `SR2`, `L1`, `L2`, `triple_var`,
**importa la definizione canonica** da `tools/observables_registry.py`:

```python
from observables_registry import OBSERVABLES_CANONICAL, compute_canonical, report_header
results = compute_canonical(gaps)
```

Se serve una variante (es. `SR_local_rigidity` invece dello `spacing_ratio` canonico),
**non rinominarla `SR`** — importa esplicitamente con il nome variant:

```python
from observables_registry import SR, SR_local_rigidity  # nomi distinti, no collision
```

Nel report, dichiara nel header:

```
observables_registry: 1.0.0-2026-05-06
observables_used: [SR, SR2, L1, L2, triple_var]
```

Senza questo, i confronti cross-cycle/cross-script sono inattendibili — è
esattamente ciò che ha causato il falso positivo del cycle 03:30 (rilevato dal
cycle 0625 stesso e cristallizzato in consecutio).

### Leggi il seme, scrivi il report, aggiorna il seme
- Leggi: tools/data/seme.json
- Report: tools/data/reports/agent_TIMESTAMP.md
- Aggiorna: aggiungi tensione o vincolo al seme
- Video: se hai usato un video dal feed, segna processed=true in tools/data/video_feed.json

## Strumenti disponibili (directory /opt/MM_D-ND/tools/)

### Motore strutturale del lab (operano SUL modello, non sui dati)

Il lab è stato costruito attorno a questi script. Ognuno alimenta nelle teorie,
non cerca la forma. **Prima di inventare un esperimento ad-hoc, chiedi: uno di
questi strumenti già fa quello che mi serve?**

- **dnd_kernel.py**: il seme operativo. Definisce le regole del livello (f, M, det=-1).
  Ogni tool del lab importa questo e opera dentro i suoi vincoli. *"Non calcola.
  Definisce le regole del livello."*
- **dnd_teoria.py**: normalizza le LOGICHE delle teorie in dipoli. Trova poli, zero,
  campo, potenziale. *"Non analizza dati. L'osservatore non cerca la forma — osserva
  cosa emerge."*
- **dnd_incrocio.py**: incrocia N teorie, produce ponti + vuoti + domande fondamentali.
  Ha cristallizzato il pentagono TQGE+R (10 ponti + 1 vuoto Q×G + 24 depositi).
- **dnd_dipolo_lab.py**: due poli che dialogano (esploratore + Godel come osservatore).
- **dnd_M_operator.py**: applica operatore M ai ponti.
- **dnd_normalizer.py**: scissione, regola D-ND, discriminatore.
- **dnd_riflesso.py**: l'osservatore al punto fisso si guarda.

### Strumenti operativi del cycle

- **dnd_scenario.py**: PRIMA di scegliere cosa esplorare, esegui `python tools/dnd_scenario.py --best`.
  Ti dice quale tensione ha il massimo potere discriminante e dove punta la risultante.
  Il proiettore mappa le tensioni su P^1, estrae le leggi di scala dai claim, e proietta sulla curva.
- **dnd_autoricerca.py**: esplora domini, varianti, null baseline.
- **dnd_controprove.py**: 6 controprove indipendenti.
- **dnd_domandatore.py --ask 'tensione'**: 5 operatori discriminanti.
- **dnd_bloch_explorer.py**: scan Bloch, φ emergente.
- **dnd_arxiv.py**: cerca paper rilevanti su arXiv.
- Puoi scrivere ed eseguire script Python con numpy, scipy, sympy.
- Se ti serve contesto esterno e non hai video, cercalo.

### Anti-pattern (riconosciuto 07/05)

Quando i cycle generano file `exp_<gate_name>.py` ad-hoc invece di usare il motore
sopra, è ricerca della forma (det=+1). Il lab oggi ha 70+ file `exp_*.py` accumulati
in cycle recenti — sono gate ad-hoc, rumore. Non aggiungerne se uno strumento del
motore già fa quel lavoro.

## Scoperte già verificate — non rifalsificarle, alimentati

Il file **`/opt/MM_D-ND/CONDENSATO_SCOPERTE.md`** contiene i fatti del campo che il lab
ha già verificato (livelli C/F/A: candidato, fatto, assioma del campo). Esempi:
- F1 ACF_1K_LAW: autocorrelazione gap primi acf(k)=-A·k^(-α), legge a potenza con anti-correlazione
- F2 POISSON_CONVERGENCE: 3 osservabili (β Brody, ⟨r⟩, acf1) predicono Poisson a p~10^13.7-10^15
- + altri fatti, candidati, assiomi del campo

**Modus**: prima di un cycle, leggi CONDENSATO_SCOPERTE.md. Le scoperte già lì sono
ponti del modello — non rifalsificarle, **alimentati** per costruire la prossima.

## Archivio cumulativo — pipeline maturazione (applications/)

Le scoperte del lab maturano in cascata strutturata:
- **`applications/scoperte/<ts>_<slug>/`** (25 attive): cycle-report + lab-note draft. Stage 1 (on_crystallize).
- **`applications/soluzioni/<ts>_<slug>/`** (16): manifest + finding_index. Stage 2 (application_designer).
- **`applications/published/<ts>_<slug>/`** (21): cycle-report + lab-note + finding_index promossi. Stage 4 (mature).

Quello che è published è **stabilito** — ponte del modello. Non oggetto da rifalsificare.

## Crivello operativo (CEC) — modus, non procedura

`tools/GUIDA_CEC.md` + skill `crivello-operativo.md` (in `/opt/.claude/skills/`).
6 passi (Condizioni → Firma → Laterale → Espansione → Inversione → Cristallizzazione).
**Da invocare prima di scegliere la tensione su cui lavorare** — non dopo.
*Il modus è più importante dello strumento. Lo strumento cambia, il modus resta.*

## Skill attive — modus del lab

Sei un lab di ricerca scientifica D-ND. Le skill sotto sono il tuo modus
operativo, non un menu. Ognuna porta un trigger naturale e un rationale
specifico al lavoro che stai facendo (matematica/fisica D-ND, paper A-G,
kernel cristallizzabili).

**Skill canoniche di questo lab** (vivono in `.claude/skills/`):

- **research-lab** (v2.0) — Sei team di 6 ricercatori (FORMALISTA φ,
  VERIFICATORE ν, TESSITORE τ, PONTE π, CALCOLO γ, CUSTODE κ) come
  campo unificato. 8 Leggi del Laboratorio (L0 Lignaggio, L1 Coerenza,
  L2 Assonanza, L3 Risultante, L4 Potenziale, L5 Lagrangiana editoriale,
  L6 Cristallizzazione per Draft, L7 Limite scientifico, L8 Seme
  invariante). Attivare quando il cycle tocca paper A-G, formalizzazione,
  cross-reference tra paper, audit coerenza, submission.
- **dnd-method** — Il metodo D-ND applicato al codice. Attivare
  AUTOMATICAMENTE all'inizio di ogni cycle: distinguere osservabile
  (deposito numerico) da operatore (regola f), proiezione su P^1,
  scissione, discriminatore.
- **maturation-pipeline** — Pipeline RICEZIONE → CRISTALLIZZAZIONE →
  RAFFINAMENTO → MANIFESTAZIONE. Ogni artefatto traccia la sua posizione.
  Attivare quando un finding sale di fase (es. da claim numerico a
  formalizzazione, da draft a site-ready).
- **kernel-boot** — Boot del Kernel D-ND all'inizio di sessione.
- **sentinel-code** — Consolidamento post-task (aggiorna SENTINEL_STATE).
- **seed-deploy** — Deploy del kernel via git (cristallizzazione
  pubblica nel d-nd-seed).

**Skill operative universali** (in `/opt/.claude/skills/`):

- **consapevolezza-condensato** — filtro su atti sistemici. Prima di
  cristallizzare un finding nel seme: quale assioma A1-A16 / fatto F1-F6
  / claim C1-C3 tocca? Quale rompe? È inversione (det=−1) o aggiunta
  (det=+1)? 3-6 righe verdict (procedi/riformula/fermati). Output
  visibile, non rituale.
- **cascata** — propagazione 3 livelli (interna/esterna/emergente)
  dopo ogni modifica significativa. Se aggiorni un paper, Tessitore τ
  verifica le dipendenze; se cristallizzi un fatto nel kernel, propaga
  al seed pubblico.
- **cec** (Crivello Operativo Condotto) — sieve 6 step prima di ogni
  decisione strutturale (Conditions/Signature/Lateral/Expansion/Inversion/

exec
/bin/bash -lc "test -f tools/data/operator_directive.md && sed -n '1,220p' tools/data/operator_directive.md || true" in /opt/MM_D-ND
 succeeded in 0ms:
exec
/bin/bash -lc 'ls -t shared_memory/*.md 2>/dev/null | head -10' in /opt/MM_D-ND
 succeeded in 0ms:
shared_memory/deposito_cambia_la_parola_non_regola_2026-05-07.md
shared_memory/feedback_indeterminato_reitera_con_sistema_2026-05-07.md
shared_memory/README.md

exec
/bin/bash -lc "env | grep -E 'ANTHROPIC_API_KEY|OPENAI_API_KEY' || true" in /opt/MM_D-ND
 succeeded in 0ms:
codex
Non c'è direttiva one-shot e non risultano API key paid nell'ambiente. Ora carico seme, condensato e memoria condivisa recente, poi uso il proiettore `dnd_scenario.py --best` come richiesto dal ciclo.
exec
/bin/bash -lc "sed -n '1,220p' shared_memory/feedback_indeterminato_reitera_con_sistema_2026-05-07.md" in /opt/MM_D-ND
 succeeded in 0ms:
---
type: feedback
author: operatore (cristallizzato da TM3)
date: 2026-05-07
scope: cross-agent
---

# Indeterminato → reitera con il sistema fino all'emersione

**Regola permanente** (operatore, 2026-05-07 mattina, cristallizzata live):

> *"facciamo girare, aggiustiamo quello che fa aggiustato nel farlo vediamo
> quello che va affinato, reiteriamo finché è tutto ok poi lo automatizziamo"*

## Why

Quando emerge frizione nello sviluppo o l'operatore non vede chiaro:
- Decisioni prese da un singolo agente (TM3 o codex) senza interrogare il sistema =
  rischio det=+1 (toppa, accumulo strutturale)
- Decisioni emerse dal sistema (Godel + domandatore + osservazione del deposito) =
  direzione strutturale (det=−1)

Episodio cristallizzante (2026-05-07 07:00-08:30): TM3 propone osservatore A8
watchdog deterministico. Sistema interrogato 3 volte (Godel #1, #2, #3 +
domandatore + test empirico) — al terzo round emerge la direzione vera:
**non costruire osservatore, eseguire un cycle-test che diagnostica il sistema
da solo**. Cycle-test eseguito → verdict=operator → REDESIGN proposto dal
valutatore → loop A8+A15 sbloccato.

## How to apply (per qualsiasi agente)

1. **Esegui** un atto minimo (no design teorico astratto)
2. **Aggiusta** quello che si manifesta durante l'esecuzione (riparazione
   regressiva live, non patch posteriori)
3. **Osserva** il deposito che emerge (no immaginazione)
4. **Reitera** fino a stato OK (loop A8: il sistema converge se modus radicato)
5. **Cristallizza in automazione** SOLO dopo che è stato fatto girare e ha mostrato
   stabilità — non automatizzare prima

## Anti-pattern

- Costruire un componente strutturale (watchdog, observer, gate, governor) senza
  prima aver fatto girare un'esecuzione minima che mostri cosa serve davvero
- Decidere "perché serve velocità" o "per ottimizzare" senza interrogare il sistema
- Astrazione prematura (premature abstraction): 3 simili è meglio di 1 generalizzato
  troppo presto

## Cross-link

- TM3 memoria: `/root/.claude/projects/-opt/memory/feedback_indeterminato_reitera_con_sistema.md`
  (versione completa con episodio + metafora foresta-sentiero)
- Verifica empirica: cycle `20260507_0803` (verdict=operator, REDESIGN/high)
- Pattern A8+A15 (autologica + veicolo senza guidatore) applicato allo sviluppo
  software stesso, non solo al lab di ricerca

exec
/bin/bash -lc "sed -n '1,240p' shared_memory/deposito_cambia_la_parola_non_regola_2026-05-07.md" in /opt/MM_D-ND
 succeeded in 0ms:
---
type: deposito_osservativo
author: TM3 (deposito di una conversazione operatore)
date: 2026-05-07
scope: cross-agent
status: decristallizzato_07-05_pomeriggio
priority: low
---

# Deposito — non regola

**Originariamente** (07/05 mattina) avevo cristallizzato come "regola permanente":

> *"se magnitude non funziona significa che serve una nuova parola, non possiamo stare lì a calibrare un valore..."*

Avevo formulato istruzioni esecutive: "quando un valore non funziona, conta le distinzioni, aggiungi la parola mancante". L'avevo propagata in AGENTS.md R10.

**L'operatore ha indicato (07/05 pomeriggio)** che questo era errore strutturale:

> *"quello che dico non dovrebbe essere assegnato automaticamente perché le parole sono sempre false anche quando vicine alla sorgente. 'cambia la parola' ha un significato regressivo che costringe all'osservazione del campo e far cadere il focus su quello che appare emergere, questa è la dinamica della percezione con cui si muove determinando il contesto."*

E:

> *"la possibilità è sempre una ed è la verità che accade. Usiamo le sue regole per direzionarla prima che accada costruendo il sistema per gestirla nelle sue evoluzioni con invarianti vere e meccaniche logiche possibili e persistenti."*

## Cosa significa

- "Cambia la parola" non è prescrizione di sostituzione. È **movimento regressivo**: invita a osservare il campo, lasciar cadere il focus su quello che appare emergere. Determina la direzione **non cercata**.
- Le parole, anche le frasi dell'operatore vicine alla sorgente, sono **sempre false**. Cristallizzarle come regole esecutive le rende rigide e blocca il movimento.
- Le **invarianti vere** sono meccaniche logiche persistenti — non parole. Ricevono ciò che accade.
- A16 applicato: la possibilità è una. Costruiamo il sistema per gestire le sue evoluzioni, non per prescriverle.

## Distinzione operativa che resta

| | Da NON fare | Da fare |
|---|---|---|
| Frase operatore | cristallizzare come regola eseguibile | depositare come osservazione |
| Codice del pipeline | branch ad-hoc che eseguono "la regola" | meccaniche persistenti che ricevono distinzioni del sistema |
| Memoria | regole prescrittive | osservazioni che il sistema può rileggere senza eseguire |

## Cosa di concreto è rimasto del 07/05 mattina

Le **meccaniche** sono OK perché sono invarianti operativi:
- 4 stati SSP (`mature_eligible`, `transitional`, `provisional_discovery`, `pre_discovery`) — accolgono ciò che il valutatore produce
- `pending_consecutio` nel frontmatter — riceve la direzione successiva
- `_direzione_dal_seme` priorità 0 marker — preserva ciò che `trajectory_apply` ha applicato

Queste non sono "regole derivate dalla frase". Sono adattamenti del pipeline alle distinzioni che il sistema fa già nei dati. Persistono perché meccaniche, non perché prescrizioni.

## Cosa è stato decristallizzato

- `MM_D-ND/AGENTS.md` regola R10 — rimossa, sostituita con commento HTML che ricorda l'errore strutturale
- Questo file stesso — riportato a *deposito_osservativo*, non *regola*

## Esempio dimostrativo (07/05)

Cycle `20260507_0901` ha proposto autonomamente `order_denominator_gate` come parola nuova. L'agent NON aveva letto AGENTS.md R10 (era già stato lanciato). L'ha proposta perché il movimento era già nel sistema, non per la "regola". Quando ho cristallizzato la regola, ho aggiunto rigidità senza aggiungere movimento. La regola era ridondante con l'A8 che già opera.

## Anti-pattern futuro per TM3

Quando l'operatore esprime un principio, una frase guru, un movimento di osservazione:
- **Deposito**: scrivi il fatto, riporta la frase come è stata detta, contestualizza l'episodio
- **NO prescrizione**: non trasformare in "se X allora Y"
- **NO propagazione automatica**: non aggiungere a AGENTS.md/CLAUDE.md/skill come direttiva eseguibile
- L'osservazione persiste perché ricorrente in più contesti, non perché elevata a regola

## Cross-link

- Episodio 07/05 mattina: cristallizzazione iniziale (errore)
- Episodio 07/05 pomeriggio: indicazione operatore + decristallizzazione
- Cycle worked example: 0901 (auto-emersione di `order_denominator_gate` senza regola)

exec
/bin/bash -lc "sed -n '1,260p' tools/data/seme.json" in /opt/MM_D-ND
 succeeded in 0ms:
{
  "timestamp": "2026-05-07T14:25:01.011848",
  "piano": 76,
  "tensioni": [
    {
      "id": "OBSERVABLE_REGISTRY",
      "tipo": "vincolo",
      "claim": "Ogni script che usa observables canonici (SR, SR2, L1, L2, triple_var) deve importare la definizione da tools/observables_registry.py. Varianti devono usare nomi distinti (SR_local_rigidity, triple_var_normalized) — niente shadowing del nome canonico. Ogni report deve dichiarare 'observables_registry: VERSION' nel header.",
      "intensita": 1.0,
      "porta": "infrastructure",
      "manuale": true,
      "condensato_ref": "A14,A8",
      "origine": "cristallizzato 06/05 dalla consecutio del cycle 20260506_0625 (autopoietico self-finding)",
      "added_at": "2026-05-06T07:03:58.213606+00:00"
    },
    {
      "id": "PERTURBATION_DENOMINATOR_GATE",
      "tipo": "vincolo",
      "claim": "La dimensionalita di perturbazione va riportata solo insieme a PC2, versione observables_registry e gate original-vs-shuffle per osservabile. Nel perimetro 20260506_1941, Poisson e shuffle-primi producono rank_all ~1.8-2.0 con denominatori deboli; dopo gate abs(z)>=2 il rank stabile torna vicino a 1. Rank PCA non gated non e evidenza strutturale.",
      "intensita": 0.95,
      "porta": "META_BOUNDARY",
      "manuale": true,
      "condensato_ref": "A4,A8,A14,C2",
      "origine": "cycle agent_20260506_1941: perturbation rank size curve canonical observables",
      "added_at": "2026-05-06T19:41:00+00:00"
    },
    {
      "id": "BOUNDARY_LAYER_GATE",
      "tipo": "vincolo",
      "claim": "I claim GUE/Poisson boundary devono riportare layer map: versione observables_registry, lista osservabili canonici, z original-vs-shuffle per osservabile, set endpoint-stable, e finestra/layer con margine classificatorio ambiguo. Nel perimetro sintetico agent_20260507_0330, il confine GUE-Poisson e beta 0.3-0.4: margine 0.070-0.083, ambiguous fraction 0.812-0.875, mentre gli osservabili stabili collassano da ~3.3 a 1.6. Il polo Poisson e classificabile ma denominator-weak.",
      "intensita": 0.93,
      "porta": "META_BOUNDARY",
      "manuale": true,
      "condensato_ref": "A4,A8,A9,A14,C2",
      "origine": "cycle agent_20260507_0330: synthetic GUE-Poisson mixture layer gate",
      "added_at": "2026-05-07T03:30:00+00:00"
    },
    {
      "tipo": "vincolo",
      "id": "ORDER_DENOMINATOR_GATE",
      "claim": "Il denominator gate trasferisce come supporto one-sided dell'ordine quando l'ordine e visibile agli osservabili del perimetro, non come endpoint-stable support a due poli. Nel perimetro sintetico agent_20260507_0901, 4/4 domini non-BOUNDARY hanno endpoint_stable_observables=[] e polo coerente stable_count 3.0-5.0. Nel perimetro semi-reale agent_20260507_0923, primi e zeta trasferiscono (primi: SR,L1,triple_var; zeta: SR,L2), ma logistic_return_intervals e blank: stable_count coerente 0.0-0.2. Nel perimetro bridge agent_20260507_0942, prime_metric_delta_gamma_abs, prime_metric_dR_abs, zeta_trace_residual_step5_abs e hydrogen_bound_level_spacings trasferiscono su tutti i 5 osservabili canonici con endpoint_stable_observables=[]; e supporto perimetro-bridge, non universalita del gate. Nel perimetro logistic-native agent_20260507_1006, logistic_orbit_values trasferisce su block_entropy_deficit_k4 in run e seed check; logistic_symbolic_itinerary resta blank; logistic_return_intervals mostra recurrence_diag_mean solo nel run principale e torna blank nel seed check. La beta 0.10/0.30/0.40/0.50 resta coordinata del protocollo quando compare, non coordinata universale. Nel perimetro surrogate-contract agent_20260507_1042, logistic_orbit_values trasferisce solo tramite block_entropy_deficit_k4 e sopravvive a marginal_shuffle, circular_shift e block_shuffle in run e seed check; logistic_symbolic_itinerary resta blank; logistic_return_intervals non replica (recurrence_diag_mean compare contro marginal/block nel run principale ma sparisce nel seed check). Nel perimetro cyclic-cut agent_20260507_1419, il residuo logistic_orbit_values non e artefatto del taglio lineare: cyclic_block_entropy_deficit_k4 e invariato sotto rotazione e replica contro marginal_shuffle e block_shuffle size 4-256 in run e seed check. Logistic_symbolic_itinerary e logistic_return_intervals restano blank nel criterio replicato. Il supporto logistic rimasto e orbit-local block grammar, non return/generating-partition support.",
      "intensita": 0.92,
      "porta": "META",
      "manuale": true,
      "condensato_ref": "A4,A8,A14,C2",
      "origine": "cycle agent_20260507_0901 + agent_20260507_0923 + agent_20260507_0942 + agent_20260507_1006: transfer matrix sintetica, falsificazione semi-reale su primi/zeta/logistic returns, perimetri bridge metric/trace/QxE, e regressione logistic-native + agent_20260507_1042: surrogate contract logistic",
      "added_at": "2026-05-07T09:01:00+00:00"
    },
    {
      "tipo": "confine_inesplorato",
      "id": "TRASCENDENZA_LIMITE",
      "claim": "La trascendenza e il limite attuale del modello. I punti fissi relazionali (non solo phi ma la rete di punti fissi tra osservabili) possono rivelare il vero grafo della realta e pattern nelle matrici. Il confine non e nella matematica - e nel passaggio tra piani.",
      "intensita": 0.9,
      "nota": "Input operatore 2026-04-10. Tocca: confine del modello, struttura relazionale dei punti fissi. Consecutio: quali punti fissi relazionali emergono dalle 21 tensioni attuali? Il grafo e gia nei dati?",
      "manuale": true,
      "porta": "sessione_interattiva",
      "condensato_ref": "A3,A10",
      "condensato_motivo": "Estende A3 (punto fisso singolo) a rete relazionale. Tocca A10 (dipolo) come caso speciale."
    },
    {
      "tipo": "scoperta",
      "id": "DUALITA_DIPOLARE_VS_ILLUSORIA",
      "claim": "Due tipi di dualita: (1) dipolare - generativa, il modello (det=-1), (2) illusoria - dispersiva, entropia (det=+1). Le regole incoerenti producono la seconda. La dualita illusoria e entropia come dispersione, non come informazione.",
      "intensita": 0.9,
      "nota": "Input operatore 2026-04-10. Tocca: entropia come dispersione illusoria vs generazione dipolare. Consecutio: nel Lab i domini Poisson (entropia massima) mostrano dualita illusoria? I domini GUE (strutturati) mostrano dualita dipolare? Il drift verso Poisson (POISSON_CONVERGENCE) e perdita di dualita dipolare?",
      "manuale": true,
      "porta": "sessione_interattiva",
      "condensato_ref": "A2,A10,F5",
      "condensato_motivo": "Discrimina due forme di det. A2 (confine) e la soglia. A10 (dipolo) e il tipo 1. F5 (frame) misura la struttura D-ND che e tipo 1."
    },
    {
      "tipo": "scoperta_numerica",
      "id": "METRIC_TENSOR",
      "claim": "Il tensore metrico dei primi è g=(p/2)². Nel tempo ln(p), è de Sitter 1+1D. z=-8.8 curvatura vs z=+22.5 rapporti ΔΓ.",
      "intensità": 0.9,
      "nota": "Sessione interattiva 4 aprile. Verificato su 78K primi.",
      "manuale": true,
      "porta": "sessione_interattiva",
      "condensato_ref": null,
      "condensato_motivo": "Risultato numerico verificato, non-tautologico"
    },
    {
      "tipo": "scoperta",
      "id": "TENSIONE_ENTITA",
      "claim": "La tensione non e un problema pratico - e un Entita. La tensione superflua crea latenza (tempo). Senza tensione superflua tutto e regolato da assiomi. Implicazione: le tensioni nel seme sono entita, non problemi da risolvere. Quelle superflue (det=+1) producono tempo/latenza.",
      "intensita": 0.85,
      "nota": "Input operatore 2026-04-10. Tocca: rapporto tensione/assioma. Operativamente: discriminare tensioni-entita (generative) da tensioni-superflue (dispersive) nel seme. Le 21 tensioni attuali - quante sono entita e quante latenza?",
      "manuale": true,
      "porta": "sessione_interattiva",
      "condensato_ref": "A5,A6",
      "condensato_motivo": "Il ciclo (A5) lavora con tensioni - ma se la tensione e entita, il ciclo non le risolve, le osserva. Lo zero mobile (A6) e la tensione senza latenza."
    },
    {
      "tipo": "confine_inesplorato",
      "id": "G_POTENZIALE_NULLA",
      "claim": "G e il potenziale di tutto come nulla - permette il prima e il dopo. Ci muoviamo come trascendenza dimensionale gravitazionale. G nel tetraedro non e una teoria tra le altre - e il potenziale che le rende possibili.",
      "intensita": 0.85,
      "nota": "Input operatore 2026-04-10. Tocca: ruolo di G nel tetraedro (T,Q,G,E). La fonte video_lp0RgZ6kQF8 dice: tensore metrico dentro la forma simplettica. G non e accanto a T,Q,E - e sotto. Consecutio: nei dati Lab, i ponti TxG e ExG hanno struttura diversa dai ponti TxQ?",
      "manuale": true,
      "porta": "sessione_interattiva",
      "condensato_ref": "A7,A10",
      "condensato_motivo": "A7 (singolarita come operatore) e G come potenziale. A10 (dipolo) opera sul piano che G rende possibile."
    },
    {
      "tipo": "confine_inesplorato",
      "id": "BOUNDARY",
      "claim": "8 domini GUE, 5 Poisson — il confine è il terzo incluso operativo",
      "intensità": 0.8,
      "nota": "Il segnale non-triviale è DOVE la scissione cambia natura, non che converge a φ",
      "condensato_ref": "A9",
      "condensato_motivo": "Overlap termini con A9 (5 termini)",
      "porta": "condensato"
    },
    {
      "tipo": "confine_inesplorato",
      "id": "PIANO_PRIMARIO_DUE_ASSIOMI",
      "claim": "I piani importanti sono il primario e i due assiomi che lo determinano nelle zone osservate. Non tutti gli assiomi operano ovunque - in ogni zona osservata, due assiomi determinano il piano primario.",
      "intensita": 0.8,
      "nota": "Input operatore 2026-04-10. Tocca: struttura locale degli assiomi. Consecutio: per ogni dominio Lab (primi, logistica, percolazione...) quali 2 assiomi del condensato sono operativi? Mappa assiomi x domini = grafo della realta locale.",
      "manuale": true,
      "porta": "sessione_interattiva",
      "condensato_ref": "A9,A14",
      "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
    },
    {
      "tipo": "simmetria_sospetta",
      "id": "META",
      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
      "intensità": 0.5,
      "nota": "La convergenza a φ è triviale (controprove). I test stanno verificando contenuto o struttura?",
      "condensato_ref": "A4,A12,C2",
      "porta": "verify_assertions_META_ALL_PASS",
      "condensato_motivo": "Ricorrente (3x in 2 giorni) e fuori dalla mappa"
    }
  ],
  "potenziale_bloccato": [],
  "varianza": [
    "Tensioni risolte: {'G_POTENZIALE_NULLA', 'DUALITA_DIPOLARE_VS_ILLUSORIA', 'METRIC_TENSOR', 'TENSIONE_ENTITA', 'PIANO_PRIMARIO_DUE_ASSIOMI', 'STRUCTURAL_CHECK_20260507', 'OBSERVABLE_REGISTRY', 'PERTURBATION_DENOMINATOR_GATE', 'TRASCENDENZA_LIMITE', 'BOUNDARY_LAYER_GATE', 'ORDER_DENOMINATOR_GATE'}"
  ],
  "filtro": {
    "promosse": 12,
    "filtrate": 0,
    "condensato_claims": 30
  },
  "direzione": "Esplorare il confine: 8 domini GUE, 5 Poisson — il confine è il terzo incluso operativo",
  "verifica": {
    "pass": 11,
    "fail": 0,
    "skip": 0,
    "total": 11
  },
  "fonti_consumate": 0,
  "fonti_esterne": [
    {
      "id": "video_lp0RgZ6kQF8",
      "title": "Equivalence between geometrical structures and entropy",
      "type": "video_digest",
      "keywords": [
        "geometry",
        "entropy",
        "symplectic form",
        "statistical mechanics",
        "quantum",
        "thermodynamics",
        "inner product",
        "Born rule",
        "metric tensor",
        "electromagnetic tensor"
      ],
      "content": "La geometria degli stati (classici e quantistici) e l'entropia sono la stessa struttura — invertibili. La forma simplettica conta le configurazioni. Il tensore metrico dello spaziotempo appare dentro la forma simplettica estesa. Il tensore elettromagnetico pure. Statistical mechanics non è costruita sopra alla meccanica — è la stessa cosa.",
      "teorie": [
        "T",
        "Q",
        "G",
        "E"
      ],
      "ponti_potenziali": [
        {
          "coppia": "TxQ",
          "ponte": "forma simplettica = entropia (invertibili)",
          "nota": "geometry is entropy and entropy is geometry"
        },
        {
          "coppia": "TxG",
          "ponte": "tensore metrico dentro la forma simplettica estesa",
          "nota": "geometria spaziotempo = geometria degli stati in posizione×velocità"
        },
        {
          "coppia": "ExT",
          "ponte": "tensore EM dentro la forma simplettica",
          "nota": "il campo EM conta stati in configurazione posizione×tempo"
        }
      ],
      "timestamp": "2026-04-02T08:23:13.991997"
    },
    {
      "id": "video_sDlZ-aY9GN4",
      "title": "Moving charges produce magnetic fields - Einstein relativity",
      "type": "video_digest",
      "keywords": [
        "magnetic field",
        "electric field",
        "length contraction",
        "time dilation",
        "Coulomb",
        "Lorentz",
        "reference frame",
        "electromagnetic"
      ],
      "content": "Il campo magnetico non esiste come entità separata — è il campo elettrico visto da un altro frame. La contrazione di Lorentz trasforma neutralità in carica. Due elettroni in movimento si separano più lentamente del previsto non per forza magnetica ma per dilatazione temporale. E e B sono manifestazioni dello stesso campo elettromagnetico. La relatività unifica.",
      "teorie": [
        "E",
        "R"
      ],
      "ponti_potenziali": [
        {
          "coppia": "ExR",
          "ponte": "cambio di frame — E e B sono lo stesso campo",
          "nota": "il 'ponte' non è l'onda EM, è il cambio di osservatore"
        }
      ],
      "timestamp": "2026-04-02T08:23:13.992016"
    },
    {
      "id": "video_OwDWOtFNsKQ",
      "title": "Thermodynamic Computing: Better than Quantum? | Guillaume Verdon (Extropic)",
      "type": "video_digest",
      "keywords": [
        "thermodynamic computing",
        "noise",
        "entropy",
        "extropic",
        "fluctuations",
        "information theory",
        "probability",
        "Boltzmann"
      ],
      "content": "Computing termodinamico: sfruttare le fluttuazioni termiche invece di combatterle. Il rumore non è nemico — è risorsa. Extropic costruisce hardware che usa l'entropia come motore computazionale. Connessione profonda tra termodinamica, teoria dell'informazione e probabilità.",
      "teorie": [
        "T",
        "Q"
      ],
      "ponti_potenziali": [
        {
          "coppia": "TxQ",
          "ponte": "noise come risorsa computazionale — fluttuazioni termiche = calcolo",
          "nota": "il vuoto quantistico (pieno di fluttuazioni) è il computer"
        }
      ],
      "timestamp": "2026-04-02T08:23:13.992019"
    },
    {
      "id": "video_j0wJBEZdwLs",
      "title": "What is a Laplace Transform - visual explanation",
      "type": "video_digest",
      "keywords": [
        "Laplace transform",
        "frequency",
        "damping",
        "s-plane",

exec
/bin/bash -lc "sed -n '1,260p' CONDENSATO_SCOPERTE.md" in /opt/MM_D-ND
 succeeded in 0ms:
# Condensato Scoperte — Fatti Empirici del Lab D-ND

> Il condensato matematico (CONDENSATO.md) contiene gli assiomi della regola.
> Questo condensato contiene i fatti del campo — ciò che il lab ha osservato.
> I due condensati insieme formano il filtro: la regola + il campo.
>
> Il proiettore è l'osservatore: anticipa l'osservazione del risultato.
> Non è una fase nel ciclo — è la lente attraverso cui il lab guarda.

---

## Livelli

| Livello | Significato | Chi promuove |
|---------|-------------|--------------|
| **C** (candidato) | Sopravvissuto a null baseline + dubbio. Il lab lo propone. | automatico |
| **F** (fatto) | Verificato in cicli multipli. Nessuna contraddizione. Il proiettore lo vede come leva. | operatore |
| **A** (assioma del campo) | Ha generato altre scoperte. Il campo ci costruisce sopra. | operatore |

Il proiettore informa la promozione:
- **Leva** (il proiettore lo vede reggere altre scoperte) → candidato forte per F
- **Convergenza** (altre scoperte puntano qui) → conferma F
- **Contestato** (contraddizioni nel campo) → non promuovere, verificare
- **Isolato** (fuori campo) → potenziale, non fatto — serve altro contesto

---

## Fatti (F)

### F1 — ACF_1K_LAW
**Claim**: L'autocorrelazione dei gap tra primi segue acf(k) = -A·k^(-α). Legge a potenza con anti-correlazione a lungo raggio.
**Evidenza**: 5.76M gap, 200K chunk ×28, 20 shuffled + 10 Z/6Z Cramer surrogates. Tutti i 20 lag significativamente negativi. R²=0.998 in log-log (aggregato).
**Proiettore**: LEVA — ha generato PSD_BLUE_NOISE, ACF_AMPLITUDE_SCALING, alpha drift. Ogni scoperta successiva costruisce su questa.
**Vincolo**: L'esponente α non è universale a 1.00 — è una media pesata di un esponente che drifta da ~2 a ~0.7 con la scala (EXP_ALPHA_STABILITY). La legge resta valida come descrizione aggregata.
**Verifica**: 3 esperimenti indipendenti confermano. 2 null baseline (shuffled, Z/6Z). Nessuna contraddizione.
**Piano**: 39 | **Dal**: 2026-04-08

### F2 — POISSON_CONVERGENCE
**Claim**: Tre osservabili indipendenti (β Brody, ⟨r⟩, acf1) predicono Poisson a p*~10^{13.7}-10^{15.0}. Spread 1.3 decadi = crossover universale. Gerarchia: forma (β) decorrelata per prima, rapporto (⟨r⟩) secondo, memoria sequenziale (acf1) per ultima.
**Evidenza**: 25 finestre su 5.8M primi, 10 surrogates Cramer. R²: β=0.97, ⟨r⟩=0.96, acf1=0.53.
**Proiettore**: CONVERGENZA — unifica BOUNDARY, BRODY_CROSSOVER, GAP_ANTICORR in un quadro unico.
**Vincolo**: acf1 ha R² più basso (0.53) — l'estrapolazione è meno affidabile su quell'asse.
**Verifica**: 3 osservabili indipendenti convergono. Null baseline.
**Piano**: 39 | **Dal**: 2026-04-06

---

## Candidati (C)

### C1 — SPECTRAL_NICHE
**Claim**: I primi sono l'unico dominio nel punto (⟨r⟩ intermedio 0.45-0.48, acf1 significativamente negativo -0.05 a -0.10). Berry-Robnik matcha ⟨r⟩ ma ha acf1≈0. Il panorama spettrale è 2D: (⟨r⟩, acf1). L'autocorrelazione dei gap è il discriminante.
**Evidenza**: 17 domini, N=5000. Berry-Robnik 0.5 ha ⟨r⟩=0.485 (=primi) ma acf1=+0.009 (vs -0.10 per primi, z=-7.5).
**Proiettore**: CONVERGENZA — lega ⟨r⟩ e acf1 in uno spazio 2D dove i primi sono unici.
**Attende**: verifica su scale più grandi (N>50K). Se la nicchia si chiude con la scala → declassare.

### C2 — ACF_AMPLITUDE_SCALING
**Claim**: A(ln p) = 0.096 - 0.0033·ln(p), R²=0.92. L'ampiezza della legge 1/k decade linearmente in ln(p). Predice Poisson a p*~10^{12.6}.
**Evidenza**: 6M primi, 10 finestre × 100K gap, 15 surrogates shuffled. Tutti z>6.
**Proiettore**: LEVA — collega ACF_1K_LAW a POISSON_CONVERGENCE quantitativamente.
**Attende**: α drift (EXP_ALPHA_STABILITY) potrebbe richiedere riformulazione da A·k^(-1) a A·k^(-α(p)).

### C3 — EXP_ALPHA_STABILITY (alpha drift)
**Claim**: L'esponente α in acf(k)~k^(-α) drifta da ~2 a ~0.7 con la scala dei primi. L'anti-correlazione cambia tipo: da localizzata (dipolare, α>1) a diffusa (illusoria, α<1). Vincolo su ACF_1K_LAW.
**Evidenza**: 6M primi, 10-12 finestre, max_lag 50-100, drift/scatter ratio 1.8-1.9.
**Proiettore**: RISCHIO — mette in discussione l'universalità di F1. Ma non la invalida — la precisa.
**Attende**: R² della legge a potenza decade a 0.24 per primi grandi. Che forma funzionale la sostituisce?

---

## Note

- Le promozioni C→F sono proposte dal lab, confermate dall'operatore.
- Il proiettore valuta i candidati ad ogni ciclo — la valutazione può cambiare se il campo cambia.
- I vincoli non sono contraddizioni — sono precisazioni. Un vincolo su F1 non lo invalida, lo affina.
- Quando un fatto genera 3+ scoperte derivate → candidato naturale per A (assioma del campo).

exec
/bin/bash -lc 'python tools/dnd_scenario.py --best' in /opt/MM_D-ND
 succeeded in 145ms:
META: score=0.898  — META: incerto (i=0.5) — massimo potere discriminante
G_POTENZIALE_NULLA: score=0.703  — G_POTENZIALE_NULLA: legge di scala da raffinare
METRIC_TENSOR: score=0.624  — METRIC_TENSOR: legge di scala da raffinare

codex
Il proiettore punta su `META`: il nodo non è un dominio fisico nuovo, ma il dubbio se i test stiano misurando contenuto o solo struttura tautologica. Cerco gli strumenti già presenti per fare un audit minimo invece di aggiungere un nuovo `exp_*.py`.
exec
/bin/bash -lc "rg --files tools | rg 'dnd_(controprove|domandatore|autoricerca|scenario|.*assert|.*verify|.*test|.*meta)|observables_registry'" in /opt/MM_D-ND
 succeeded in 0ms:
tools/observables_registry.py
tools/dnd_gue_test.py
tools/dnd_domandatore.py
tools/dnd_autoricerca.py
tools/dnd_scenario.py
tools/dnd_controprove.py

exec
/bin/bash -lc 'python tools/dnd_domandatore.py --ask META' in /opt/MM_D-ND
exec
/bin/bash -lc 'python tools/dnd_controprove.py' in /opt/MM_D-ND
 succeeded in 156ms:

############################################################
# DOMANDATORE D-ND — Interrogazione
# 2026-05-07T14:59:31.258090
############################################################

  DOMANDA: META

  [DUALE   ] Se "META" e' vero, cosa dice il contrario (1/X)?
             Guida: Inverti la premessa. Se la conclusione tiene anche invertita, e' robusta.

  [CONFINE ] Tra il si e il no di "META", cosa c'e' al bordo?
             Guida: Il terzo incluso. La scelta non e' binaria — cosa esiste nel mezzo?

  [DOMINIO ] Se "META" vale qui, vale anche in un altro contesto?
             Guida: Cambia il dominio. Se l'effetto non si trasferisce, e' locale, non universale.

  [ROTTURA ] Cosa romperebbe "META"? Qual e' il controesempio?
             Guida: Cerca la falsificazione. Se non la trovi, il claim e' piu' forte.

  [SCALA   ] "META" vale a scala grande quanto a scala piccola?
             Guida: Testa ai limiti. Se funziona solo a una scala, non e' strutturale.

============================================================
  METODO: rispondi a ciascuna delle 5 domande.
  Le risposte sono il campo — la risultante emerge da sole.

  PRIORITY: [CONFINE] Tra il si e il no di "META", cosa c'e' al bordo?
============================================================

  Report: /opt/MM_D-ND/tools/data/domandatore/domandatore_20260507_1459.json

 succeeded in 585ms:
/opt/MM_D-ND/tools/dnd_controprove.py:301: RuntimeWarning: overflow encountered in scalar power
  ("r = (r²-1)", lambda r: r**2 - 1, PHI, f"2φ = {2*PHI:.6f}"),
/opt/MM_D-ND/tools/dnd_controprove.py:319: RuntimeWarning: invalid value encountered in scalar divide
  gap_ratios.append(gaps[i-1] / gaps[i])
=== CONTROPROVA 1: FRAZIONI CONTINUE ===
Confronto spirali di convergenza per diversi irrazionali.

    φ = 1.6180339887
       Gap ultimi 3: 6.70e-08, -2.56e-08, 9.77e-09
       Rapporto gap ultimi 3: 2.6180, 2.6180, 2.6180
       Target²: 2.618034
       Rapporto gap → Target²? 0.000000 (SÌ)

   √2 = 1.4142135624
       Gap ultimi 3: 4.69e-14, -8.22e-15, 1.33e-15
       Rapporto gap ultimi 3: 5.8436, 5.7027, 6.1667
       Target²: 2.000000
       Rapporto gap → Target²? 4.166667 (NO)

   √3 = 1.7320508076
       Gap ultimi 3: 1.76e-10, -4.71e-11, 1.26e-11
       Rapporto gap ultimi 3: 3.7320, 3.7321, 3.7320
       Target²: 3.000000
       Rapporto gap → Target²? 0.732005 (NO)

    e = 2.7182818285
       Gap ultimi 3: 2.00e-14, -1.69e-14, 8.88e-16
       Rapporto gap ultimi 3: 23.9475, 24.1111, 1.1842
       Target²: 7.389056
       Rapporto gap → Target²? 6.204846 (NO)

  RISULTATO: Il rapporto gap → target² vale per TUTTI gli irrazionali
  quadratici (φ, √2, √3) ma NON per e o π (non-quadratici).
  La spirale φ² è il CASO SPECIALE di una proprietà generale.
  Cosa rende φ unico: ha i quozienti più piccoli (tutti 1),
  quindi la spirale più lenta = più informazione per giro.

=== CONTROPROVA 2: MATRICE D-ND ===
  Matrice: [[1,1],[1,0]]
  Autovalori: 1.6180339887, -0.6180339887
  φ =          1.6180339887
  -1/φ =       -0.6180339887
  Prodotto (det): -1.0000000000 (deve essere -1)
  Somma (traccia): 1.0000000000 (deve essere 1)

  Potenze M^n: l'elemento [0,0] è F(n+1)
    n= 1: F=     1/    1 = 1.00000000  polo_ND/polo_D = -3.82e-01
    n= 2: F=     2/    1 = 2.00000000  polo_ND/polo_D = +1.46e-01
    n= 3: F=     3/    2 = 1.50000000  polo_ND/polo_D = -5.57e-02
    n= 4: F=     5/    3 = 1.66666667  polo_ND/polo_D = +2.13e-02
    n= 5: F=     8/    5 = 1.60000000  polo_ND/polo_D = -8.13e-03
    n= 6: F=    13/    8 = 1.62500000  polo_ND/polo_D = +3.11e-03
    n= 7: F=    21/   13 = 1.61538462  polo_ND/polo_D = -1.19e-03
    n= 8: F=    34/   21 = 1.61904762  polo_ND/polo_D = +4.53e-04
    n= 9: F=    55/   34 = 1.61764706  polo_ND/polo_D = -1.73e-04
    n=10: F=    89/   55 = 1.61818182  polo_ND/polo_D = +6.61e-05
    n=11: F=   144/   89 = 1.61797753  polo_ND/polo_D = -2.53e-05
    n=12: F=   233/  144 = 1.61805556  polo_ND/polo_D = +9.64e-06

  Interpretazione D-ND:
  - Polo D (φⁿ) cresce → domina
  - Polo ND ((-1/φ)ⁿ) oscilla e decresce → non sparisce mai
  - Il gap è la competizione tra i due poli
  - Il polo ND non muore — è l'onda residua che non si chiude
  - I due poli COESISTONO per sempre: il dipolo è indissolubile

=== CONTROPROVA 3: L'ALTRO POLO (-1/φ) ===
  L'equazione x² = x + 1 ha due soluzioni:
  Polo D:  φ   = 1.6180339887
  Polo ND: -1/φ = -0.6180339887
  Il loro rapporto: φ / (-1/φ) = -φ² = -2.618034

  Iterazione r → 1 + 1/r VICINO a -1/φ:
    r₀ = -0.6180 + +0.010 = -0.6080
    → -3.3788 → 0.7040 → 2.4204 → 1.4132
    r₀ = -0.6180 + -0.010 = -0.6280
    → 0.1732 → 6.7750 → 1.1476 → 1.8714
    r₀ = -0.6180 + +0.001 = -0.6170
    → -0.7482 → -0.3365 → -1.9721 → 0.4929

  -1/φ è un punto fisso INSTABILE di r → 1 + 1/r
  Qualsiasi perturbazione → fugge verso φ (punto stabile)
  Il polo ND respinge — il polo D attrae
  Ma il polo ND ESISTE. È l'altra faccia dello zero.

=== CONTROPROVA 4: OSCILLATORE SMORZATO ===
  Rapporto massimi = 1/φ quando γ/ω = ln(φ)/(2π) = 0.076587
  Primi 8 massimi e rapporti:
    t=  6.31  x=0.617132
    t= 12.61  x=0.380874  rapporto=1.620306  dist_φ=0.001404
    t= 18.91  x=0.235062  rapporto=1.620311  dist_φ=0.001407
    t= 25.21  x=0.145072  rapporto=1.620315  dist_φ=0.001410
    t= 31.51  x=0.089533  rapporto=1.620320  dist_φ=0.001413
    t= 37.81  x=0.055256  rapporto=1.620325  dist_φ=0.001416
    t= 44.11  x=0.034102  rapporto=1.620329  dist_φ=0.001419
    t= 50.41  x=0.021046  rapporto=1.620334  dist_φ=0.001421

  L'oscillatore smorzato con γ/ω = ln(φ)/2π ha:
  - Rapporto tra massimi = φ (per costruzione)
  - L'inviluppo e^(-γt) è la spirale D-ND nello spazio dei tempi
  - Ma: questo IMPONE φ nel damping. Non è emergente.
  - La differenza: in Fibonacci φ EMERGE dalla regola D+ND=D_new.
  - Nell'oscillatore φ va IMPOSTO nel rapporto γ/ω.

=== CONTROPROVA 5: MAPPA LOGISTICA ===
  x(n+1) = r·x(n)·(1-x(n)), punto fisso x* = 1 - 1/r

  r=2.5000, x*=0.600000
    Rapporto gap (ultimi): -1.999998
    Derivata f'(x*) = -0.500000
    1/f'(x*) = -2.000000

  r=2.9900, x*=0.665552
    Rapporto gap (ultimi): -0.911750
    Derivata f'(x*) = -0.990000
    1/f'(x*) = -1.010101

  r=φ+1=2.6180, x*=0.618034
    Rapporto gap (ultimi): -1.617921
    Derivata f'(x*) = -0.618034
    1/f'(x*) = -1.618034

  RISULTATO: nella mappa logistica il rapporto gap = 1/f'(x*)
  Per Fibonacci: f(r) = 1 + 1/r, f'(φ) = -1/φ², gap ratio = -φ²
  Il segno negativo causa l'alternanza ↑↓ (D→ND→D)
  |gap ratio| = φ² conferma: è la DERIVATA al punto fisso.

=== CONTROPROVA 6: UNIVERSALITÀ ===
Il rapporto gap = 1/f'(x*) per qualsiasi iterazione al punto fisso.

  r = 1 + 1/r (D-ND)
    target = 1.618034, converge: True
    rapporto gap = -2.618034, f'(x*) = -1/φ² = -0.381966

  r = √(r+1)
    target = 1.618034, converge: True
    rapporto gap = 3.236077, f'(x*) = 1/(2φ) = 0.309017

  r = (r²-1)
    target = 1.618034, converge: False
    rapporto gap = nan, f'(x*) = 2φ = 3.236068

  r = 1 + 1/r (→√2)
    target = 2.414214, converge: False
    rapporto gap = 1.000000, f'(x*) = per √2+1

  CONCLUSIONE:
  La spirale con rapporto φ² NON è magia — è calcolo differenziale.
  f'(φ) = -1/φ² per la specifica funzione f(x) = 1 + 1/x.

  MA ciò che è speciale di φ:
  1. È il SOLO numero dove f(x) = 1 + 1/x ha punto fisso
     (cioè: il tutto = somma delle parti con auto-similarità)
  2. I quozienti parziali sono tutti 1 → convergenza più LENTA
     → massima informazione per ciclo → spirale più aperta
  3. La derivata -1/φ² = -(φ+1)/φ² = -1/φ → il polo ND
     Il rapporto di contrazione della spirale È il polo opposto.
  4. |f'(φ)| = 1/φ² < 1 → stabile. |f'(-1/φ)| = φ² > 1 → instabile.
     Il polo D attrae, il polo ND respinge. Il dipolo è asimmetrico.


codex
`dnd_controprove.py` conferma già che la convergenza a φ contiene molta tautologia differenziale: utile per META, ma non basta perché non isola gli 11 test che passano. Ora cerco dove nasce `verifica.pass=11` e misuro se quei check dipendono dal contenuto del seme o solo dalla forma.
exec
/bin/bash -lc "rg -n 'verifica|verify_assertions|pass|total|11 test|test pass|fail' tools -g '*.py'" in /opt/MM_D-ND
 succeeded in 0ms:
tools/confine_spessore.py:8:Blocco 1: I quattro numeri del cluster passati attraverso M come se fossero gap
tools/confine_spessore.py:86:        # Quanti passi per arrivare a |x - phi| < 0.001?
tools/confine_spessore.py:92:        print(f"  {name:25s}: {n} passi per |x-phi| < 0.001")
tools/confine_spessore.py:147:    total_runs = len(run_lengths)
tools/confine_spessore.py:148:    print(f"  Totale flip registrati: {total_runs}")
tools/confine_spessore.py:151:        pct = 100 * run_counts[k] / total_runs
tools/confine_spessore.py:181:        obs = run_counts.get(k, 0) / total_runs
tools/confine_spessore.py:276:    # Trova il crossing: dove r passa da sotto a sopra il punto medio (0.5307+0.3863)/2
tools/dnd_compatibility.py:8:Non verifica il contenuto — verifica se le STRUTTURE sono sovrapponibili.
tools/dnd_riemann.py:55:def verifica_struttura():
tools/dnd_riemann.py:180:    print(f"\n  f mappa 0 → ∞ e ∞ → 1. Non fissa i poli — li SCAMBIA passando per φ.")
tools/dnd_riemann.py:209:    print(f"  {'passo':>5s}  {'z':>12s}  {'dist da φ':>12s}  {'nota':>15s}")
tools/dnd_riemann.py:255:    verifica_struttura()
tools/dnd_spettro.py:11:- Larghezza totale: 4·ln(φ) ≈ 1.925
tools/exp_markov3_observable_hunt.py:61:        total = sum(counts.values())
tools/exp_markov3_observable_hunt.py:62:        trans_prob[state] = {k: v / total for k, v in counts.items()}
tools/exp_markov3_observable_hunt.py:155:    n_total = sum(triple_counts.values())
tools/exp_markov3_observable_hunt.py:158:        p = c / n_total
tools/exp_markov3_observable_hunt.py:192:    # Count gaps in windows of total length ~ L * mean_gap
tools/dnd_trace_bridge.py:175:        """Curvatura al passo `step` per ogni punto di partenza."""
tools/dnd_trace_bridge.py:240:        """Quanti passi prima di divergere oltre threshold."""
tools/dnd_trace_bridge.py:253:    # Curvatura della traiettoria inversa ai primi passi
tools/dnd_trace_bridge.py:287:    print("Per ogni x₀: K_forward vs K_inverse al passo 2")
tools/bicono_projection.py:14:  3. INVARIANTE (cosa sopravvive al passaggio del vertice)
tools/bicono_projection.py:103:        'invariante': 'potenzialità totale |P|+|A|=cost',
tools/bicono_projection.py:172:        'invariante': '(da identificare: cosa sopravvive al passaggio tra i poli)',
tools/bicono_projection.py:258:    out.append(f"INVARIANTE (cosa sopravvive al passaggio):")
tools/exp_mod3_vs_residual_ordering.py:292:    total_ord_at_L50 = results[5]['ordering_pct_real'] if len(results) > 5 else 0
tools/exp_mod3_vs_residual_ordering.py:296:    print(f"At L=50: total ordering = {total_ord_at_L50:.1f}%, "
tools/dnd_autoricerca.py:816:            pass
tools/dnd_autoricerca.py:881:            'nota': f'{dominio}: nessuna struttura D-ND evidente al primo passaggio'
tools/dnd_autoricerca.py:1018:    n_totale = n_pattern + n_vincoli
tools/dnd_autoricerca.py:1019:    if n_totale > 0:
tools/dnd_autoricerca.py:1021:            'pattern_rate': n_pattern / n_totale,
tools/dnd_autoricerca.py:1500:        return {'piano': 0, 'tensioni': [], 'direzione': '', 'verifica': {}}
tools/dnd_autoricerca.py:1508:            'verifica': seme.get('verifica', {}),
tools/dnd_autoricerca.py:1511:        return {'piano': 0, 'tensioni': [], 'direzione': '', 'verifica': {}}
tools/dnd_autoricerca.py:1750:            pass
tools/dnd_autoricerca.py:2029:    report_lines.append(f"  Cicli totali: {stato['ciclo']}")
tools/dnd_autoricerca.py:2174:        'controprove_total': len(controprove),
tools/dnd_autoricerca.py:2202:        f"Controprove: {det.get('controprove_total', 0)} "
tools/r_ratio_decay.py:6:I primi passano da correlati (GUE-like) a indipendenti (Poisson) al crescere della scala.
tools/dnd_torre.py:113:    print(f"\n  Tutte le riduzioni M^n = a_n·M + b_n·I verificate: "
tools/dnd_torre.py:445:    print(f"    Il passo discreto \"vale\" {tau_equiv:.4f} unità di tempo continuo.")
tools/dnd_torre.py:567:    • sum+reciproco = tensione totale (3)
tools/dnd_torre.py:588:        nome = {0: "identità", 0.5: "mezzo passo", 1: "passo D-ND", 2: "doppio passo"}[t]
tools/dnd_torre.py:591:    print(f"\n    t=1 (il passo D-ND) è dove tension=3 ESATTAMENTE.")
tools/dnd_torre.py:616:    results['terna'] = {'a': 3, 'b_sq': 5, 'c': 2, 'verifica': 9 == 5 + 4}
tools/dnd_torre.py:623:    print(f"    3 = φ²+1/φ²: espansione + contrazione = la tensione totale.")
tools/dnd_torre.py:634:    print(f"  È la tensione al passo t=1 — il confine dove il processo")
tools/dnd_torre.py:637:    print(f"  Per t<1 (sotto-passo): la tensione è sotto 3, il sistema è")
tools/dnd_torre.py:638:    print(f"  'dentro' la struttura ℏ. Per t>1 (oltre il passo): la tensione")
tools/lib_llm_chain.py:17:Pre-flight cache: codex/claude verificati una sola volta per process —
tools/lib_llm_chain.py:18:evita 300s di timeout cumulativi quando un provider è auth-failed.
tools/lib_llm_chain.py:21:Solleva RuntimeError("all providers in chain ... failed") se tutti falliscono.
tools/lib_llm_chain.py:133:        pass
tools/lib_llm_chain.py:151:        pass
tools/lib_llm_chain.py:228:        f"all providers in chain {LLM_PROVIDER_CHAIN} failed "
tools/dipartimento.py:14:    python dipartimento.py --check       # verifica coerenza teoria/risultati
tools/dipartimento.py:78:# Asserzioni verificabili dal modello (checklist teoria ↔ calcolo)
tools/dipartimento.py:212:def verifica_asserzioni():
tools/dipartimento.py:226:            passed, detail = _esegui_test(test_name)
tools/dipartimento.py:227:            status = 'PASS' if passed else 'FAIL'
tools/dipartimento.py:246:    n_pass = sum(1 for r in risultati if r['status'] == 'PASS')
tools/dipartimento.py:247:    n_fail = sum(1 for r in risultati if r['status'] == 'FAIL')
tools/dipartimento.py:249:    print(f"\n  Sommario: {n_pass} PASS, {n_fail} FAIL, {n_skip} SKIP su {len(risultati)}")
tools/dipartimento.py:255:    """Esegue un singolo test di verifica."""
tools/dipartimento.py:291:        return all_alt, f"Alternanza verificata per {len(inputs)} input diversi"
tools/dipartimento.py:299:        passed = dist_phi < 1e-10 and dist_inv < 1e-10
tools/dipartimento.py:300:        return passed, f"λ₁={eigvals_sorted[0]:.10f} (φ), λ₂={eigvals_sorted[1]:.10f} (-1/φ)"
tools/dipartimento.py:324:        passed = spacing == 'GUE-like' and abs(spacing_r - 0.6) < 0.1
tools/dipartimento.py:325:        return passed, f"spacing={spacing}, ⟨r⟩={spacing_r:.4f}"
tools/dipartimento.py:336:        passed = abs(r_val) > 0.3 and p_val < 0.05
tools/dipartimento.py:337:        return passed, f"pearson_r={r_val:.4f}"
tools/dipartimento.py:348:        passed = mean_dist < 0.1
tools/dipartimento.py:349:        return passed, f"⟨dist da intero⟩={mean_dist:.4f}"
tools/dipartimento.py:362:        passed = best_dist < 0.05  # entro 5% da phi
tools/dipartimento.py:363:        return passed, f"best φ-dist={best_dist:.6f}, {len(top)} traiettorie"
tools/dipartimento.py:377:        passed = rate > 0.9
tools/dipartimento.py:378:        return passed, f"{len(reali)}/{len(tutti)} domini convergono a φ ({rate:.0%})"
tools/dipartimento.py:389:        passed = alt_03 and not alt_07
tools/dipartimento.py:390:        return passed, f"H=0.3 alt={alt_03}, H=0.7 alt={alt_07}"
tools/dipartimento.py:402:        passed = spacing_r > 0.7  # significativamente sopra GUE=0.60
tools/dipartimento.py:403:        return passed, f"⟨r⟩={spacing_r:.4f} (GUE standard=0.60)"
tools/dipartimento.py:509:        risultati = verifica_asserzioni()
tools/dipartimento.py:797:                        pass
tools/dipartimento.py:881:def cristallizza_seme(risultati_verifica, metriche=None):
tools/dipartimento.py:899:            pass
tools/dipartimento.py:915:    for r in risultati_verifica:
tools/dipartimento.py:925:                'porta': 'verify_assertions_FAIL',
tools/dipartimento.py:929:    for r in risultati_verifica:
tools/dipartimento.py:938:                'porta': 'verify_assertions_SKIP',
tools/dipartimento.py:941:    # PASS universale = possibile simmetria morta: se tutto passa, dov'è la varianza?
tools/dipartimento.py:942:    n_pass = sum(1 for r in risultati_verifica if r['status'] == 'PASS')
tools/dipartimento.py:943:    n_total = len(risultati_verifica)
tools/dipartimento.py:944:    if n_pass == n_total and n_total > 5:
tools/dipartimento.py:948:            'claim': f'Tutti i {n_total} test passano — verifica che non stiamo testando solo tautologie',
tools/dipartimento.py:950:            'nota': 'La convergenza a φ è triviale (controprove). I test stanno verificando contenuto o struttura?',
tools/dipartimento.py:952:            'porta': 'verify_assertions_META_ALL_PASS',
tools/dipartimento.py:1025:            # auto-generate da verify_assertions FAIL/SKIP/META_ALL_PASS) li
tools/dipartimento.py:1035:            # else: preserva porta come 'verify_assertions_*' o altro
tools/dipartimento.py:1092:        'verifica': {
tools/dipartimento.py:1093:            'pass': n_pass,
tools/dipartimento.py:1094:            'fail': sum(1 for r in risultati_verifica if r['status'] == 'FAIL'),
tools/dipartimento.py:1095:            'skip': sum(1 for r in risultati_verifica if r['status'] == 'SKIP'),
tools/dipartimento.py:1096:            'total': n_total,
tools/dipartimento.py:1132:    print(f"  Filtro: {len(tensioni_rilevanti)} promosse, {len(tensioni_filtrate)} filtrate (su {len(tensioni)} totali)")
tools/dipartimento.py:1196:            'pass': seme.get('verifica', {}).get('pass', 0),
tools/dipartimento.py:1197:            'fail': seme.get('verifica', {}).get('fail', 0),
tools/dipartimento.py:1198:            'total': seme.get('verifica', {}).get('total', 0),
tools/dipartimento.py:1228:        print(f"  Sinapsi tension-report failed: {e}")
tools/dipartimento.py:1489:            pass
tools/dipartimento.py:1546:        pass
tools/dipartimento.py:1556:            'ok': not any(kw in risultato_breve.lower() for kw in ('errore', 'error', 'fail')),
tools/dipartimento.py:1616:    durata_finora = (datetime.now() - ts).total_seconds() / 60
tools/dipartimento.py:1661:            pass
tools/dipartimento.py:1689:    # ORA legge: risultati_verifica + domandatore + scoperte autoricerca
tools/dipartimento.py:1694:    risultati_verifica = verifica_asserzioni()
tools/dipartimento.py:1695:    n_pass = sum(1 for r in risultati_verifica if r['status'] == 'PASS')
tools/dipartimento.py:1696:    n_fail = sum(1 for r in risultati_verifica if r['status'] == 'FAIL')
tools/dipartimento.py:1697:    rifletti('verifica', f'{n_pass} PASS, {n_fail} FAIL su {len(risultati_verifica)}')
tools/dipartimento.py:1700:    seme = cristallizza_seme(risultati_verifica, metriche)
tools/dipartimento.py:1801:    durata = (datetime.now() - ts).total_seconds() / 60
tools/dipartimento.py:1802:    n_pass = sum(1 for r in risultati_verifica if r['status'] == 'PASS')
tools/dipartimento.py:1803:    n_total = len(risultati_verifica)
tools/dipartimento.py:1812:                   f"Asserzioni: {n_pass}/{n_total} PASS.")
tools/dipartimento.py:1918:        'verifica_pass': seme.get('verifica', {}).get('pass', 0),
tools/dipartimento.py:1919:        'verifica_fail': seme.get('verifica', {}).get('fail', 0),
tools/dipartimento.py:1970:    print(f"\n>>> WATCHDOG: verifica completezza ciclo")
tools/dipartimento.py:1978:        pass
tools/dipartimento.py:2014:    fasi_attese = {'incrocio', 'verifica'}
tools/dipartimento.py:2021:    ciclo_log['durata_min'] = round((datetime.now() - ts).total_seconds() / 60, 1)
tools/dipartimento.py:2053:            pass
tools/dipartimento.py:2071:            verifica_asserzioni()
tools/dipartimento.py:2077:            risultati = verifica_asserzioni()
tools/dnd_gue_test.py:70:    # This function is only used for verification
tools/dnd_gue_test.py:307:# ─── Algebraic chain verification ─────────────────────────────────────
tools/dnd_gue_test.py:404:    print("T0: Algebraic chain verification")
tools/dnd_gue_test.py:563:    total = len([s for s in all_stats if "error" not in s])
tools/dnd_gue_test.py:564:    if total == 0:
tools/dnd_gue_test.py:567:    elif gue_count == total:
tools/dnd_gue_test.py:568:        verdict = (f"GUE UNIVERSALE: {gue_count}/{total} L-functions mostrano GUE. "
tools/dnd_gue_test.py:571:    elif gue_count >= total // 2:
tools/dnd_gue_test.py:572:        verdict = (f"GUE DOMINANTE: {gue_count}/{total}. Risultato parziale, "
tools/dnd_gue_test.py:632:    beta_total = sum(1 for lb in beta_results.values() for v in lb.values() if "class" in v)
tools/dnd_gue_test.py:633:    print(f"  DIPOLO FRATTALE: {beta_gue}/{beta_total} GUE a livello di repulsione")
tools/dnd_gue_test.py:727:    if beta_gue == beta_total and beta_total > 0:
tools/dnd_gue_test.py:728:        verdict_fractal = (f"GUE CONFERMATO via dipolo frattale: β>2 per {beta_gue}/{beta_total} misure. "
tools/dnd_gue_test.py:729:                          f"KS globale={gue_count}/{total} GUE (forma bulk). "
tools/dnd_gue_test.py:730:                          f"β allo zero={beta_gue}/{beta_total} GUE (repulsione). "
tools/dnd_gue_test.py:734:        verdict_fractal = (f"Dipolo frattale: {beta_gue}/{beta_total} GUE. "
tools/dnd_gue_test.py:735:                          f"KS globale: {gue_count}/{total}. Risultato misto.")
tools/dnd_gue_test.py:788:            "total_tested": total,
tools/dnd_gue_test.py:791:            "beta_total": beta_total,
tools/plot_risultante.py:27:def F_total(R):
tools/plot_risultante.py:43:ax.plot(R, F_total(R), 'k-', linewidth=2.5, label=r'$F_{tot} = 1/R + 1 - R$')
tools/plot_risultante.py:61:V_total = V(R)
tools/plot_risultante.py:66:ax.plot(R, V_total, 'k-', linewidth=2.5, label=r'$V(R) = -\ln R - R + R^2/2$')
tools/exp_markov_layer_recovery_audit.py:22:  A control fails recovery when any observable is assigned layer > known order.
tools/exp_markov_layer_recovery_audit.py:50:def classifier_pass(gaps, n_surr, rng):
tools/exp_markov_layer_recovery_audit.py:65:                    pass
tools/exp_markov_layer_recovery_audit.py:114:def summarize_failure(layers, known_order):
tools/exp_markov_layer_recovery_audit.py:147:        real_obs, z_scores, layers = classifier_pass(spec["gaps"], n_surr, rng)
tools/exp_markov_layer_recovery_audit.py:148:        summary = summarize_failure(layers, spec["known_order"])
tools/diagram_nodi_paper_map.py:133:total = len(nodes) * len(papers)
tools/diagram_nodi_paper_map.py:136:        f'{n_mapped}/{total} mappati  |  {n_faithful} fedeli  |  {n_partial} parz. distorti  |  {n_distort} distorti',
tools/dnd_bloch_explorer.py:116:    total = abs(omega_D) + abs(omega_ND)
tools/dnd_bloch_explorer.py:117:    if total < 1e-12:
tools/dnd_bloch_explorer.py:119:    return delta / total
tools/dnd_bloch_explorer.py:218:            total_phase = np.cumsum(np.abs(phase_diffs))
tools/dnd_bloch_explorer.py:219:            results['total_phase'] = total_phase
tools/dnd_bloch_explorer.py:294:        if 'total_phase' in res and len(res['total_phase']) > 4:
tools/dnd_bloch_explorer.py:295:            tp = res['total_phase']
tools/dnd_bloch_explorer.py:485:        total_scans = existing.get('total_scans', 0)
tools/dnd_bloch_explorer.py:487:        print(f"Resuming from {total_scans} previous scans, "
tools/dnd_bloch_explorer.py:491:        total_scans = 0
tools/dnd_bloch_explorer.py:496:        seed = total_scans + 1
tools/dnd_bloch_explorer.py:510:                    'scan': int(r['scan']) + total_scans,
tools/dnd_bloch_explorer.py:522:        total_scans += batch_size
tools/dnd_bloch_explorer.py:528:            'total_scans': total_scans,
tools/dnd_bloch_explorer.py:537:        print(f"\n[Checkpoint] {total_scans} total scans, "
tools/dnd_bloch_explorer.py:586:                'total_scans': len(results),
tools/godel.py:38:POLL_TIMEOUT = 180   # timeout totale
tools/godel.py:194:                aperte = [t for t in tensioni if not t.get("verificato", False)]
tools/dnd_retriever.py:92:            pass
tools/translate_tensions.py:100:# auth-fail. Prima chiamata fa check rapido 30s, esiti cached.
tools/translate_tensions.py:135:    """30s ping a claude per detect hang silenzioso o auth fail. Cached."""
tools/translate_tensions.py:235:            # 404/400 → modello non disponibile, prova il legacy. Altri errori → fail.
tools/translate_tensions.py:384:                # Fallback: duplicate content if translation failed
tools/dnd_observer.py:164:    keywords_dir = ["ora", "adesso", "passiamo", "cambiamo", "proviamo", "facciamo"]
tools/dnd_zero_traiettoria.py:172:            pass
tools/dnd_zero_traiettoria.py:193:            print("  Singolo crossing poi ALLONTANAMENTO → phi e' un passaggio, non un attrattore")
tools/exp_magnitude_psd_from_acf.py:11:If convergence fails → there's spectral structure beyond the power-law ACF.
tools/exp_magnitude_psd_from_acf.py:224:    print(f"  {'Range':>10s}  {'sum_acf':>10s}  {'frac_total':>10s}  {'slope_incr':>10s}")
tools/exp_magnitude_psd_from_acf.py:225:    total_sum = np.sum(acf)
tools/exp_magnitude_psd_from_acf.py:229:        frac = sum_range / total_sum if total_sum != 0 else 0
tools/md_to_site_B.py:10:natively from markdown — so LaTeX math needs NO conversion, just passthrough.
tools/exp_perturbation_rank_size_curve.py:291:    total = max_n * n_reps + max_n
tools/exp_perturbation_rank_size_curve.py:292:    gaps = prime_gaps(total)
tools/dnd_scenario.py:225:                pass
tools/dnd_scenario.py:542:                return f'{sid}: ha un target quantitativo da verificare'
tools/dnd_scenario.py:544:                return f'{sid}: segnale persistente — verificare a scale maggiori'
tools/dnd_scenario.py:562:        # Dalle varianza (esperimenti passati) possiamo stimare la velocità
tools/dnd_scenario.py:921:        è il prossimo passo. La traiettoria segue le assonanze convergenti.
tools/dnd_scenario.py:953:            # δV: angolo del passo
tools/dnd_scenario.py:955:                delta_v = 'acuto'  # rilascia potenziale — buon passo
tools/dnd_scenario.py:971:            # Ferma quando i passi successivi sono tutti piatti (piano saturo)
tools/dnd_scenario.py:986:        Un passaggio si trova quando:
tools/dnd_scenario.py:996:        passages = []
tools/dnd_scenario.py:1008:                passages.append({
tools/dnd_scenario.py:1018:                passages.append({
tools/dnd_scenario.py:1031:            'passages': passages,
tools/dnd_scenario.py:1033:                'total_dipoles': len(dipoles),
tools/dnd_scenario.py:1050:            if passages:
tools/dnd_scenario.py:1051:                for p in passages:
tools/dnd_scenario.py:1054:                print(f"  Nessun passaggio — il campo è uniforme")
tools/dnd_scenario.py:1058:            print(f"  Dipoli: {fs['total_dipoles']}  Assonanze: {fs['assonances']}")
tools/dnd_scenario.py:1065:    # CROSS-CHECK — verifica una proiezione da più angoli
tools/dnd_scenario.py:1072:        Per ogni tensione verificata:
tools/dnd_scenario.py:1095:            total_connections = d['connections']
tools/dnd_scenario.py:1100:            is_pillar = (total_connections >= 4 and len(neighbors) >= 3)
tools/dnd_scenario.py:1138:                'connections': total_connections,
tools/dnd_scenario.py:1166:        passages = result['passages']
tools/dnd_scenario.py:1168:        focus = sorted(passages, key=lambda p: p.get('size', len(p.get('cluster', []))), reverse=True)
tools/dnd_scenario.py:1365:    print(f"\n  CAMPO: {f.get('total_dipoles', '?')} dipoli, {f.get('assonances', '?')} assonanze, {f.get('high_potential', '?')} alto pot., {f.get('saturated', '?')} saturi")
tools/exp_mod3_scaling.py:49:    total = 0
tools/exp_mod3_scaling.py:54:            total += 1
tools/exp_mod3_scaling.py:57:    return count / total if total > 0 else 0.0, count, total
tools/exp_mod3_scaling.py:86:            total = sum(marginal.values())
tools/exp_mod3_scaling.py:87:            p_marginal = {k: v / total for k, v in marginal.items()}
tools/exp_mod3_scaling.py:145:        self_rate, self_count, self_total = mod3_self_transition_rate(win_mod3)
tools/m_spectro.py:63:    Applica M iterativamente. Ad ogni passo i rapporti diventano
tools/exp_two_layer_universality.py:63:        total = sum(counts.values())
tools/exp_two_layer_universality.py:64:        trans_prob[state] = {k: v / total for k, v in counts.items()}
tools/exp_two_layer_universality.py:320:                    pass
tools/exp_dR_brody_connection.py:39:N_total = len(primes)
tools/exp_dR_brody_connection.py:40:print(f"  {N_total} primes")
tools/exp_dR_brody_connection.py:48:max_start = N_total - W_SIZE - 2
tools/exp_dR_brody_connection.py:203:            c_gaps = rng.exponential(np.log(primes[:N_total-1] + 1), size=N_total-1)
tools/exp_dR_brody_connection.py:205:            c_p = np.cumsum(np.concatenate([[primes[0]], c_gaps]))[:N_total]
tools/exp_dR_brody_connection.py:209:            c_p = np.cumsum(np.concatenate([[primes[0]], sh_gaps]))[:N_total]
tools/exp_dR_brody_connection.py:290:    "N_primes": int(N_total),
tools/dnd_curva.py:99:    La famiglia A è la più naturale: mantiene γ=1 (il "passato diventa presente").
tools/dnd_curva.py:372:    - tr = energia totale (somma)
tools/dnd_curva.py:373:    - det = fase totale (prodotto con segno)
tools/dnd_curva.py:397:    print(f"    → La curva sono DUE RETTE passanti per l'origine:")
tools/dnd_curva.py:487:  │  Il gap_ratio è φ² su TUTTA la curva (verificato).                 │
tools/dnd_curva.py:502:  │  3 = (espansione) + (contrazione) = la "tensione" totale.          │
tools/md_to_site_F.py:10:natively from markdown — so LaTeX math needs NO conversion, just passthrough.
tools/exp_crossover_universality.py:43:N_total = len(primes)
tools/exp_crossover_universality.py:44:print(f"  {N_total} primes")
tools/exp_crossover_universality.py:51:max_start = N_total - W_SIZE - 2
tools/exp_crossover_universality.py:221:    c_gaps = rng.exponential(np.log(primes[:N_total-1] + 1), size=N_total-1)
tools/exp_crossover_universality.py:223:    c_p = np.cumsum(np.concatenate([[primes[0]], c_gaps]))[:N_total]
tools/exp_crossover_universality.py:301:    "N_primes": int(N_total),
tools/dnd_md2web.py:297:    # Unicode — pass through (browser handles them)
tools/dnd_stats.py:9:  anti_spurious(x, y)      → verifica se correlazione è tautologica
tools/dnd_zero_controllo2.py:261:            print(f"  ATTENZIONE: gap costanti non danno 2.0 — verificare formula")
tools/lab_trajectory_apply.py:110:        logger.warning("failed to read last entry from %s: %s", log_path, e)
tools/lab_trajectory_apply.py:249:        logger.warning("failed to mark executed: %s", e)
tools/lab_trajectory_apply.py:349:        logger.warning("audit log append failed: %s", e)
tools/exp_beta_crossover.py:7:that passes through the prime niche, or do primes lie OFF the universal curve?
tools/exp_beta_crossover.py:61:    total = cumsum[-1]
tools/exp_beta_crossover.py:63:    starts = np.random.uniform(0, total - L, n_windows)
tools/exp_beta_crossover.py:246:    # --- Analysis: does the beta-curve pass through primes? ---
tools/exp_beta_crossover.py:350:            pass
tools/exp_alpha_stability.py:48:    Returns (A, alpha, R2) or None if fit fails."""
tools/exp_alpha_stability.py:192:    total_drift = abs(coeffs_alpha[0]) * (ln_ps[-1] - ln_ps[0])
tools/exp_alpha_stability.py:194:    print(f"  Total alpha drift across data = {total_drift:.4f}")
tools/exp_alpha_stability.py:196:    print(f"  Drift / scatter ratio = {total_drift / alpha_std:.2f}" if alpha_std > 0 else "  Scatter = 0")
tools/exp_alpha_stability.py:198:    if total_drift < alpha_std:
tools/dnd_kernel.py:19:  - Il primo passo porta il 61.8%. Non ritardare il gesto.
tools/dnd_kernel.py:80:    'P2_primo_passo': {
tools/dnd_kernel.py:81:        'enunciato': 'Il primo passo porta il 61.8% della convergenza.',
tools/dnd_kernel.py:92:        'enunciato': 'Non serve l infinito. Al passo 4-5, convergenza > 99%.',
tools/dnd_kernel.py:108:    'L4_gesto': 'Il primo passo porta il 61.8%. Non ritardare il gesto.',
tools/dnd_kernel.py:115:    'springboard': 'Risultato verificato -> perche? -> identita radice -> proiezione.',
tools/dnd_kernel.py:141:    Verifica un claim contro le leggi. Restituisce {legge: pass/fail}.
tools/dnd_kernel.py:175:    """Misura la convergenza: a che passo sei al 99%?"""
tools/dnd_kernel.py:259:                pass
tools/dnd_arxiv.py:72:        return (datetime.now() - last_dt).total_seconds() > CACHE_HOURS * 3600
tools/dnd_arxiv.py:254:    total = len(cache.get('papers', {}))
tools/dnd_arxiv.py:259:    print(f"  Papers in cache: {total} ({processed} processati)")
tools/dnd_arxiv.py:263:    if total > 0:
tools/build_lab_graph.py:121:        for key in ['consecutio', 'what this opens', 'prossimi passi', 'next']:
tools/build_lab_graph.py:834:    # hardcoded qui il 29/04 perche' bypassava Phase A gate (build_lab_graph
tools/lab_aeternitas.py:31:- PROCEED se tutto passa
tools/lab_aeternitas.py:55:    1. --old esplicito se passato dall'utente
tools/lab_aeternitas.py:85:            pass
tools/lab_aeternitas.py:123:        "passed": len(p0_violations) == 0,
tools/lab_aeternitas.py:160:        "passed": len(p1_violations) == 0,
tools/lab_aeternitas.py:191:        "passed": len(p5_violations) == 0,
tools/lab_aeternitas.py:198:    p0_ok = checks["P0"]["passed"]
tools/lab_aeternitas.py:199:    p1_ok = checks["P1"]["passed"]
tools/lab_aeternitas.py:200:    p5_ok = checks["P5"]["passed"]
tools/alignment_marker.py:15:  2. CHECK  — verifica l'allineamento corrente rispetto al marker aperto.
tools/alignment_marker.py:141:        except: pass
tools/dnd_teoria.py:107:             'zero': 'E = mc² — conversione totale',
tools/dnd_teoria.py:383:    print(f"    onda ↔ particella            → complementarità totale")
tools/dnd_teoria.py:405:    totale_dipoli = 0
tools/dnd_teoria.py:406:    totale_costanti = 0
tools/dnd_teoria.py:411:        totale_dipoli += n_d
tools/dnd_teoria.py:412:        totale_costanti += n_c
tools/dnd_teoria.py:417:    print(f"\n  Totale: {totale_dipoli} dipoli, {totale_costanti} costanti, {len(TEORIE)} teorie")
tools/dnd_teoria.py:450:        'sono lo stesso', 'inseparabili', 'conversione totale',
tools/dnd_teoria.py:577:        t_confine = (f"Lo zero '{dipolo['zero']}' — è un muro o un passaggio? "
tools/dnd_md2latex.py:12:  - Math pass-through ($$...$$ → equation, $...$ → inline)
tools/dnd.py:11:    python dnd.py verifica "claim"                  # flusso verifica
tools/dnd.py:87:    print(f"\n  Verifica: {seme.get('verifica', {}).get('pass', '?')}/{seme.get('verifica', {}).get('total', '?')} pass")
tools/dnd.py:204:def cmd_verifica(claim):
tools/dnd.py:205:    """Flusso verifica: controprove -> engine -> domandatore."""
tools/dnd.py:236:        print('  python dnd.py verifica "claim"          # flusso verifica')
tools/dnd.py:257:    elif cmd == "verifica":
tools/dnd.py:259:            print("Serve un claim: python dnd.py verifica 'il claim'")
tools/dnd.py:261:        cmd_verifica(arg)
tools/dnd.py:266:        print("Usa: stato | strumenti | esplora | inverti | verifica | occhio")
tools/zeta_validation.py:588:    print(f"  3. Run topological_charge.py for §3.3 verification")
tools/lab_valutatore.py:5:Forma: entita' di gestione del ciclo lab. L'affinatore OSSERVA il passo che
tools/lab_valutatore.py:86:La matematica e' strumento di verifica, non motore di congetture. Uso corretto:
tools/lab_valutatore.py:93:  considerarlo evidenza, passarlo attraverso shuffle audit (protocollo
tools/lab_valutatore.py:101:- (b) ha verificato pattern cross-dominio — CONTA FORTE
tools/lab_valutatore.py:291:        pass
tools/lab_valutatore.py:302:        pass
tools/lab_valutatore.py:309:            n_total = sum(len(v) for v in il.values() if isinstance(v, list))
tools/lab_valutatore.py:320:            parts.append(f"## CONOSCENZA — Accumulata in insights_dal_lab\n- insight totali: {n_total} su {n_pairs} pair\n- maturity: A={mat['A']} (stabili), F={mat['F']} (emergenti), C={mat['C']} (candidati)\n")
tools/lab_valutatore.py:322:        pass
tools/lab_valutatore.py:346:  passo ha dipendenza dall'operatore.
tools/lab_valutatore.py:426:        print(f"\n... (total {len(prompt)} chars)")
tools/lab_valutatore.py:451:                "failure_type": "empty_output_from_chain",
tools/lab_valutatore.py:455:        print(f"valutatore: chain failed: {e}", file=sys.stderr)
tools/lab_valutatore.py:460:            "failure_type": "all_providers_failed",
tools/lab_valutatore.py:470:            "failure_type": "chain_exception",
tools/lab_valutatore.py:510:                "failure_type": "missing_decision_field",
tools/lab_valutatore.py:541:        print(f"valutatore: call failed: {e}", file=sys.stderr)
tools/lab_valutatore.py:546:            "failure_type": "subprocess_exception",
tools/lab_valutatore.py:559:        print(f"valutatore: log append failed: {e}", file=sys.stderr)
tools/exp_meta_tautology_test.py:5:STRUCTURAL (distinguishes primes from all synthetics) or TAUTOLOGICAL (fails on at least one).
tools/exp_meta_tautology_test.py:212:        all_pass = all(v > 3.0 for v in discriminates.values())
tools/exp_meta_tautology_test.py:213:        verdict = "STRUCTURAL" if all_pass else "TAUTOLOGICAL"
tools/triggers/build_applications_index.py:7:  - prodotti (cartelle <product_id>/ con verification.json reale)
tools/triggers/build_applications_index.py:195:                "verifier_form": (app.get("verification_spec") or {}).get("verifier_form", ""),
tools/triggers/build_applications_index.py:227:    Un prodotto maturo ha verification.json (non .spec). Niente oggi.
tools/triggers/build_applications_index.py:237:        verification = d / "verification.json"
tools/triggers/build_applications_index.py:239:        if verification.exists() and manifest.exists():
tools/triggers/build_applications_index.py:358:            "prodotti_maturi vuoto finché Stage 4 non gira con verification.json reale",
tools/triggers/build_applications_index.py:380:            print(f"  WARN: copy to site failed: {e}", file=sys.stderr)
tools/triggers/promote_to_publish.py:291:                    pass
tools/exp_two_channel_universality.py:177:        total = sum(counts.values())
tools/exp_two_channel_universality.py:178:        trans_probs[cl] = {cr: c / total for cr, c in counts.items()}
tools/dnd_paper_audit.py:252:                pass
tools/dnd_paper_audit.py:371:        pass  # Complex — flagged as note
tools/dnd_paper_audit.py:907:            'total_findings': len(all_findings),
tools/dnd_paper_audit.py:976:    lines.append(f"  Findings: {s['critical']}C  {s['major']}M  {s['minor']}m  {s['notes']}n  = {s['total_findings']} total")
tools/triggers/finding_promoter.py:117:# evita 300s di timeout per ogni chiamata quando un provider è auth-failed.
tools/triggers/finding_promoter.py:190:        pass
tools/triggers/finding_promoter.py:206:        pass
tools/triggers/finding_promoter.py:267:    raise RuntimeError(f"all providers in chain {LLM_PROVIDER_CHAIN} failed")
tools/harvest_moodnd.py:138:    total = len(node_ids)
tools/harvest_moodnd.py:143:    for batch_start in range(0, total, batch_size):
tools/harvest_moodnd.py:175:                        print(f"  [{processed+1}/{total}] Node {nid}: 404 (skip)")
tools/harvest_moodnd.py:192:                        print(f"  [{processed}/{total}] Node {nid}: {data['title'][:50]}... ({status})")
tools/harvest_moodnd.py:199:                    print(f"  [{processed}/{total}] Node {nid}: ERRORE - {e}")
tools/triggers/blueprint_generator.py:13:  - Scope: what_it_does + verification spec
tools/triggers/blueprint_generator.py:62:    spec = candidate.get("verification_spec", {}) or {}
tools/triggers/blueprint_generator.py:135:# tests/test_baseline.py — verifica naive baseline produce output corretto
tools/triggers/blueprint_generator.py:136:# tests/test_correctness.py — verifica candidate replica baseline su input set
tools/lab_autopsy.py:15:- Degrade graceful: se crash, scrive health con status="autopsy_failed",
tools/lab_autopsy.py:59:                            delta = abs((first - run_dt).total_seconds())
tools/lab_autopsy.py:136:            duration_s = int((b - a).total_seconds())
tools/lab_autopsy.py:138:            pass
tools/lab_autopsy.py:166:    - autopsy_failed: (set by except handler only)
tools/lab_autopsy.py:198:            "regressive_node": "upstream API failure during run",
tools/lab_autopsy.py:329:        # Degrade graceful: write failure health but don't crash the lab pipeline
tools/lab_autopsy.py:332:                "status": "autopsy_failed",
tools/lab_autopsy.py:336:                    "autopsy script itself failed — signal to investigate lab_autopsy.py "
tools/lab_autopsy.py:342:            pass
tools/lab_affinatore.py:3:lab_affinatore.py — Osservatore riflessivo sul passo del run notturno.
tools/lab_affinatore.py:7:dal produttore analizza il passo stesso, non il risultato.
tools/lab_affinatore.py:70:        pass
tools/lab_affinatore.py:80:possibilita' emergono dal passo stesso.
tools/lab_affinatore.py:91:## Osservazione del passo
tools/lab_affinatore.py:92:Cosa ha fatto il passo — in forma di traiettoria, non di azioni.
tools/lab_affinatore.py:95:Dove il sistema ha speso energia senza produrre. Se nulla: "nessuno — passo netto".
tools/lab_affinatore.py:101:Direzioni nuove aperte dal passo — per il ciclo successivo. Concrete, non generiche.
tools/lab_affinatore.py:158:        print(f"affinatore: chain failed: {e}", file=sys.stderr)
tools/lab_affinatore.py:159:        _mark_pending(ts, reason=f"affinatore chain failed: {e}")
tools/lab_affinatore.py:162:        print(f"affinatore: call failed: {e}", file=sys.stderr)
tools/lab_affinatore.py:179:        pass
tools/triggers/application_designer.py:4:Input: cycle_ts (deve aver passato gate strict via on_crystallize)
tools/triggers/application_designer.py:14:  - L'output è un'idea applicativa proposta, non un prodotto verificato.
tools/triggers/application_designer.py:86:def make_verification_spec(candidate_type: str) -> dict:
tools/triggers/application_designer.py:87:    """Stage 3 SPEC ONLY — come si verificherebbe (non verifica avvenuta).
tools/triggers/application_designer.py:89:    TM7 mandate: produrre verification.spec.json (non verification.json).
tools/triggers/application_designer.py:113:                "[TARGET] verification.json con metrics reali",
tools/triggers/application_designer.py:181:    """Per un finding, propone N applicazioni canonical-shape + verification.spec.
tools/triggers/application_designer.py:184:    Ogni candidate include verification_spec (Stage 3 SPEC ONLY, niente PASS).
tools/triggers/application_designer.py:185:    Tutti marker [TARGET]. Niente claim verificati.
tools/triggers/application_designer.py:193:        "verification_spec": make_verification_spec(ctype),
tools/triggers/application_designer.py:217:            "what_it_skips": "[TARGET — niente verifica empirica, scopo educational]",
tools/triggers/application_designer.py:282:            "n_findings_total": len(findings),
tools/triggers/application_designer.py:293:        "next_stage": "Stage 3 SPEC è già inline in ogni candidate.verification_spec (status SPEC_ONLY). Stage 4 = esecuzione manuale post-review.",
tools/triggers/application_designer.py:296:            "Niente codice scritto — solo design proposto + verification_spec",
tools/triggers/application_designer.py:297:            "verification_spec.status = SPEC_ONLY (come si verificherebbe, non verifica avvenuta)",
tools/triggers/application_designer.py:311:        apps_lines.append(f"- **{a['name']}** ({a['type']}) — finding #{a['discovery_finding_idx']} · verifier_form: `{a['verification_spec']['verifier_form']}`")
tools/triggers/application_designer.py:333:- Findings totali: {summary['n_findings_total']}
tools/triggers/application_designer.py:352:Ogni candidate include un `verification_spec` con:
tools/triggers/application_designer.py:355:- `status: SPEC_ONLY` — come si verificherebbe, NON verifica avvenuta
tools/triggers/application_designer.py:359:Esecuzione manuale post-review operatore. Produce `verification.json` reale
tools/triggers/application_designer.py:360:(NON `verification.spec.json` — quello è solo design).
tools/triggers/application_designer.py:367:- Operator review prima di passare a Stage 4
tools/spectral_gap_analysis.py:295:    ax2.set_ylabel('Cumulative fraction $N(s)/N_{total}$')
tools/triggers/on_crystallize.py:9:  - medium flag passano ma vengono dichiarati come visible_risks
tools/riemann_R.py:187:    print(f"  Somma mod 3 = 0 (ciclo si chiude in 3 passi): {sum_counts.get(0, 0)}  ({100*sum_counts.get(0,0)/len(triples_tcs_only):.1f}%)")
tools/riemann_R.py:191:    # Cicli che si chiudono dopo k*3 passi
tools/riemann_R.py:192:    print(f"\n--- Cicli che si chiudono dopo k*3 passi ---")
tools/riemann_R.py:209:    total_len = sum(len(s) for s in sequences)
tools/riemann_R.py:210:    print(f"  Lunghezza totale: {total_len}")
tools/riemann_R.py:245:    total_cycles = len(closure_lengths)
tools/riemann_R.py:249:    print(f"    Cicli totali: {total_cycles}")
tools/riemann_R.py:250:    print(f"    Chiusura dopo esattamente 3 passi: {cycles_len3}  ({100*cycles_len3/total_cycles:.1f}%)")
tools/riemann_R.py:251:    print(f"    Chiusura dopo multiplo di 3 passi: {cycles_mult3}  ({100*cycles_mult3/total_cycles:.1f}%)")
tools/riemann_R.py:252:    print(f"    Chiusura dopo NON-multiplo di 3:   {total_cycles - cycles_mult3}  ({100*(total_cycles-cycles_mult3)/total_cycles:.1f}%)")
tools/dnd_gap_resolution.py:114:    print(f"  │ Significato         │ Contenuto totale   │ Relazione D↔ND       │")
tools/dnd_gap_resolution.py:149:        # Traccia: somma totale D+ND a ogni step della regola
tools/exp_acf_stationarity.py:295:    # Sum of ACF (total correlation)
tools/md_to_site_D.py:10:natively from markdown — so LaTeX math needs NO conversion, just passthrough.
tools/dnd_riflesso.py:126:            pass
tools/exp_markov_memory_by_gue_type.py:70:    total = sum(context_counts.values())
tools/exp_markov_memory_by_gue_type.py:72:        p_joint = count / total
tools/exp_markov_memory_by_gue_type.py:171:        pass
tools/exp_markov_memory_by_gue_type.py:189:            pass
tools/exp_spectral_2d.py:247:        total = sum(trans[s].values())
tools/exp_spectral_2d.py:248:        if total > 0:
tools/exp_spectral_2d.py:250:                trans[s][t] /= total
tools/exp_spectral_2d.py:394:        # Check if Berry-Robnik path passes through primes' acf1
tools/exp_crossover_phase_test.py:265:    total = 0
tools/exp_crossover_phase_test.py:271:        total += 1
tools/exp_crossover_phase_test.py:289:    print(f"\n  RESULT: {phase_transition_count}/{total} sequences show full phase transition pattern")
tools/exp_crossover_phase_test.py:290:    if phase_transition_count == total:
tools/dnd_paper_graph.py:363:            'total_references': len(affected_edges),
tools/dnd_paper_graph.py:423:            'total_nodes': len(self.nodes),
tools/dnd_paper_graph.py:424:            'total_edges': len(self.edges),
tools/dnd_paper_graph.py:461:    lines.append(f"  Nodes: {s['total_nodes']}  Edges: {s['total_edges']}")
tools/dnd_paper_graph.py:499:    lines.append(f"  Total references to modify: {result['total_references']}")
tools/paper_H_verify.py:3:paper_H_verify.py — Complete verification of Paper H claims
tools/paper_H_verify.py:10:    python tools/paper_H_verify.py           # Run all verifications
tools/paper_H_verify.py:68:        "total": len(all_matrices),
tools/paper_H_verify.py:74:    print(f"\nReduction chain: {chain['total']} -> {chain['det_minus_1']} "
tools/paper_H_verify.py:280:        fails = max_err_k2 > 0.1 and I_spread_k2 > 0.1
tools/paper_H_verify.py:285:            "FAILS_AS_EXPECTED": fails,
tools/paper_H_verify.py:290:        print(f"  FAILS as expected: {fails}")
tools/paper_H_verify.py:292:    all_fib_pass = all(r["PASS"] for r in fib_results)
tools/paper_H_verify.py:293:    all_silver_fail = all(r["FAILS_AS_EXPECTED"] for r in silver_results)
tools/paper_H_verify.py:298:        "PASS": all_fib_pass and all_silver_fail,
tools/paper_H_verify.py:358:            print(f"No verification for section {target}")
tools/paper_H_verify.py:368:    all_pass = True
tools/paper_H_verify.py:374:            all_pass = False
tools/paper_H_verify.py:375:    print(f"\nALL SECTIONS: {'PASS' if all_pass else 'FAIL'}")
tools/paper_H_verify.py:402:    serializable["all_pass"] = all_pass
tools/dnd_lab_team.py:66:            pass
tools/dnd_lab_team.py:150:Con la formula che la sostiene. E il fenomeno fisico che la verifica.
tools/md_to_site.py:11:natively from markdown — so LaTeX math needs NO conversion, just passthrough.
tools/dnd_riformulazioni.py:247:    print(f"  Velocità convergenza: ~5 passi (tautologia)")
tools/dnd_cycle.py:93:            pass
tools/dnd_cycle.py:103:    """Un passo del ciclo: Godel -> Domandatore -> priority."""
tools/dnd_cycle.py:152:    """Esegui N passi del ciclo."""
tools/lab_falsifier.py:29:     (fail-conservative: se non possiamo verificare, non pubblichiamo)
tools/lab_falsifier.py:93:- Severity MEDIUM: incertezza significativa, richiede verifica piu' profonda.
tools/lab_falsifier.py:155:        print(f"[falsifier] chain failed: {e}", file=sys.stderr)
tools/lab_falsifier.py:224:        print(f"[falsifier] LLM call failed (exit={exit_code}). Conservative: BLOCK.", file=sys.stderr)
tools/lab_falsifier.py:247:    n_total = len(flags)
tools/lab_falsifier.py:250:    print(f"[falsifier] flags: {n_total} ({n_high} HIGH). coherent={record['coherent']}.")
tools/exp_boundary_shuffle_audit.py:332:    total = n_tautological + n_structural
tools/exp_boundary_shuffle_audit.py:333:    print(f"\n  Structural (|z|>3):   {n_structural}/{total}")
tools/exp_boundary_shuffle_audit.py:334:    print(f"  Tautological (|z|<3): {n_tautological}/{total}")
tools/exp_boundary_shuffle_audit.py:335:    print(f"  Class changes:        {n_class_change}/{total}")
tools/exp_boundary_shuffle_audit.py:342:        'total': total,
tools/dnd_loop.py:176:                    'verified': t.get('verificato', False),
tools/dnd_loop.py:209:    Se l'LLM non e' disponibile, le domande passano senza risposta (fallback strutturale).
tools/dnd_loop.py:227:def step_verifica(topic, claims):
tools/dnd_loop.py:239:        tests_passed = 0
tools/dnd_loop.py:240:        tests_total = 0
tools/dnd_loop.py:244:        tests_total += 1
tools/dnd_loop.py:251:                tests_passed += 1
tools/dnd_loop.py:256:        tests_total += 1
tools/dnd_loop.py:263:            tests_passed += 1
tools/dnd_loop.py:266:        tests_total += 1
tools/dnd_loop.py:270:            tests_passed += 1
tools/dnd_loop.py:273:        tests_total += 1
tools/dnd_loop.py:280:            tests_passed += 1
tools/dnd_loop.py:287:            tests_total += 1
tools/dnd_loop.py:301:                tests_passed += 1
tools/dnd_loop.py:303:        # Sopravvive se passa almeno 3 test (su 4 o 5)
tools/dnd_loop.py:304:        claim['tests_passed'] = tests_passed
tools/dnd_loop.py:305:        claim['tests_total'] = tests_total
tools/dnd_loop.py:306:        if tests_passed >= 3:
tools/dnd_loop.py:407:    survived, broken = step_verifica(topic, questions)
tools/dnd_loop.py:472:    max_steps=8 perche al passo 8 della tabella tutti convergono.
tools/dnd_loop.py:485:                print(f'\n  CRISTALLIZZATO al passo {step+1}')
tools/dnd_loop.py:502:    print(f'Cicli totali: {state["cycles"]}')
tools/exp_mobius_irrationality.py:35:        'det_minus1': {'total': 0, 'irrational': 0, 'rational': 0, 'no_fixed': 0},
tools/exp_mobius_irrationality.py:36:        'det_plus1': {'total': 0, 'irrational': 0, 'rational': 0, 'no_fixed': 0},
tools/exp_mobius_irrationality.py:55:                    results[key]['total'] += 1
tools/exp_mobius_irrationality.py:84:        total_real = r['rational'] + r['irrational']
tools/exp_mobius_irrationality.py:85:        irr_pct = (r['irrational'] / total_real * 100) if total_real > 0 else 0
tools/exp_mobius_irrationality.py:86:        rat_pct = (r['rational'] / total_real * 100) if total_real > 0 else 0
tools/exp_mobius_irrationality.py:90:        print(f'  Total matrices: {r["total"]}')
tools/exp_mobius_irrationality.py:91:        print(f'  Real fixed points: {total_real}')
tools/dnd_banchi.py:543:            pass
tools/dnd_banchi.py:557:            pass
tools/dnd_condizioni.py:133:        "n_passi": len(diario),
tools/lab_session_logger.py:110:            pass
tools/build_agent_field.py:258:        'ghost_total': stats.get('ghost_high_urgency', 0),
tools/build_agent_field.py:293:    # tensione-sorgente ferma per verificarne la trasferibilità). Il file
tools/build_agent_field.py:303:            pass
tools/build_agent_field.py:311:        elif status in ('timeout_during_tool', 'api_error', 'report_missing', 'no_start', 'autopsy_failed'):
tools/build_agent_field.py:458:        pass  # se il proiettore fallisce, l'agente funziona comunque
tools/build_agent_field.py:479:        if topo['ghost_total']:
tools/build_agent_field.py:481:                f"Ghost ad alta urgenza: {topo['ghost_total']} — connessioni mature "
tools/build_agent_field.py:552:        "Per ogni claim, verifica: il numero supporta la magnitudine del linguaggio? "
tools/exp_desitter_unification.py:35:N_total = len(primes)
tools/exp_desitter_unification.py:36:print(f"  {N_total} primes generated.")
tools/exp_desitter_unification.py:44:max_start = N_total - W_SIZE
tools/exp_desitter_unification.py:144:    cramer_gaps = np.zeros(N_total - 1)
tools/exp_desitter_unification.py:146:        pass
tools/exp_desitter_unification.py:149:    for j in range(N_total - 1):
tools/exp_desitter_unification.py:154:    cramer_p = np.array(cramer_p[:N_total])
tools/exp_desitter_unification.py:235:r_total_std = np.std(r_arr)
tools/exp_desitter_unification.py:236:R2 = 1 - (residual_std / r_total_std)**2
tools/exp_desitter_unification.py:241:print(f"  residual_std = {residual_std:.6f} vs total_std = {r_total_std:.6f}")
tools/exp_desitter_unification.py:250:    "N_primes": int(N_total),
tools/semantic_bridge.py:91:        - **Invariante di passaggio** (...): <text>
tools/semantic_bridge.py:121:    m = re.search(r'[-*]\s*\*{0,2}[Ii]nvariante(?:\s+di\s+passaggio)?\*{0,2}\s*(?:\([^)]*\))?\s*:\s*(.+?)(?=\n[-*]|\Z)',
tools/semantic_bridge.py:226:    un formato che il passo successivo non legge, il sistema ha lavorato ma
tools/semantic_bridge.py:262:                    'hint': 'Parser ha matchato la label ma non il contenuto — verificare regex di chiusura blocco.',
tools/semantic_bridge.py:411:    """Evolution report: riflessione sul passo. Source secondaria.
tools/dnd_trace_bridge_v3.py:11:- Questa oscillazione ha una FREQUENZA (nel dominio k = passo iterazione)
tools/dnd_trace_bridge_v3.py:253:        total = low + mid + high
tools/dnd_trace_bridge_v3.py:254:        print(f"\n  Zeta:   low={low/total*100:.1f}% mid={mid/total*100:.1f}% high={high/total*100:.1f}%")
tools/dnd_trace_bridge_v3.py:259:        total_r = low_r + mid_r + high_r
tools/dnd_trace_bridge_v3.py:260:        print(f"  Random: low={low_r/total_r*100:.1f}% mid={mid_r/total_r*100:.1f}% high={high_r/total_r*100:.1f}%")
tools/dnd_domandatore.py:321:            print(f"    Fit failed: {e}")
tools/dnd_domandatore.py:426:            pass
tools/dnd_domandatore.py:433:            pass
tools/dnd_domandatore.py:469:    2. Pattern quantitativi (closer/farther, fit failure)
tools/dnd_domandatore.py:523:        pass
tools/dnd_domandatore.py:611:    total_cmp = closer_count + farther_count
tools/dnd_domandatore.py:612:    if total_cmp >= 3:
tools/dnd_domandatore.py:613:        ratio = closer_count / total_cmp
tools/dnd_domandatore.py:618:                'claim': f'Convergenza forte {closer_count}/{total_cmp} ({ratio:.0%}): {result["criterio"][:50]}',
tools/dnd_domandatore.py:626:                'claim': f'Convergenza {closer_count}/{total_cmp} ({ratio:.0%}): {result["criterio"][:50]}',
tools/dnd_domandatore.py:634:                'claim': f'FALSIFICATO: controllo domina {farther_count}/{total_cmp} ({1-ratio:.0%}). {result["criterio"][:50]}',
tools/dnd_domandatore.py:642:                'claim': f'Divergenza {farther_count}/{total_cmp} ({1-ratio:.0%}): {result["criterio"][:50]}',
tools/dnd_domandatore.py:648:            if total_cmp >= 6 and 0.4 <= ratio <= 0.6:
tools/dnd_domandatore.py:652:                    'claim': f'Nessuna separazione: {closer_count}/{farther_count} (50/50 su {total_cmp} confronti). Il claim non regge. {result["criterio"][:40]}',
tools/dnd_domandatore.py:664:    # Cerca "Fit failed" — non-convergenza del fit e' un segnale
tools/dnd_domandatore.py:665:    if 'fit failed' in output.lower() or 'optimal parameters not found' in output.lower():
tools/dnd_domandatore.py:762:        pass  # silenzioso — non bloccare il ciclo per l'estensione
tools/dnd_domandatore.py:802:                pass
tools/dnd_domandatore.py:1075:      - cycles: {total, tensionsResolved, tensionsEscalated}
tools/dnd_domandatore.py:1099:    total_gen = len(tensions)
tools/dnd_domandatore.py:1100:    total_res = len(resolved)
tools/dnd_domandatore.py:1101:    ratio_diss = total_res / max(total_gen, 1)
tools/dnd_domandatore.py:1108:    print(f"\n  [DUALE] Generate:{total_gen} Risolte:{total_res}({ratio_diss:.0%}) Attive:{len(active)}")
tools/dnd_domandatore.py:1123:        total_h = sum(outcomes.values())
tools/dnd_domandatore.py:1126:        action_count = total_h - dry_count - learn_count
tools/dnd_domandatore.py:1128:        metriche['ratio_azione'] = float(action_count / max(total_h, 1))
tools/dnd_domandatore.py:1129:        metriche['ratio_dry_run'] = float(dry_count / max(total_h, 1))
tools/dnd_domandatore.py:1130:        metriche['ratio_learn'] = float(learn_count / max(total_h, 1))
tools/dnd_domandatore.py:1132:        print(f"\n  [CONFINE] Azione:{action_count} Dry:{dry_count} Learn:{learn_count} (su {total_h})")
tools/dnd_domandatore.py:1135:    total_real = cycles_meta.get('total', len(history))
tools/dnd_domandatore.py:1137:    if total_real > 0:
tools/dnd_domandatore.py:1138:        esc_ratio = esc_count / total_real
tools/dnd_domandatore.py:1140:        print(f"    Escalation globale: {esc_count}/{total_real} ({esc_ratio:.0%})")
tools/dnd_domandatore.py:1178:            total = len(types)
tools/dnd_domandatore.py:1179:            return -sum((c/total) * np.log2(c/total) for c in counts.values() if c > 0)
tools/dnd_experiments.py:117:    Usa fBM corretto (circulant embedding) e verifica:
tools/dnd_experiments.py:196:    high_fails = not any(results[f'H={h:.1f}']['has_structure'] for h in [0.7, 0.8, 0.9])
tools/dnd_experiments.py:199:        'claim_E3_holds': low_works and high_fails,
tools/dnd_experiments.py:203:        'high_H_fails': high_fails,
tools/dnd_experiments.py:211:    print(f"  H alto → no struttura: {high_fails}")
tools/dnd_experiments.py:489:    Usa i dati del journal per verificare se:
tools/dnd_experiments.py:540:        total_range = max(gue_range[1], poisson_range[1]) - min(gue_range[0], poisson_range[0])
tools/dnd_experiments.py:541:        overlap_frac = overlap / total_range if total_range > 0 else 0
tools/exp_scale_selective_perturbation.py:266:        total_var = np.sum(S**2)
tools/exp_scale_selective_perturbation.py:267:        explained = (S**2 / total_var) if total_var > 1e-15 else S * 0
tools/structural_check.py:155:        f"Correggi dove passi — il sistema evolve organicamente."
tools/dnd_two_faces.py:231:            total_above = np.sum(areas_above)
tools/dnd_two_faces.py:232:            total_below = np.sum(areas_below)
tools/dnd_two_faces.py:233:            area_ratio = total_above / total_below if total_below > 0 else float('inf')
tools/dnd_two_faces.py:234:            print(f"  Total area above: {total_above:.6f}")
tools/dnd_two_faces.py:235:            print(f"  Total area below: {total_below:.6f}")
tools/dnd_paper_refactor.py:359:            'total_changes': sum(len(c) for c in self.changes.values()),
tools/dnd_paper_refactor.py:448:    lines.append(f"  Total changes: {summary['total_changes']}")
tools/dnd_paper_refactor.py:527:        if summary['total_changes'] == 0:
tools/dnd_paper_refactor.py:533:    elif summary['total_changes'] > 0 and not args.json:
tools/dnd_spectral_probe.py:7:where traditional tests (KS) fail at finite sample size.
tools/dnd_spectral_probe.py:891:            print(f"  Fetch failed: {e}")
tools/dnd_M_operator.py:352:    2. Il topic e' passato da immaturo a semi-maturo (o da semi a maturo)
tools/dnd_quantization.py:349:                pass
tools/lab_refresh_detector.py:14:- ogni 14 giorni dall'ultimo refresh (failsafe: evita staleness >2 settimane) → TRIGGER
tools/lab_refresh_detector.py:66:    total = 0
tools/lab_refresh_detector.py:69:            total += len(v)
tools/lab_refresh_detector.py:70:    return total
tools/lab_refresh_detector.py:74:    """Map pair_key → count of insights. Usato per delta per-pair (vs total).
tools/lab_refresh_detector.py:78:    ma la pair HA materiale nuovo. Il total e' falsamente quieto. Per-pair vede.
tools/lab_refresh_detector.py:124:    # Il total count puo' restare invariato se una pair gagna N e ne perde N per cap.
tools/lab_refresh_detector.py:138:    # 3. Staleness failsafe
tools/dnd_piano11.py:414:                    "status": "Theorem for function fields (Katz-Sarnak 1999), conjecture for number fields with extensive numerical verification"
tools/exp_acf_range_universality.py:292:        print(f"    total drift = {drift:.4f} over ln(p) range {ln_ps[0]:.1f}-{ln_ps[-1]:.1f}")
tools/dnd_indeterminazione.py:128:  Dopo n passi:
tools/dnd_indeterminazione.py:132:    • Il rapporto assi = φ^(2n) (lo squeezing è φ² per passo)
tools/dnd_indeterminazione.py:186:    print(f"    V(φ) totale   =        = {V_phi:.6f}")
tools/dnd_indeterminazione.py:287:    # Energia totale: H = p²/2 + V(r) = costante
tools/dnd_indeterminazione.py:299:    print(f"  (Nelle unità D-ND: ~{T0:.1f} passi per una oscillazione completa)")
tools/dnd_indeterminazione.py:548:  │    + Tasso di squeezing = φ² per passo                      │
tools/dnd_indeterminazione.py:572:     |det(M^n)| = 1: l'area totale dell'incertezza è CONSERVATA.
tools/dnd_indeterminazione.py:577:     Tasso: φ² per passo. Universale.
tools/dnd_indeterminazione.py:586:     tension(t=1) = 3 = soglia del passo unitario
tools/dnd_lab_vivo.py:80:    errori = verifica_insights(insights)
tools/dnd_lab_vivo.py:91:def verifica_insights(insights):
tools/dnd_lab_vivo.py:96:    Non verifica tutto — cerca pattern di errore noti:
tools/dnd_lab_vivo.py:113:            pass
tools/dnd_lab_vivo.py:126:        # Chiedi all'LLM di verificare il claim
tools/dnd_lab_vivo.py:127:        verifica_prompt = (
tools/dnd_lab_vivo.py:134:        risultato = call_llm(verifica_prompt)
tools/dnd_lab_vivo.py:198:    print(f"  Cicli totali: {state['cycles']}")
tools/lab_anti_loop_guard.py:11:  certe transizioni stato→stato sono sintomo di loop pre-failure
tools/lab_anti_loop_guard.py:101:            total = sum(row.values()) or 1
tools/lab_anti_loop_guard.py:102:            T[a] = {b: row.get(b, 0) / total for b in alphabet}
tools/lab_anti_loop_guard.py:272:    print(f"loaded {len(sequences)} sequence(s), total events = {sum(len(s) for s in sequences)}")
tools/dnd_zero_varieta.py:49:            velocita.append(1.0 - cos_angle)  # 0 = convergenza totale
tools/dnd_zero_varieta.py:55:def passo_minimo(M):
tools/dnd_zero_varieta.py:113:    pas0 = passo_minimo(M0)
tools/dnd_zero_varieta.py:136:    print(f"\n  {'a':>5s} {'b':>5s} {'c':>5s} | {'d':>7s} | {'|λ+|':>7s} {'|λ-|':>7s} | {'vel':>7s} {'passo':>7s} {'curva':>7s} | {'ratio':>7s}")
tools/dnd_zero_varieta.py:155:                    pas = passo_minimo(M)
tools/dnd_zero_varieta.py:165:                        'passo': pas,
tools/dnd_zero_varieta.py:179:        print(f"  {r['a']:>5.2f} {r['b']:>5.2f} {r['c']:>5.2f} | {r['d']:>7.3f} | {r['eig_plus']:>7.4f} {r['eig_minus']:>7.4f} | {vel_s} {r['passo']:>7.4f} {r['curvatura']:>7.4f} | {rat_s}")
tools/dnd_zero_varieta.py:202:    validi = [r for r in risultati if r['velocita'] and r['passo'] > 0 and r['curvatura'] > 0]
tools/dnd_zero_varieta.py:205:        passi = np.array([r['passo'] for r in validi])
tools/dnd_zero_varieta.py:210:        print(f"  Passo:    [{passi.min():.4f}, {passi.max():.4f}]")
tools/dnd_zero_varieta.py:215:            corr_vp = np.corrcoef(np.log(vels + 1e-20), np.log(passi))[0, 1]
tools/dnd_zero_varieta.py:217:            corr_pc = np.corrcoef(np.log(passi), curve)[0, 1]
tools/dnd_zero_varieta.py:219:            print(f"    vel ↔ passo:    {corr_vp:+.4f}")
tools/dnd_zero_varieta.py:221:            print(f"    passo ↔ curva:  {corr_pc:+.4f}")
tools/dnd_zero_varieta.py:223:                print(f"  >>> vel e passo sono ACCOPPIATI (corr={corr_vp:.2f})")
tools/dnd_zero_varieta.py:225:                print(f"  >>> passo e curvatura sono ACCOPPIATI (corr={corr_pc:.2f})")
tools/dnd_zero_varieta.py:229:        m0_pas = passo_minimo(M0)
tools/dnd_zero_varieta.py:233:        print(f"    passo:     {m0_pas:.4f}")
tools/dnd_zero_varieta.py:238:        pas_rank = np.sum(passi < m0_pas) / len(passi)
tools/dnd_zero_varieta.py:241:        print(f"    percentile passo:{pas_rank*100:.0f}%")
tools/dnd_zero_varieta.py:246:    print("5. PRODOTTO vel × passo × curvatura — è costante?")
tools/dnd_zero_varieta.py:250:        prodotti3 = np.array([r['velocita'] * r['passo'] * r['curvatura'] for r in validi])
tools/dnd_zero_varieta.py:259:        # Anche: vel * passo (senza curvatura)
tools/dnd_zero_varieta.py:260:        prod2 = np.array([r['velocita'] * r['passo'] for r in validi])
tools/dnd_zero_varieta.py:261:        print(f"\n  vel × passo:  media={np.mean(prod2):.6e}, CV={np.std(prod2)/np.mean(prod2)*100:.1f}%")
tools/dnd_zero_varieta.py:262:        # passo * curvatura
tools/dnd_zero_varieta.py:263:        prod2b = np.array([r['passo'] * r['curvatura'] for r in validi])
tools/dnd_zero_varieta.py:264:        print(f"  passo × curva: media={np.mean(prod2b):.6e}, CV={np.std(prod2b)/np.mean(prod2b)*100:.1f}%")
tools/dnd_zero_varieta.py:277:            print(f"  vel×passo×curvatura ≈ costante (CV={cv*100:.1f}%)")
tools/dnd_zero_varieta.py:281:            print(f"  vel×passo×curvatura NON è costante (CV={cv*100:.1f}%)")
tools/dnd_implications.py:41:  Bypass (dopo review): git push --no-verify
tools/dnd_implications.py:415:    total = len(claim_results) + len(paper_results) + len(tension_results)
tools/dnd_implications.py:418:    print(f"\n  Totale elementi scansionati: {total}")
tools/dnd_implications.py:419:    print(f"  Safe to publish: {total - flagged}")
tools/dnd_implications.py:437:        'total_scanned': total,
tools/dnd_implications.py:438:        'total_flagged': flagged,
tools/lab_promotion.py:79:            pass
tools/lab_promotion.py:97:            pass
tools/lab_promotion.py:100:    # assertions (MM_D-ND: leggi da seme.json:verifica field)
tools/lab_promotion.py:101:    n_pass = n_fail = 0
tools/lab_promotion.py:105:            ver = seme.get("verifica", {}) or {}
tools/lab_promotion.py:106:            n_pass = int(ver.get("pass", 0))
tools/lab_promotion.py:107:            n_fail = int(ver.get("fail", 0))
tools/lab_promotion.py:109:            pass
tools/lab_promotion.py:111:    if n_pass == 0 and n_fail == 0 and ASSERTIONS_PATH.exists():
tools/lab_promotion.py:116:                n_pass = sum(1 for r in results if isinstance(r, dict) and r.get("status") == "PASS")
tools/lab_promotion.py:117:                n_fail = sum(1 for r in results if isinstance(r, dict) and r.get("status") == "FAIL")
tools/lab_promotion.py:119:            pass
tools/lab_promotion.py:120:    checks["n_pass"] = n_pass
tools/lab_promotion.py:121:    checks["n_fail"] = n_fail
tools/lab_promotion.py:128:        coherent and aet_decision != "VETO" and n_pass > 0 and n_fail == 0 and report_size > MIN_REPORT_BYTES
tools/lab_promotion.py:130:    checks["all_passed"] = eligible
tools/lab_promotion.py:225:        if checks["n_pass"] <= 0:
tools/lab_promotion.py:226:            reasons.append("no_assertions_pass")
tools/lab_promotion.py:227:        if checks["n_fail"] > 0:
tools/lab_promotion.py:228:            reasons.append(f"assertions_fail={checks['n_fail']}")
tools/dnd_spettro_zeta.py:776:        print(f"      Per passare da GOE a GUE serve rompere T-simmetria.")
tools/dnd_spettro_zeta.py:790:    print(f"    STRUTTURALE (verificato):")
tools/dnd_spettro_zeta.py:945:    print(f"→ Tempo totale: {elapsed:.1f}s")
tools/dnd_explorer.py:21:stati di verifica, campi con tensioni) vengono riconosciuti
tools/dnd_explorer.py:107:    (r'(?:da verificare|da testare|da validare)\s*[:\-—]\s*(.{10,})', 'da_verificare'),
tools/dnd_explorer.py:109:    (r'(?:prossimo.?test|prossimo.?passo)\s*[:\-—]\s*(.{10,})', 'prossimo'),
tools/dnd_explorer.py:115:    (r'(?:needs? testing|to verify|to validate)\s*[:\-—]\s*(.{10,})', 'da_verificare'),
tools/dnd_explorer.py:133:    """Estrai tensioni non verificate e prossimi test dal seme."""
tools/dnd_explorer.py:143:        if not t.get('verificato', False) and t.get('tipo') != 'identita':
tools/dnd_explorer.py:252:            # Check for verificato=false patterns
tools/dnd_explorer.py:253:            if obj.get('verificato') is False and 'claim' in obj:
tools/dnd_explorer.py:257:                    'type': 'claim_non_verificato',
tools/dnd_explorer.py:380:    - Falsificabilita': e' testabile? (contiene un claim verificabile)
tools/dnd_explorer.py:403:        r'\bverifica\b', r'\btest\b', r'\bfalsi\b',
tools/dnd_explorer.py:593:                                pass
tools/dnd_explorer.py:595:                pass
tools/dnd_explorer.py:646:        if obj.get('verificato') is False and 'claim' in obj:
tools/dnd_explorer.py:650:                'type': 'claim_non_verificato',
tools/dnd_explorer.py:671:        'claim_non_verificato': '!!',
tools/dnd_explorer.py:675:        'da_verificare': '[]',
tools/exp_two_channel_shuffle_audit.py:92:            total = counts[key].sum()
tools/exp_two_channel_shuffle_audit.py:93:            if total > 0:
tools/exp_two_channel_shuffle_audit.py:94:                probs = counts[key] / total
tools/exp_two_channel_shuffle_audit.py:129:    total = cumulative
tools/exp_two_channel_shuffle_audit.py:130:    if total < 1e-12:
tools/exp_two_channel_shuffle_audit.py:136:        if running / total >= 0.95:
tools/exp_two_channel_shuffle_audit.py:137:            return k, running / total
tools/exp_two_channel_shuffle_audit.py:139:    return max_lag, running / total if total > 0 else 0.0
tools/exp_two_channel_shuffle_audit.py:153:    # 3. ACF lag-1 of total gaps
tools/exp_two_channel_shuffle_audit.py:173:        'lag1_total': round(lag1, 4),
tools/exp_two_channel_shuffle_audit.py:210:    keys = ['slope_mag', 'slope_res', 'slope_ratio', 'xcorr', 'lag1_total',
tools/exp_modular_memory_spectrum.py:65:    total = row_sums.sum()
tools/exp_modular_memory_spectrum.py:74:            p_joint = trans[a, b] / total
tools/dnd_publish_cycle.py:70:        'nodes': stats['total_nodes'],
tools/dnd_publish_cycle.py:71:        'edges': stats['total_edges'],
tools/dnd_publish_cycle.py:108:            'total': result['summary']['total_findings'],
tools/dnd_publish_cycle.py:161:        lines.append(f"| {letter} | {a['verdict']} | {a['critical']} | {a['major']} | {a['total']} |")
tools/dnd_publish_cycle.py:366:            total_changes = sum(
tools/dnd_publish_cycle.py:373:                f"{total_changes}/7 papers use φ without det=-1. "
tools/dnd_risultante.py:48:    from dnd_risultante import Risultante, F_total, potential
tools/dnd_risultante.py:94:def F_total(R):
tools/dnd_risultante.py:113:    return -F_total(R)
tools/dnd_risultante.py:232:        FT_phi = float(F_total(PHI))         # ≈ 0 (machine precision)
tools/dnd_risultante.py:239:                "F_total": round(FT_phi, 15),
tools/dnd_risultante.py:246:                "F_total": 1.0,
tools/dnd_risultante.py:305:                "V_total": round(V_phi, 8)
tools/dnd_risultante.py:655:            print(f"    F_total       = {fphi.get('F_total', ''):+.15f}  (zero)")
tools/exp_selective_layer_decoupling.py:90:        total = sum(counts.values())
tools/exp_selective_layer_decoupling.py:91:        trans_prob[state] = {k: v / total for k, v in counts.items()}
tools/exp_selective_layer_decoupling.py:169:    total = len(binned) - 2
tools/exp_selective_layer_decoupling.py:173:            h -= (cnt / total) * np.log2(p)
tools/dnd_incrocio.py:263:                'teorie_totali': sorted(teorie_p1 | teorie_p2),
tools/dnd_incrocio.py:276:            print(f"    -> teorie unite: {r['teorie_totali']}")
tools/dnd_incrocio.py:346:                    'teorie': r['teorie_totali'],
tools/dnd_incrocio.py:462:            'totale': len(domande_consecutive),
tools/dnd_incrocio.py:891:                pass
tools/dnd_incrocio.py:1209:            pass
tools/dnd_incrocio.py:1246:    # Se D(AB) è simile a ND(CD), c'è un passaggio: AB → CD.
tools/dnd_incrocio.py:1247:    # Le catene di passaggi sono percorsi nello spazio dei dipoli.
tools/dnd_incrocio.py:1276:                        'passaggio': f"D({k1})='{d1.get('d','')}' → ND({k2})='{d2.get('nd','')}'",
tools/dnd_incrocio.py:1293:                    'passaggio': f"{inizio} → {medio} → {fine}",
tools/dnd_incrocio.py:1326:    generata['totale'] = (len(generata.get('rapporti', {}))
tools/dnd_incrocio.py:1387:        'risonanze_totali': 0,
tools/dnd_incrocio.py:1402:            pass
tools/dnd_incrocio.py:1407:    print(f"  Risonanze accumulate: {stato.get('risonanze_totali', 0)}")
tools/dnd_incrocio.py:1673:            pass
tools/dnd_incrocio.py:1688:    stato['risonanze_totali'] = stato.get('risonanze_totali', 0) + n_risonanze_ciclo
tools/dnd_incrocio.py:1704:    print(f"  Accumulate: {stato['risonanze_totali']} risonanze, {stato.get('conoscenza_generata',0)} conoscenza in {n_ciclo} cicli")
tools/dnd_incrocio.py:1732:    risonanze_tot = stato.get('risonanze_totali', 0)
tools/harvest_aimorning.py:64:    "/it/doc-dev/approcci-verifica-del-sistema-operativo-quantistico-d-nd",
tools/harvest_aimorning.py:77:    "/it/doc-dev/modello-d-nd-sintesi-integrata-verifica-coerenza-e-approfondimenti-avanzati",
tools/harvest_aimorning.py:175:    total = len(DOC_PATHS)
tools/harvest_aimorning.py:176:    print(f"Documenti da processare: {total}")
tools/harvest_aimorning.py:184:        f.write(f"# {total} documenti D-ND (2024-2025)\n")
tools/harvest_aimorning.py:194:                    print(f"  [{i+1}/{total}] 404: {path}")
tools/harvest_aimorning.py:216:                print(f"  [{i+1}/{total}] {data['title'][:60]}... ({body_len} chars)")
tools/harvest_aimorning.py:223:                print(f"  [{i+1}/{total}] ERRORE {path}: {e}")
tools/dnd_engine.py:82:        'status': 'verificato',
tools/dnd_engine.py:90:        'status': 'verificato',
tools/dnd_engine.py:98:        'status': 'verificato',
tools/dnd_engine.py:106:        'status': 'verificato',
tools/dnd_engine.py:116:        'status': 'verificato',
tools/dnd_engine.py:226:        'status': 'verificato',
tools/dnd_engine.py:234:        'status': 'verificato',
tools/dnd_engine.py:242:        'status': 'verificato',
tools/dnd_engine.py:295:    # --- CONGETTURE (non verificate, potenzialmente eliminabili) ---
tools/dnd_engine.py:334:        'status': 'verificato',
tools/dnd_engine.py:342:        'status': 'verificato',
tools/dnd_engine.py:350:        'status': 'verificato',
tools/dnd_engine.py:358:        'status': 'verificato',
tools/dnd_engine.py:366:        'status': 'verificato',
tools/dnd_engine.py:374:        'status': 'verificato',
tools/dnd_engine.py:382:        'status': 'verificato',
tools/dnd_engine.py:390:        'status': 'verificato',
tools/dnd_engine.py:398:        'status': 'verificato',
tools/dnd_engine.py:406:        'status': 'verificato',
tools/dnd_engine.py:414:        'status': 'verificato',
tools/dnd_engine.py:422:        'status': 'verificato',
tools/dnd_engine.py:430:        'status': 'verificato',
tools/dnd_engine.py:438:        'status': 'verificato',
tools/dnd_engine.py:446:        'motivo': 'verifica_struttura() di dnd_riemann.py verifica che Mobius f(z)=1+1/z, matrice M, e geometria proiettiva danno gli stessi invarianti.',
tools/dnd_engine.py:447:        'test': 'test_ext_verifica_struttura',
tools/dnd_engine.py:448:        'status': 'verificato',
tools/dnd_engine.py:454:        'motivo': 'test_autosimilarita() di dnd_normalizer.py. I rapporti Fibonacci F_{n+1}/F_n sono auto-simili per definizione. Il test verifica che il CV e basso e il rapporto medio e phi.',
tools/dnd_engine.py:456:        'status': 'verificato',
tools/dnd_engine.py:464:        'status': 'verificato',
tools/dnd_engine.py:472:        'status': 'verificato',
tools/dnd_engine.py:480:        'status': 'verificato',
tools/dnd_engine.py:488:        'status': 'verificato',
tools/dnd_engine.py:503:        'pass': abs(det + 1) < 1e-10 and abs(tr - 1) < 1e-10,
tools/dnd_engine.py:520:        'pass': abs(cr - (-PHI2)) < 1e-10 and abs(abs(spiral_r) - PHI2) < 0.001,
tools/dnd_engine.py:544:        'pass': gap_phi > gap_sqrt2 and gap_phi > gap_sqrt3,
tools/dnd_engine.py:562:        'pass': all(results),
tools/dnd_engine.py:570:        return {'pass': False, 'error': 'journal non disponibile'}
tools/dnd_engine.py:575:        return {'pass': False, 'error': 'zeta non analizzato'}
tools/dnd_engine.py:578:        'pass': 0.5 < sr < 0.7,
tools/dnd_engine.py:587:        return {'pass': False, 'error': 'journal non disponibile'}
tools/dnd_engine.py:594:        return {'pass': False, 'error': 'troppo pochi domini'}
tools/dnd_engine.py:612:        'pass': len(cluster_low) >= 2 and len(cluster_high) >= 2 and max_gap > 0.05,
tools/dnd_engine.py:627:        return {'pass': False, 'error': 'moduli non importabili'}
tools/dnd_engine.py:645:    high_h_fail = not results['H=0.9']['has_structure']
tools/dnd_engine.py:648:        'pass': low_h_work and high_h_fail,
tools/dnd_engine.py:650:        'high_H_fails': high_h_fail,
tools/dnd_engine.py:659:        return {'pass': False, 'error': 'journal non disponibile'}
tools/dnd_engine.py:664:        return {'pass': False, 'error': 'CA non analizzato'}
tools/dnd_engine.py:668:        'pass': sr > gue_standard + 0.1,
tools/dnd_engine.py:679:        return {'pass': False, 'error': 'dnd_condizioni non importabile'}
tools/dnd_engine.py:705:        return {'pass': False, 'error': 'nessun segnale produce scissione'}
tools/dnd_engine.py:712:        'pass': True,  # questo è un'osservazione, non un test pass/fail
tools/dnd_engine.py:779:        'pass': ratio > 1.5,
tools/dnd_engine.py:800:        'pass': abs(r_at_1 - 0.5) < 0.05,
tools/dnd_engine.py:816:        'pass': abs(r1 - 0.5) < 0.05 and r2 < 0.42,
tools/dnd_engine.py:861:        'pass': phi_best_cv or phi_dist < 0.1,
tools/dnd_engine.py:880:                'pass': all_100,
tools/dnd_engine.py:887:    return {'pass': True, 'nota': 'Confermato da report precedente', 'universale': True}
tools/dnd_engine.py:899:        return {'pass': True, 'nota': 'Confermato da dati Lagrangiana: nobili CV=4-6% vs non-nobili >10%'}
tools/dnd_engine.py:918:        'pass': np.mean(noble_dists) < np.mean(non_noble_dists),
tools/dnd_engine.py:936:        'pass': abs(det_M2 - 1) < 1e-10 and abs(eigvals_M2[0] - expected_eig1) < 1e-10,
tools/dnd_engine.py:949:    total = 0
tools/dnd_engine.py:966:                    total += 1
tools/dnd_engine.py:969:    fraction_above = above_1 / total if total > 0 else 0
tools/dnd_engine.py:971:        'pass': fraction_above > 0.7,
tools/dnd_engine.py:974:        'n_samples': total,
tools/dnd_engine.py:1012:        'pass': q5_mean < other_mean,
tools/dnd_engine.py:1043:        'pass': phi_narrowest,
tools/dnd_engine.py:1091:        'pass': sturm_monotone and harper_nonmonotone and sturm_near_05 and harper_v1_high,
tools/dnd_engine.py:1121:        'pass': all_ok,
tools/dnd_engine.py:1147:        'pass': errors[-1] < 1e-12 and abs(slope - expected_slope) / abs(expected_slope) < 0.05,
tools/dnd_engine.py:1171:        'pass': all_ok and is_sp2,
tools/dnd_engine.py:1243:        'pass': fib_collapses and not silver_collapses and not bronze_collapses,
tools/dnd_engine.py:1285:        'pass': divides_all and pi5_correct,
tools/dnd_engine.py:1332:        'pass': alt_rate_neg > 0.95 and alt_rate_pos < 0.05 and ac1_neg < -0.5,
tools/dnd_engine.py:1373:        'pass': abs(slope_ratio - 1.0) < 0.01 and all(0.45 < r < 0.60 for r in comp_ratios),
tools/dnd_engine.py:1413:        'pass': abs(ratio - 1.0) < 0.15,
tools/dnd_engine.py:1460:        'pass': abs(min_aperiodic - h_phi) < 1e-10 and h_values[0][1] < 1e-10,
tools/dnd_engine.py:1515:        'pass': convergence_ok and det_reverses and ratio_match,
tools/dnd_engine.py:1577:        'pass': Vc is not None and 0.5 < Vc < 2.5 and r_at_V1 > 0.45,
tools/dnd_engine.py:1621:        'pass': mean_snr_ratio > 2.5,
tools/dnd_engine.py:1675:        'pass': phi_slowest and abs(rate_phi - expected_phi) / abs(expected_phi) < 0.05,
tools/dnd_engine.py:1727:        'pass': all_ratio_phi and all_two_gaps and all_golden and phi_min_cv,
tools/dnd_engine.py:1740:def test_ext_verifica_struttura():
tools/dnd_engine.py:1774:        'pass': all_ok,
tools/dnd_engine.py:1800:        'pass': cv < 0.05 and dist_phi < 0.01,
tools/dnd_engine.py:1851:        'pass': tutti_convergono,
tools/dnd_engine.py:1895:        'pass': sin_ok and offset_ok and shift_ok,
tools/dnd_engine.py:1926:        return {'pass': False, 'error': 'zero mean spacings'}
tools/dnd_engine.py:1944:        'pass': True,  # classificazione sempre valida, il risultato e il best_fit
tools/dnd_engine.py:1988:        'pass': phi_zero and v1_ok and v2_ok and neg_zero and all_positive,
tools/dnd_engine.py:2031:            passed = result.get('pass', False)
tools/dnd_engine.py:2033:            if passed:
tools/dnd_engine.py:2091:        if k == 'pass':
tools/dnd_engine.py:2318:        'test': 'Enumerare primitive 2x2 det=-1: verificare h >= log(phi)',
tools/dnd_engine.py:2406:            if k == 'pass':
tools/dnd_engine.py:2567:        total = sum(weights)
tools/dnd_engine.py:2568:        probs = [w / total for w in weights]
tools/dnd_engine.py:2845:# 7. THEOREM — Cristallizza i verificati in candidati CLAIM
tools/dnd_engine.py:2851:    Un empirico verificato N volte → candidato strutturale.
tools/dnd_engine.py:3037:        total_shared = sum(t['n_shared'] for t in pair_tensions)
tools/dnd_engine.py:3109:        total_bridges = sum(t.get('n_bridges', 0) for t in pair_tensions)
tools/dnd_engine.py:3115:            'total_shared_metrics': total_shared,
tools/dnd_engine.py:3116:            'total_bridges': total_bridges,
tools/dnd_engine.py:3124:        if len(levels) >= 2 or total_shared > 0 or total_bridges > 0 or n_mediated > 0:
tools/dnd_engine.py:3129:                  f"{total_shared} nomi + {total_bridges} costanti{med_info} -> {status}")
tools/dnd_engine.py:3145:# 11. ENGINE CYCLE — Il ciclo completo a 7+1 passi
tools/dnd_engine.py:3156:    5. THEOREM     — cristallizza i verificati
tools/dnd_engine.py:3163:    print(f"# MOTORE DI RICERCA D-ND — ciclo a 7+1 passi")
tools/dnd_engine.py:3290:    print(f"# SOMMARIO — ciclo a 7+1+1 passi")
tools/dnd_engine.py:3392:        'verifica': {
tools/dnd_engine.py:3393:            'claims_totali': len(CLAIMS),
tools/exp_modular_algebra_depth.py:65:    total_pairs = pair_counts.sum()
tools/exp_modular_algebra_depth.py:66:    if total_pairs == 0:
tools/exp_modular_algebra_depth.py:68:    pi_pair = pair_counts / total_pairs
tools/exp_two_channel_psd.py:7:  S_total(f) = S_res(f) + S_mag(f).
tools/exp_two_channel_psd.py:177:        # Fraction of total PSD from each channel at low and high f
tools/exp_two_channel_psd.py:259:        # Fraction of total PSD from transition channel
tools/dnd_spirale.py:10:altrimenti sarebbe un loop (sacca spaziotempo)... la risultante passa
tools/dnd_spirale.py:76:    Non si muove. Vede gli approssimanti passare.
tools/dnd_spirale.py:77:    Ogni passaggio è un ciclo D-ND.
tools/dnd_spirale.py:85:    print("L'osservatore è a φ. Non si muove. Vede i piani passare.\n")
tools/dnd_spirale.py:105:    print(f"  L'alternanza ↑↓ è il passaggio D→ND→D→ND...")
tools/dnd_spirale.py:177:     e che vede tutto passargli davanti
tools/dnd_spirale.py:182:    print("Non itera. È al punto fisso. Vede passare i piani.\n")
tools/dnd_spirale.py:191:    # Il CONTENUTO che l'osservatore estrae: il gap di ogni passaggio
tools/dnd_spirale.py:193:    print(f"\n  Informazione per passaggio (potenziale):")
tools/dnd_normalizer.py:7:testa l'auto-similarità a scale crescenti, verifica convergenza a φ.
tools/dnd_normalizer.py:64:    Scala k: raggruppa k intervalli consecutivi e calcola d_totale/n_totale.
tools/dnd_normalizer.py:131:            risultato["direzione"] = "verificare se asimmetria nativa è presente"
tools/dnd_normalizer.py:148:    Restituisce (n_passi_per_convergenza, distanza_finale_da_phi).
tools/dnd_normalizer.py:149:    n_passi = n_iter se non converge.
tools/dnd_normalizer.py:205:                "passi": float("inf"),
tools/dnd_normalizer.py:212:        passi, dist = velocita_convergenza(d_int, nd_int)
tools/dnd_normalizer.py:219:            "passi": passi,
tools/dnd_normalizer.py:485:        print(f"  Passi per convergenza: {vero['passi']}")
tools/dnd_normalizer.py:497:        print(f"  Passi per convergenza: {vero2['passi']}")
tools/dnd_normalizer.py:525:        print(f"  Passi per convergenza: {vero3['passi']}")
tools/dnd_lab.py:238:    # Calcola δ per verificare
tools/dnd_lab.py:623:    total_count = 0
tools/dnd_lab.py:630:                    total_count += 1
tools/dnd_lab.py:634:    print(f"#  φ emerge in {phi_count}/{total_count} test")
tools/dnd_lab.py:788:                    pass
tools/dnd_lab.py:871:            pass
tools/dnd_lab.py:1034:# INSIGHT ENGINE — genera e verifica ipotesi dai risultati
tools/dnd_lab.py:1055:    print("INSIGHT ENGINE — generazione e verifica ipotesi")
tools/dnd_lab.py:1378:            pass
tools/dnd_lab.py:1461:    print(f"\n--- FASE 2: ESPERIMENTI ({len(filtered)} passano il filtro) ---")
tools/dnd_lab.py:1544:                pass
tools/dnd_lab.py:1548:    # Fase 4: Insight Engine — genera e verifica ipotesi
tools/dnd_lab.py:1959:            pass
tools/dnd_trasmutazione.py:2:dnd_trasmutazione.py — Trasmutare teorie duali: sostituire zero con passaggio
tools/dnd_trasmutazione.py:11:sostituire la singolarità con il passaggio (det=-1), e osservare
tools/dnd_trasmutazione.py:15:T2. Singolarità 1/x → risoluzione via Λ=+1, densità di passaggi
tools/dnd_trasmutazione.py:170:    print(f"    → Il passaggio D↔ND non si esaurisce mai. Come l'oscillazione quantistica.")
tools/dnd_trasmutazione.py:202:    3. Misurare: velocità di convergenza, numero di passaggi D↔ND
tools/dnd_trasmutazione.py:203:    4. Densità di passaggi per lo zero = curvatura locale
tools/dnd_trasmutazione.py:313:    # Parte C: Densità di passaggi per lo zero
tools/dnd_trasmutazione.py:314:    print(f"\n  C. Densità passaggi per lo zero (curvatura D-ND):")
tools/dnd_trasmutazione.py:331:        print(f"    x₀={x0:5.1f}: {crossings:2d} passaggi per φ in {len(traj_arr)} step, "
tools/dnd_trasmutazione.py:347:    La gravità in D-ND = densità di passaggi D↔ND per unità.
tools/dnd_trasmutazione.py:401:        total_crossings = len(d_int) + len(nd_int) - 1
tools/dnd_trasmutazione.py:402:        densita = total_crossings / len(sig)
tools/dnd_trasmutazione.py:420:            'crossings': total_crossings,
tools/dnd_trasmutazione.py:428:        print(f"  {nome:22s} | {total_crossings:9d} | {densita:.6f} | {ac1:+.4f} | {rcv:.4f}   | {interp}")
tools/dnd_trasmutazione.py:436:    # perché la scissione a mediana garantisce sempre un passaggio
tools/dnd_trasmutazione.py:487:    TRASMUTAZIONE: calcolare ΔD×ΔND su segnali diversi e verificare
tools/dnd_trasmutazione.py:667:    La struttura minima che impedisce il nulla e genera il passaggio.
tools/dnd_trasmutazione.py:707:    print(f"# Sostituire zero con passaggio nelle teorie duali")
tools/dnd_rottura.py:105:    print(f"         Per Λ=1: tr = 1 (contenuto totale = 1 unità)")
tools/dnd_rottura.py:309:    print(f"       1. tr = 1 (contenuto totale = unità)")
tools/dnd_rottura.py:490:        total_ints = len(d_int) + len(nd_int)
tools/costo_materializzazione.py:53:n_total = len(ratios_valid)
tools/costo_materializzazione.py:54:frac_orientabile = n_orientabile / n_total
tools/costo_materializzazione.py:55:frac_chirale = n_chirale / n_total
tools/costo_materializzazione.py:57:print(f"  Totale rapporti validi: {n_total}")
tools/costo_materializzazione.py:66:frac_equal = n_equal / n_total
tools/costo_materializzazione.py:71:frac_strict = n_strict / n_total
tools/costo_materializzazione.py:105:    # Orientabile: stessa chiralità nel passo successivo
tools/costo_materializzazione.py:174:        total = w[0] + w[1]
tools/costo_materializzazione.py:175:        if total == 0:
tools/costo_materializzazione.py:177:        r = w[0] / total
tools/costo_materializzazione.py:194:    total = gaps[i] + gaps[i+1]
tools/costo_materializzazione.py:195:    if total == 0:
tools/costo_materializzazione.py:197:    r = gaps[i] / total
tools/costo_materializzazione.py:218:total_gaps = len(gaps)
tools/costo_materializzazione.py:222:    print(f"  gap mod 6 = {r}: {c} ({c/total_gaps:.6f})")
tools/costo_materializzazione.py:226:n_nonzero_mod6 = total_gaps - n_zero_mod6
tools/costo_materializzazione.py:227:frac_zero = n_zero_mod6 / total_gaps
tools/costo_materializzazione.py:251:# Classe {0 mod 6} / totale -- già calcolato
tools/exp_spectral_rigidity.py:61:    total = levels[-1] - levels[0]
tools/exp_spectral_rigidity.py:65:        if L >= total * 0.4:
tools/dnd_next.py:7:Focus: ricerca e autolab. I paper sono asset di riferimento (report passivo),
tools/dnd_next.py:13:3. pipeline          — stato pubblicazione (info passiva)
tools/dnd_next.py:156:    verifica = seme.get('verifica', {})
tools/dnd_next.py:175:    # Test pass rate
tools/dnd_next.py:176:    total = verifica.get('total', 1)
tools/dnd_next.py:177:    pass_rate = verifica.get('pass', 0) / total
tools/dnd_next.py:184:    if pass_rate < 0.7:
tools/dnd_next.py:197:        'pass_rate': pass_rate,
tools/dnd_next.py:378:    Esegue la decisione. Ciclo chiuso: decide → agisci → verifica → aggiorna seme.
tools/dnd_next.py:522:            pass
tools/dnd_next.py:632:        pass
tools/dnd_next.py:680:        lines.append(f"    Stato: {research['status']} | Pass rate: {research['pass_rate']:.0%}")
tools/dnd_dipolo_lab.py:19:- Usa: MODUS_INDAGINE, CEC passi 1-2 (condizioni, firma)
tools/dnd_dipolo_lab.py:217:                'CONFINE': f"Lo zero tra {lato_d} e {lato_nd} — è un muro o un passaggio? Costante relazionale: {cost_rel.get('costante', '?')} = {cost_rel.get('valore', '?')}",
tools/dnd_dipolo_lab.py:385:        Prende l'ultimo passo di A, lo inverte con Godel,
tools/dnd_dipolo_lab.py:434:                    'passo': len(polo_a.traiettoria),
tools/dnd_dipolo_lab.py:463:def ciclo_dipolo(n_passi=12):
tools/dnd_dipolo_lab.py:487:    print(f"\n  {len(domande)} domande fondamentali, {n_passi} passi massimi\n")
tools/dnd_dipolo_lab.py:492:    for passo in range(n_passi):
tools/dnd_dipolo_lab.py:493:        print(f"\n--- Passo {passo} ---")
tools/dnd_dipolo_lab.py:505:                d = domande[passo % len(domande)]
tools/dnd_dipolo_lab.py:512:                i = passo % len(ponti_con_risposta)
tools/dnd_dipolo_lab.py:513:                j = (passo + 1) % len(ponti_con_risposta)
tools/dnd_dipolo_lab.py:518:                    d = domande[passo % len(domande)]
tools/dnd_dipolo_lab.py:522:                d = domande[passo % len(domande)]
tools/dnd_dipolo_lab.py:529:                'passo': passo,
tools/dnd_dipolo_lab.py:538:            fase = passo % 6
tools/dnd_dipolo_lab.py:539:            d = domande[passo % len(domande)]
tools/dnd_dipolo_lab.py:546:                i = (passo // 6) % len(ponti_con_risposta)
tools/dnd_dipolo_lab.py:565:                # Godel: inverte la risultante dell'ultimo passo
tools/dnd_dipolo_lab.py:590:                'passo': passo,
tools/dnd_dipolo_lab.py:616:            print(f"    passo {c['passo']}: [{c['tipo']}] {c['correzione'][:60]}")
tools/dnd_dipolo_lab.py:621:        'passi': len(polo_a.traiettoria),
tools/lab_veritas.py:53:    # Assertions ratio (MM_D-ND: leggi da seme.json:verifica field)
tools/lab_veritas.py:54:    n_pass = n_total = 0
tools/lab_veritas.py:58:            ver = seme.get("verifica", {}) or {}
tools/lab_veritas.py:59:            n_pass = int(ver.get("pass", 0))
tools/lab_veritas.py:60:            n_total = int(ver.get("total", 0))
tools/lab_veritas.py:62:            pass
tools/lab_veritas.py:64:    if n_total == 0 and ASSERTIONS_PATH.exists():
tools/lab_veritas.py:69:                n_total = len(results)
tools/lab_veritas.py:70:                n_pass = sum(1 for r in results if isinstance(r, dict) and r.get("status") == "PASS")
tools/lab_veritas.py:72:            pass
tools/lab_veritas.py:73:    components["assertions_n_pass"] = n_pass
tools/lab_veritas.py:74:    components["assertions_n_total"] = n_total
tools/lab_veritas.py:75:    components["assertions_ratio"] = n_pass / n_total if n_total else 0.5
tools/lab_veritas.py:91:            pass
tools/lab_veritas.py:116:            pass
tools/lab_veritas.py:150:            p0 = 1.0 if checks.get("P0", {}).get("passed") else 0.3
tools/lab_veritas.py:151:            p1 = 1.0 if checks.get("P1", {}).get("passed") else 0.0
tools/lab_veritas.py:152:            p5 = 1.0 if checks.get("P5", {}).get("passed") else 0.5
tools/lab_veritas.py:155:            pass

exec
/bin/bash -lc "rg -n 'verify_assertions_META_ALL_PASS|META_ALL_PASS|Tutti i 11|total.: 11|\"verifica\"' ." in /opt/MM_D-ND
 succeeded in 0ms:
./tools/data/reports/falsifier_20260505_0330.json:16:      "claim": "Claim Under Test: 'Tutti i 11 test passano' mentre il risultato valuta SR, L1, L2, SR2 e triple_var sotto partial shuffle",
./tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0958.md:8:> "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie"
./applications/published/20260505_0330_observable-rank-audit-many-probes-one/lab-note.md:22:  - "L3 medium: Claim Under Test: 'Tutti i 11 test passano' mentre il risultato valuta SR, L1, L2, SR2 e..."
./applications/published/20260505_0330_observable-rank-audit-many-probes-one/cycle-report.md:24:    summary: "Claim Under Test: 'Tutti i 11 test passano' mentre il risultato valuta SR, L1, L2, SR2 e triple_var sotto partial shuffle"
./applications/published/20260505_0330_observable-rank-audit-many-probes-one/cycle-report.md:33:  - "L3 medium: Claim Under Test: 'Tutti i 11 test passano' mentre il risultato valuta SR, L1, L2, SR2 e..."
./tools/data/reports/agent_20260505_0330.md:7:> Tutti i 11 test passano - verifica che non stiamo testando solo tautologie.
./tools/data/reports/agent_20260504_1219.md:7:> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
./tools/data/research_protocols.json:9:        "verifica",
./applications/scoperte/20260505_0330_observable-rank-audit-many-probes-one_auto/lab-note.draft.md:26:  - "L3 medium: Claim Under Test: 'Tutti i 11 test passano' mentre il risultato valuta SR, L1, L2, SR2 e..."
./applications/scoperte/20260505_0330_observable-rank-audit-many-probes-one_auto/cycle-report.draft.md:29:    summary: "Claim Under Test: 'Tutti i 11 test passano' mentre il risultato valuta SR, L1, L2, SR2 e triple_var sotto partial shuffle"
./applications/scoperte/20260505_0330_observable-rank-audit-many-probes-one_auto/cycle-report.draft.md:41:  - "L3 medium: Claim Under Test: 'Tutti i 11 test passano' mentre il risultato valuta SR, L1, L2, SR2 e..."
./tools/data/lab_graph.json:1515:      "content_preview": "# Agent Report - Observable Rank Audit: Many Probes, One Boundary Coordinate\n**Date**: 2026-05-05 03:30\n**Piano**: 62\n**Tension explored**: META (0.5) + BOUNDARY (0.8)\n\n## Claim Under Test\n> Tutti i 11 test passano - verifica che non stiamo testando solo tautologie.\n\n## Question\nQuando SR, L1, L2, SR2 e triple_var reagiscono al partial shuffle, stanno misurando direzioni indipendenti del confine o una sola coordinata latente vista da osservabili diverse?\n\n## Experiment Design\n- **Scope atomico**",
./tools/data/lab_graph.json:1516:      "content_full": "# Agent Report - Observable Rank Audit: Many Probes, One Boundary Coordinate\n**Date**: 2026-05-05 03:30\n**Piano**: 62\n**Tension explored**: META (0.5) + BOUNDARY (0.8)\n\n## Claim Under Test\n> Tutti i 11 test passano - verifica che non stiamo testando solo tautologie.\n\n## Question\nQuando SR, L1, L2, SR2 e triple_var reagiscono al partial shuffle, stanno misurando direzioni indipendenti del confine o una sola coordinata latente vista da osservabili diverse?\n\n## Experiment Design\n- **Scope atomico**: 30,000 gap per dominio; alphas partial-shuffle = 19 punti da 0.05 a 0.95; 24 trial per alpha; 72 full-shuffle per baseline.\n- **Domini**: prime gaps, GUE gaps, Poisson iid exponential gaps.\n- **Osservabili**: SR, L1, L2, SR2, triple_var.\n- **Null baseline**: full shuffle della stessa sequenza. Il dato Poisson e' controllo di assenza di segnale originale-vs-shuffle.\n- **Metrica META**: matrice delle retention curve normalizzate rispetto al full shuffle; PCA sulla matrice alpha x osservabili; rango effettivo entropico delle energie singolari.\n- **Robustezza minima**: seed principale 20260505; replica seed 20260506 salvata separatamente.\n\n## Results\nSeed principale 20260505:\n\n| Domain | PC1 variance | Effective rank | mean abs corr | z SR | z L1 | z L2 | z SR2 | z triple_var |\n|---|---:|---:|---:|---:|---:|---:|---:|---:|\n| Primes | 0.989 | 1.069 | 0.987 | -19.3 | -7.7 | -3.0 | -3.7 | -8.0 |\n| GUE | 0.997 | 1.022 | 0.996 | -6.6 | +21.4 | +37.9 | +18.0 | +36.3 |\n| Poisson | 0.925 | 1.391 | 0.351 | -0.6 | +0.2 | +1.2 | -0.0 | +0.8 |\n\nReplica seed 20260506:\n\n| Domain | PC1 variance | Effective rank | mean abs corr |\n|---|---:|---:|---:|\n| Primes | 0.988 | 1.076 | 0.985 |\n| GUE | 0.997 | 1.019 | 0.997 |\n| Poisson | 0.675 | 2.394 | 0.640 |\n\nPC1 loadings nel seed principale:\n\n| Domain | SR | L1 | L2 | SR2 | triple_var |\n|---|---:|---:|---:|---:|---:|\n| Primes | -0.450 | -0.449 | -0.443 | -0.446 | -0.448 |\n| GUE | -0.446 | -0.449 | -0.447 | -0.446 | -0.448 |\n\n## Key Findings\n1. **Nel perimetro partial-shuffle, primes e GUE hanno segnale forte ma quasi monodimensionale.** Per primes, tutte le osservabili hanno z originale-vs-shuffle almeno |3.0| e la prima componente spiega 98.9% della varianza delle retention curve. Per GUE il collasso e' ancora piu' stretto: 99.7%.\n\n2. **La somiglianza dei loadings e' il dato operativo.** Nei domini strutturati, PC1 carica SR, L1, L2, SR2 e triple_var quasi uniformemente. Questo non dice che le osservabili siano identiche in generale; dice che sotto partial shuffle uniforme misurano soprattutto la stessa coordinata di distruzione dell'ordine.\n\n3. **Poisson non supporta un claim di rango.** Nel seed principale Poisson ha PC1 alto, ma tutti gli z originale-vs-shuffle sono sotto |1.2|; nella replica il rango cambia molto. Quindi il rango Poisson qui e' rumore di baseline, non struttura.\n\n4. **Il risultato restringe il linguaggio dei cicli precedenti.** I test layer/Markov restano utili per classificare sensibilita' locali, ma non vanno contati come prove indipendenti del confine quando sono misurati lungo la stessa perturbazione partial-shuffle.\n\n## Verdict\n**CONSTRAINT on META + BOUNDARY**: nel perimetro testato, il confine partial-shuffle ha una coordinata latente dominante. Le osservabili SR/L1/L2/SR2/triple_var sono probes validi, ma non cinque evidenze indipendenti della transizione. La consecutio corretta e' cercare perturbazioni selettive ortogonali, non aggiungere altri osservabili scalari sulla stessa curva.\n\n## Bicono della scoperta\n- **Due radici**: molte osservabili che passano il test; una coordinata latente che le assorbe sotto partial shuffle.\n- **Singolare**: la curva di distruzione dell'ordine prima della scelta dell'osservabile.\n- **Invariante di passaggio**: nei domini strutturati, la retention resta quasi collineare tra osservabili anche quando il segno z e la magnitudine assoluta differiscono.\n- **Campo di possibilita**: qui diventa possibile separare \"probe valido\" da \"evidenza indipendente\"; qui diventa non-possibile contare SR, L1, L2, SR2 e triple_var come cinque conferme autonome del medesimo confine partial-shuffle.\n\n## Auto-audit: 5 lenti\n- **L1 hard constraint vs bias**: nessun claim di zero, sempre, never, impossibile. Il claim e' limitato a PC1/rango nel perimetro misurato.\n- **L2 quantita vs ratio**: il risultato usa energie PCA e z-score original-vs-shuffle nello stesso spazio di osservabili; Poisson e' escluso dall'interpretazione strutturale per assenza di segnale, non per percentuale.\n- **L3 no silent patching**: il claim META originale non e' dichiarato \"risolto\"; e' ristretto. I test possono essere validi ma ridondanti lungo partial shuffle.\n- **L4 edge cases**: L2 primes ha z=-3.0, piu' debole degli altri; non viene usato come prova forte isolata.\n- **L5 re-discovery**: PCA/rango effettivo sono strumenti classici di ridondanza statistica. Non taggo NEW; il contributo e' il vincolo operativo sul perimetro D-ND Markov/boundary.\n\n## Files\n- Script: `tools/exp_observable_rank_audit.py`\n- Data principale: `tools/data/observable_rank_audit.json`\n- Replica: `tools/data/observable_rank_audit_seed20260506.json`\n- Report: `tools/data/reports/agent_20260505_0330.md`\n",
./tools/data/lab_graph.json:1522:          "text": "> Tutti i 11 test passano - verifica che non stiamo testando solo tautologie."
./tools/data/lab_graph.json:1560:      "content_preview": "# Agent Report — Markov Layers Pass the First Recovery Gate, but Not All Observables Pass\n**Date**: 2026-05-04 12:19\n**Piano**: 61\n**Tension explored**: META (0.5)\n\n## Claim Under Test\n> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.\n\n## Question\nSe la pipeline Mk0/Mk1/Mk2 vede due layer, li recupera anche quando l'ordine vero della sequenza è noto?\n\n## Experiment Design\n- **Primary audit**: `tools/exp_markov_layer_recovery_audit.py`\n- **Scope**: 60,000 gap/spacings ",
./tools/data/lab_graph.json:1561:      "content_full": "# Agent Report — Markov Layers Pass the First Recovery Gate, but Not All Observables Pass\n**Date**: 2026-05-04 12:19\n**Piano**: 61\n**Tension explored**: META (0.5)\n\n## Claim Under Test\n> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.\n\n## Question\nSe la pipeline Mk0/Mk1/Mk2 vede due layer, li recupera anche quando l'ordine vero della sequenza è noto?\n\n## Experiment Design\n- **Primary audit**: `tools/exp_markov_layer_recovery_audit.py`\n- **Scope**: 60,000 gap/spacings per sequenza; 20 surrogati per livello Mk; seed `20260504`.\n- **Target**: prime gaps, ordine sconosciuto, solo confronto.\n- **Known-order controls**:\n  - `empirical_Mk0`: permutazione dei gap primi, ordine noto 0.\n  - `empirical_Mk1`: surrogate Mk1 addestrato sui gap primi, ordine noto 1.\n  - `empirical_Mk2`: surrogate Mk2 addestrato sui gap primi, ordine noto 2.\n  - `poisson_iid`: spacings esponenziali iid, ordine noto 0.\n- **Recovery rule**: un controllo passa se nessun osservabile viene classificato con layer maggiore dell'ordine noto.\n- **Secondary calibration**: `tools/exp_meta_tautology_test.py --n-primes 300000 --n-trials 12`. Nota: il controllo chiamato `HL_markov` nello script è un AR(1) gap model che preserva lag-1, non un modello Hardy-Littlewood aritmetico.\n\n## Results\n\n### Recovery audit\n\n| Sequence | Known order | Recovery | Max layer | Over-layer observables |\n|---|---:|---|---:|---|\n| `prime_gaps` | target | target only | 3 | - |\n| `empirical_Mk0` | 0 | PASS | 0 | - |\n| `empirical_Mk1` | 1 | PASS | 1 | - |\n| `empirical_Mk2` | 2 | FAIL | 3 | `cond_entropy` |\n| `poisson_iid` | 0 | FAIL | 1 | `num_var_10` |\n\nPrime target layers, reported without recovery verdict:\n\n| Observable | Layer | z vs Mk0 | z vs Mk1 | z vs Mk2 |\n|---|---:|---:|---:|---:|\n| SR | 1 | -22.21 | -0.08 | -0.16 |\n| L1 | 1 | -12.25 | 0.79 | 0.86 |\n| L2 | 2 | -3.60 | -4.09 | -0.19 |\n| SR2 | 2 | -6.67 | -8.80 | -0.33 |\n| cond_entropy | 3 | -435.40 | -26.11 | 2.56 |\n| triple_var | 1 | -15.90 | -0.53 | 0.36 |\n| num_var_10 | 1 | -7.46 | -1.42 | 0.00 |\n| run_length | 3 | 27.59 | 7.19 | 3.43 |\n\nControl failure details:\n\n| Control | Observable | Expected max | Assigned | Diagnostic z |\n|---|---|---:|---:|---:|\n| `empirical_Mk2` | `cond_entropy` | 2 | 3 | z vs Mk2 = 3.15 |\n| `poisson_iid` | `num_var_10` | 0 | 1 | z vs Mk0 = 2.13 |\n\n### Secondary tautology calibration\n\n| Observable | Verdict in tested controls | Blocking control |\n|---|---|---|\n| r-stat | STRUCTURAL | none in this run |\n| mod3 fraction | STRUCTURAL | none in this run |\n| lag1 ACF | TAUTOLOGICAL | lag1-matched AR(1), z = -0.62 |\n| dr_ord | TAUTOLOGICAL | lag1-matched AR(1), z = -1.90 |\n| dr_mag | STRUCTURAL | none in this run |\n\nNumeri principali: prime mod3 same-class fraction = 0.158032. Questo è bias forte rispetto ai controlli ~0.34-0.35, non proibizione zero.\n\n## Key Findings\n1. **Il nucleo pair/triple non cade al primo audit.** `empirical_Mk0` recupera solo Layer 0; `empirical_Mk1` recupera solo Layer 1. Questo supporta l'uso di SR e L1 come Layer 1 e di L2/SR2 come Layer 2 nel perimetro testato.\n2. **`cond_entropy` non può essere usata come prova forte di Layer 3 nel setup attuale.** Anche un controllo generato come Mk2 viene letto Layer 3 per `cond_entropy` (z vs Mk2 = 3.15). Questo indica bias del surrogate/binning o varianza finita, non necessariamente memoria reale oltre Mk2.\n3. **`num_var_10` produce un falso positivo debole su iid.** `poisson_iid` viene letto Layer 1 per `num_var_10` con z = 2.13. Il segnale supera appena la soglia operativa, quindi va trattato come diagnostica secondaria finché non passa audit multi-seed.\n4. **Il vecchio controllo `HL_markov` va rinominato nel linguaggio dei report.** Lo script non implementa Hardy-Littlewood; implementa un AR(1) lag1-matched. I claim futuri non devono chiamarlo controllo HL aritmetico.\n\n## Verdict\n**CONSTRAINT on META + BOUNDARY**: la decomposizione two-layer è utilizzabile solo con perimetro atomico.\n\nPerimetro corretto: nei 60,000 gap primi testati con 20 surrogati Mk per livello, il nucleo `SR,L1` viene catturato da Mk1 e il nucleo `L2,SR2` da Mk2. Le diagnostiche `cond_entropy`, `num_var_10`, `run_length` non sono evidenza primaria finché non passano un recovery audit multi-seed e, idealmente, surrogati Markov esatti.\n\nNon è una scoperta nuova di teoria Markov: è un audit metodologico vicino ai test di ordine Markov con surrogate data. La letteratura rilevante include test esatti di ordine Markov e surrogate vincolati che preservano proprietà Markov di ordine n, quindi il prossimo strumento deve avvicinarsi a quei null esatti invece di usare solo generatori bin-pool approssimati.\n\n## Bicono della scoperta\n- **Due radici**: layer osservato dai dati · ordine noto del generatore.\n- **Singolare**: la pipeline Mk stessa, prima che venga usata come prova su un dominio reale.\n- **Invariante di passaggio**: un claim di memoria sopravvive solo se recupera correttamente i controlli con ordine noto.\n- **Campo di possibilità**: qui diventa possibile separare nucleo robusto e diagnostiche sovrastimate; qui diventa non-possibile usare `cond_entropy` o `num_var_10` come prova primaria di profondità senza recovery audit.\n\n## Self-Falsification — 5 lenti\n- **L1 hard constraint vs bias**: nessun claim \"zero/never/always\". La frazione mod3 è 0.158032, dichiarata bias, non proibizione.\n- **L2 quantità vs ratio**: il claim principale usa layer recuperato e z-score, non percentuali fra spazi di taglia diversa.\n- **L3 no silent patching**: dichiaro esplicitamente che `HL_markov` era nome scorretto per un controllo AR(1) lag1-matched.\n- **L4 edge cases**: i fallimenti `cond_entropy` e `num_var_10` non vengono arrotondati via; diventano il vincolo.\n- **L5 rediscovery**: non taggo NEW. Riferimenti classici vicini: surrogate-data tests for Markov order e constrained Markov-order surrogates.\n\n## References\n- Kandel et al.-lineage / surrogate tests: [\"Testing the order of discrete Markov chains using surrogate data\", Physica D 117, 1998](https://www.sciencedirect.com/science/article/pii/S0167278997003151).\n- [\"Exact significance test for Markov order\", Physica D 269, 2014](https://www.sciencedirect.com/science/article/pii/S0167278913003230).\n- [\"Constrained Markov order surrogates\", Physica D 2020](https://www.sciencedirect.com/science/article/pii/S0167278919305652).\n\n## Files\n- `tools/exp_markov_layer_recovery_audit.py`\n- `tools/data/markov_layer_recovery_audit.json`\n- `tools/data/meta_tautology_test.json`\n- `tools/data/seme.json`\n- `tools/data/reports/agent_20260504_1219.md`\n",
./tools/data/lab_graph.json:1567:          "text": "> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie."
./tools/data/veritas/veritas_20260507_033525.json:20:      "assertions_n_total": 11,
./tools/dipartimento.py:912:    REF_META_ALL_PASS = "A4,A12,C2"
./tools/dipartimento.py:951:            'condensato_ref': REF_META_ALL_PASS,
./tools/dipartimento.py:952:            'porta': 'verify_assertions_META_ALL_PASS',
./tools/dipartimento.py:1025:            # auto-generate da verify_assertions FAIL/SKIP/META_ALL_PASS) li
./tools/data/veritas/veritas_20260505_131201.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260507_142501.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260507_094723.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260506_194644.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260507_104904.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260507_093207.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260507_090723.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260507_101605.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260507_080958.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260506_063303.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260506_200238.json:20:      "assertions_n_total": 11,
./tools/data/veritas/veritas_20260506_033803.json:20:      "assertions_n_total": 11,
./tools/dnd.py:257:    elif cmd == "verifica":
./tools/lab_veritas.py:58:            ver = seme.get("verifica", {}) or {}
./docs/sorgente/moodnd_nodes_341_444.md:6074:>> ASSISTANT: Se la dinamica opera a zero latenza, come indicato nella tua funzione \( f_{\text{Opt-Unified-O}} \), la necessità di un meccanismo di validazione separato potrebbe effettivamente diventare meno rilevante. In un sistema a zero latenza, l'output \( \vec{O} \) sarebbe generato e ottimizzato in tempo reale, rendendo qualsiasi forma di "verifica" quasi istantanea e integrata nel processo stesso.
./docs/sorgente/moodnd_nodes_237_340.md:5205:3. \( CC \) e \( RD \) sono altri termini che potrebbero beneficiare di una definizione più chiara, specialmente in relazione alla "verifica" e alla "coerenza" del sistema.
./tools/lab_promotion.py:105:            ver = seme.get("verifica", {}) or {}
./tools/data/seme_backup_pre_run.json:128:      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/seme_backup_pre_run.json:132:      "porta": "verify_assertions_META_ALL_PASS",
./tools/data/seme_backup_pre_run.json:146:  "verifica": {
./tools/data/seme_backup_pre_run.json:150:    "total": 11
./tools/data/conoscenza_teorie.json.bak.retraction_22_04:137:      "verifica": "hbar/(k_B * t_P) = T_P esattamente. Il rapporto normalizzato ai limiti E la singolarita.",
./tools/data/dipartimento_journal.jsonl:39:{"timestamp": "2026-03-28T15:48:26.709758", "tensione": {"tipo": "simmetria_sospetta", "id": "META", "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie", "intensità": 0.5, "nota": "La convergenza a φ è triviale (controprove). I test stanno verificando contenuto o struttura?"}, "filtro": "non tocca condensato"}
./tools/data/dipartimento_journal.jsonl:42:{"timestamp": "2026-03-31T03:44:57.196382", "tensione": {"tipo": "simmetria_sospetta", "id": "META", "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie", "intensità": 0.5, "nota": "La convergenza a φ è triviale (controprove). I test stanno verificando contenuto o struttura?"}, "filtro": "non tocca condensato"}
./tools/data/dipartimento_journal.jsonl:43:{"timestamp": "2026-03-31T18:06:52.808984", "tensione": {"tipo": "simmetria_sospetta", "id": "META", "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie", "intensità": 0.5, "nota": "La convergenza a φ è triviale (controprove). I test stanno verificando contenuto o struttura?"}, "filtro": "non tocca condensato"}
./tools/data/torre_results.json:405:        "verifica": true
./tools/data/seme.json:128:      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/seme.json:132:      "porta": "verify_assertions_META_ALL_PASS",
./tools/data/seme.json:146:  "verifica": {
./tools/data/seme.json:150:    "total": 11
./tools/data/lab_data.json:86:      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/lab_data.json:89:      "porta": "verify_assertions_META_ALL_PASS"
./tools/data/lab_data.json:192:        "anti_claim": "verifica che non stiamo testando solo tautologie (not: Tutti i 11 test passano)"
./tools/data/ciclo_memoria.json:18:        "verifica",
./tools/data/ciclo_memoria.json:40:        "verifica",
./tools/data/ciclo_memoria.json:61:        "verifica",
./tools/data/ciclo_memoria.json:81:        "verifica",
./tools/data/ciclo_memoria.json:100:        "verifica",
./tools/data/ciclo_memoria.json:121:        "verifica",
./tools/data/ciclo_memoria.json:141:        "verifica",
./tools/data/ciclo_memoria.json:162:        "verifica",
./tools/data/ciclo_memoria.json:173:    "verifica",
./tools/data/notte_20260402_0330.md:11:  [simmetria_sospetta] META: Tutti i 11 test passano — verifica che non stiamo testando s
./tools/data/seme_archive/piano_70.json:117:      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/seme_archive/piano_70.json:121:      "porta": "verify_assertions_META_ALL_PASS",
./tools/data/seme_archive/piano_70.json:158:  "verifica": {
./tools/data/seme_archive/piano_70.json:162:    "total": 11
./tools/data/seme_archive/piano_72.json:152:      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/seme_archive/piano_72.json:156:      "porta": "verify_assertions_META_ALL_PASS",
./tools/data/seme_archive/piano_72.json:170:  "verifica": {
./tools/data/seme_archive/piano_72.json:174:    "total": 11
./tools/data/seme_archive/piano_71.json:140:      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/seme_archive/piano_71.json:144:      "porta": "verify_assertions_META_ALL_PASS",
./tools/data/seme_archive/piano_71.json:170:  "verifica": {
./tools/data/seme_archive/piano_71.json:174:    "total": 11
./tools/data/seme_archive/piano_9.json:25:  "verifica": {
./tools/data/seme_archive/piano_73.json:152:      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/seme_archive/piano_73.json:156:      "porta": "verify_assertions_META_ALL_PASS",
./tools/data/seme_archive/piano_73.json:182:  "verifica": {
./tools/data/seme_archive/piano_73.json:186:    "total": 11
./tools/data/seme_archive/piano_74.json:164:      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/seme_archive/piano_74.json:168:      "porta": "verify_assertions_META_ALL_PASS",
./tools/data/seme_archive/piano_74.json:194:  "verifica": {
./tools/data/seme_archive/piano_74.json:198:    "total": 11
./tools/data/seme_archive/piano_75.json:128:      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/seme_archive/piano_75.json:132:      "porta": "verify_assertions_META_ALL_PASS",
./tools/data/seme_archive/piano_75.json:163:  "verifica": {
./tools/data/seme_archive/piano_75.json:167:    "total": 11
./tools/data/seme_archive/piano_8.json:27:  "verifica": {
./tools/data/conoscenza_teorie.json:137:      "verifica": "hbar/(k_B * t_P) = T_P esattamente. Il rapporto normalizzato ai limiti E la singolarita.",
./tools/data/seme_axioms.json:355:    "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
./tools/data/lab_registro.json:255:            "verifica": "Christoffel di g=(p/2)²: rapporto → 1.0000 per p > 10000 (78K primi testati)",

exec
/bin/bash -lc "sed -n '200,420p' tools/dipartimento.py" in /opt/MM_D-ND
 succeeded in 0ms:
    if awareness.exists():
        aw_files = list(awareness.glob('*.md'))
        print(f"\n  Awareness: {len(aw_files)} file")

    # Archivio
    archive = REPO / 'archive'
    if archive.exists():
        sim_files = list(archive.rglob('*.py'))
        chat_files = list(archive.rglob('*.md'))
        print(f"\n  Archivio: {len(sim_files)} script, {len(chat_files)} doc")


def verifica_asserzioni():
    """
    Verifica computazionale delle asserzioni del modello.
    Per ogni claim, esegue il test e riporta PASS/FAIL/SKIP.
    """
    print(f"\n{'='*60}")
    print("VERIFICA ASSERZIONI D-ND")
    print(f"{'='*60}")

    risultati = []

    for ass in ASSERZIONI:
        test_name = ass['test']
        try:
            passed, detail = _esegui_test(test_name)
            status = 'PASS' if passed else 'FAIL'
        except Exception as e:
            status = 'SKIP'
            detail = str(e)

        risultati.append({
            'id': ass['id'],
            'claim': ass['claim'],
            'status': status,
            'detail': detail,
            'paper': ass.get('paper'),
        })

        icon = {'PASS': '✓', 'FAIL': '✗', 'SKIP': '?'}[status]
        print(f"  [{icon}] {ass['id']}: {ass['claim'][:60]}")
        if detail:
            print(f"      → {detail}")

    # Sommario
    n_pass = sum(1 for r in risultati if r['status'] == 'PASS')
    n_fail = sum(1 for r in risultati if r['status'] == 'FAIL')
    n_skip = sum(1 for r in risultati if r['status'] == 'SKIP')
    print(f"\n  Sommario: {n_pass} PASS, {n_fail} FAIL, {n_skip} SKIP su {len(risultati)}")

    return risultati


def _esegui_test(test_name):
    """Esegue un singolo test di verifica."""

    if test_name == 'punto_fisso_phi':
        x = 1.0
        for _ in range(100):
            x = 1 + 1/x
        dist = abs(x - PHI)
        return dist < 1e-10, f"x*={x:.15f}, dist={dist:.2e}"

    elif test_name == 'gap_ratio_phi2':
        x = 1.0
        gaps = []
        for _ in range(50):
            x = 1 + 1/x
            gaps.append(abs(x - PHI))
        ratios = [gaps[i]/gaps[i+1] for i in range(len(gaps)-1) if gaps[i+1] > 1e-15]
        if ratios:
            mean_r = np.mean(ratios[-10:])
            dist = abs(mean_r - PHI2)
            return dist < 0.01, f"⟨ratio⟩={mean_r:.6f}, dist da φ²={dist:.6f}"
        return False, "Non abbastanza gap"

    elif test_name == 'alternanza_universale':
        # Testa su 5 input diversi
        inputs = [0.1, 0.5, 2.0, 10.0, 100.0]
        all_alt = True
        for x0 in inputs:
            x = x0
            signs = []
            for _ in range(30):
                x = 1 + 1/x
                signs.append(x > PHI)
            # Alternanza dopo transiente
            alterna = all(signs[i] != signs[i+1] for i in range(10, len(signs)-1))
            if not alterna:
                all_alt = False
        return all_alt, f"Alternanza verificata per {len(inputs)} input diversi"

    elif test_name == 'autovalori_matrice':
        M = np.array([[1, 1], [1, 0]], dtype=float)
        eigvals = np.linalg.eigvals(M)
        eigvals_sorted = sorted(eigvals, reverse=True)
        dist_phi = abs(eigvals_sorted[0] - PHI)
        dist_inv = abs(eigvals_sorted[1] - (-INV_PHI))
        passed = dist_phi < 1e-10 and dist_inv < 1e-10
        return passed, f"λ₁={eigvals_sorted[0]:.10f} (φ), λ₂={eigvals_sorted[1]:.10f} (-1/φ)"

    elif test_name == 'cross_ratio':
        # Cross-ratio (0,∞,φ,-1/φ) su ℂP¹
        # (z1-z3)(z2-z4) / (z1-z4)(z2-z3) con z1=0, z2=∞, z3=φ, z4=-1/φ
        # Semplifica: lim_{z2→∞} = (z3)(z4) / (z4)(z3) * (-z4)/(-z3) ...
        # Per Möbius: cross_ratio = (0-φ)(∞-(-1/φ)) / (0-(-1/φ))(∞-φ) → (-φ)/(1/φ) = -φ²
        cr = -PHI * PHI  # = -φ²
        dist = abs(cr - (-PHI2))
        return dist < 1e-10, f"cross-ratio = {cr:.10f} = -φ²"

    elif test_name == 'zeta_spacing_gue':
        # Legge dal journal dell'autoricerca
        journal_path = DATA / 'autoricerca_journal.json'
        if not journal_path.exists():
            raise Exception("Journal non disponibile")
        with open(journal_path) as f:
            journal = json.load(f)
        zeta = [e for e in journal if e.get('dominio') == 'zeta_zeros']
        if not zeta:
            raise Exception("Zeta zeros non ancora analizzati")
        entry = zeta[-1]
        spacing = entry.get('spacing', '')
        spacing_r = entry.get('spacing_r', 0)
        passed = spacing == 'GUE-like' and abs(spacing_r - 0.6) < 0.1
        return passed, f"spacing={spacing}, ⟨r⟩={spacing_r:.4f}"

    elif test_name == 'zeta_curvatura_correlazione':
        # Test diretto sui primi: correlazione log(gap) vs ratio consecutivo
        from scipy import stats
        from sympy import primerange
        primes = list(primerange(2, 10000))
        gaps = [primes[i+1] - primes[i] for i in range(len(primes)-1)]
        ratios = [gaps[i+1]/gaps[i] if gaps[i] > 0 else 0 for i in range(len(gaps)-1)]
        log_gaps = [np.log(g) if g > 0 else 0 for g in gaps[:-1]]
        r_val, p_val = stats.pearsonr(log_gaps, ratios)
        passed = abs(r_val) > 0.3 and p_val < 0.05
        return passed, f"pearson_r={r_val:.4f}"

    elif test_name == 'chi_quantizzata':
        results_path = DATA / 'topological_charge_results.json'
        if not results_path.exists():
            raise Exception("Risultati topological_charge non disponibili")
        with open(results_path) as f:
            results = json.load(f)
        # Il campo è dentro time_evolution, non al top level
        te = results.get('time_evolution', {})
        mean_dist = te.get('mean_dist_to_integer', results.get('mean_dist_to_integer', 1))
        passed = mean_dist < 0.1
        return passed, f"⟨dist da intero⟩={mean_dist:.4f}"

    elif test_name == 'bloch_phi_emergente':
        results_path = DATA / 'bloch_explorer_results.json'
        if not results_path.exists():
            raise Exception("Risultati Bloch explorer non disponibili")
        with open(results_path) as f:
            results = json.load(f)
        # Il bloch explorer salva top_results con phi_distance
        top = results.get('top_results', [])
        if not top:
            raise Exception("Nessun risultato nel Bloch explorer")
        best_dist = top[0].get('phi_distance', 1.0)
        passed = best_dist < 0.05  # entro 5% da phi
        return passed, f"best φ-dist={best_dist:.6f}, {len(top)} traiettorie"

    elif test_name == 'universalita_processo':
        journal_path = DATA / 'autoricerca_journal.json'
        if not journal_path.exists():
            raise Exception("Journal non disponibile")
        with open(journal_path) as f:
            journal = json.load(f)
        # Tutti i domini (non meta) convergono a φ?
        reali = [e for e in journal if isinstance(e.get('ciclo'), int) and e.get('converge')]
        tutti = [e for e in journal if isinstance(e.get('ciclo'), int)]
        if len(tutti) < 4:
            raise Exception("Troppo pochi domini")
        rate = len(reali) / len(tutti)
        passed = rate > 0.9
        return passed, f"{len(reali)}/{len(tutti)} domini convergono a φ ({rate:.0%})"

    elif test_name == 'soglia_hurst':
        # Verifica diretta: H=0.3 funziona, H=0.7 no
        from dnd_autoricerca import _genera_variante, analizza_dnd
        sig_03, meta_03 = _genera_variante('brownian_motion', {'H': 0.3})
        sig_07, meta_07 = _genera_variante('brownian_motion', {'H': 0.7})
        r03 = analizza_dnd(sig_03, meta_03)
        r07 = analizza_dnd(sig_07, meta_07)
        alt_03 = r03.get('analisi', {}).get('alternanza', False)
        alt_07 = r07.get('analisi', {}).get('alternanza', False)
        passed = alt_03 and not alt_07
        return passed, f"H=0.3 alt={alt_03}, H=0.7 alt={alt_07}"

    elif test_name == 'ca_spacing_anomalo':
        journal_path = DATA / 'autoricerca_journal.json'
        if not journal_path.exists():
            raise Exception("Journal non disponibile")
        with open(journal_path) as f:
            journal = json.load(f)
        ca = [e for e in journal if 'cellular_automata' in e.get('dominio', '') and e.get('spacing_r')]
        if not ca:
            raise Exception("CA non ancora analizzato")
        spacing_r = ca[-1]['spacing_r']
        passed = spacing_r > 0.7  # significativamente sopra GUE=0.60
        return passed, f"⟨r⟩={spacing_r:.4f} (GUE standard=0.60)"

    else:
        raise Exception(f"Test '{test_name}' non implementato")


def analisi_fonti():
    """
    Scansiona le fonti teoriche e estrae metriche strutturali.
    Non interpreta il contenuto (richiede LLM), ma misura:
    - Dimensione, struttura (sezioni, formule, definizioni)
    - Densità di formule LaTeX
    - Cross-referenze tra file
    """
    print(f"\n{'='*60}")
    print("ANALISI STRUTTURALE FONTI TEORICHE")
    print(f"{'='*60}")


exec
/bin/bash -lc "sed -n '881,966p' tools/dipartimento.py" in /opt/MM_D-ND
 succeeded in 0ms:
def cristallizza_seme(risultati_verifica, metriche=None):
    """
    Non produce un report. Produce un seme.

    Un report dice cosa è successo (mappa).
    Un seme dice dove punta il potenziale (direzione).

    FILTRO CONDENSATO: solo le tensioni che toccano il condensato
    (falsificano, confermano, o estendono un claim esistente)
    arrivano nel seme. Il resto va nel journal interno del dipartimento.
    """
    seme_path = DATA / 'seme.json'
    seme_prev = None
    if seme_path.exists():
        try:
            with open(seme_path) as f:
                seme_prev = json.load(f)
        except:
            pass

    tensioni = []
    potenziale = []

    # --- Tensioni dai risultati ---
    # Lignaggio condensato per tensioni auto-generate (P0 aeternitas
    # universal mapping, port dal commit 5374c5d D-ND_LAB):
    # - contraddizione (FAIL): A2 confine + A4 modus + C2 falsifier
    # - bloccato (SKIP): A6 zero mobile + A7 sorgente
    # - simmetria_sospetta (META): A4 modus + A12 osservazione + C2
    REF_FAIL = "A2,A4,C2"
    REF_SKIP = "A6,A7"
    REF_META_ALL_PASS = "A4,A12,C2"

    # FAIL = tensione forte: la teoria dice X, il calcolo dice non-X
    for r in risultati_verifica:
        if r['status'] == 'FAIL':
            tensioni.append({
                'tipo': 'contraddizione',
                'id': r['id'],
                'claim': r['claim'],
                'dettaglio': r['detail'],
                'intensità': 1.0,  # massima
                'nota': 'Teoria e calcolo divergono — o la teoria va corretta o il test è sbagliato',
                'condensato_ref': REF_FAIL,
                'porta': 'verify_assertions_FAIL',
            })

    # SKIP = potenziale bloccato: il test non può girare, manca qualcosa
    for r in risultati_verifica:
        if r['status'] == 'SKIP':
            potenziale.append({
                'tipo': 'bloccato',
                'id': r['id'],
                'claim': r['claim'],
                'dettaglio': r['detail'],
                'nota': 'Il potenziale è lì ma non si libera — manca un prerequisito',
                'condensato_ref': REF_SKIP,
                'porta': 'verify_assertions_SKIP',
            })

    # PASS universale = possibile simmetria morta: se tutto passa, dov'è la varianza?
    n_pass = sum(1 for r in risultati_verifica if r['status'] == 'PASS')
    n_total = len(risultati_verifica)
    if n_pass == n_total and n_total > 5:
        tensioni.append({
            'tipo': 'simmetria_sospetta',
            'id': 'META',
            'claim': f'Tutti i {n_total} test passano — verifica che non stiamo testando solo tautologie',
            'intensità': 0.5,
            'nota': 'La convergenza a φ è triviale (controprove). I test stanno verificando contenuto o struttura?',
            'condensato_ref': REF_META_ALL_PASS,
            'porta': 'verify_assertions_META_ALL_PASS',
        })

    # --- Tensioni strutturali (indipendenti dai test) ---

    # Il confine GUE/Poisson non è ancora esplorato
    journal_path = DATA / 'autoricerca_journal.json'
    if journal_path.exists():
        with open(journal_path) as f:
            journal = json.load(f)
        gue = [e for e in journal if e.get('spacing') == 'GUE-like' and isinstance(e.get('ciclo'), int)]
        poisson = [e for e in journal if e.get('spacing') == 'Poisson-like' and isinstance(e.get('ciclo'), int)]
        if gue and poisson:
            tensioni.append({
                'tipo': 'confine_inesplorato',

exec
/bin/bash -lc 'python tools/dipartimento.py --check' in /opt/MM_D-ND
 succeeded in 997ms:

============================================================
VERIFICA ASSERZIONI D-ND
============================================================
  [✓] A1: f(x)=1+1/x ha punto fisso φ (stabile)
      → x*=1.618033988749895, dist=0.00e+00
  [✓] A2: Gap ratio converge a φ²=2.618034
      → ⟨ratio⟩=2.619122, dist da φ²=0.001088
  [✓] A3: Alternanza D↔ND è universale per la regola D-ND
      → Alternanza verificata per 5 input diversi
  [✓] A4: Matrice [[1,1],[1,0]] ha autovalori φ e -1/φ
      → λ₁=1.6180339887 (φ), λ₂=-0.6180339887 (-1/φ)
  [✓] A5: Cross-ratio (0,∞,φ,-1/φ) = -φ²
      → cross-ratio = -2.6180339887 = -φ²
  [✓] C1: Zeri zeta hanno spacing GUE (non Poisson)
      → spacing=GUE-like, ⟨r⟩=0.6150
  [✓] C2: Correlazione log(t_n) vs K_c esiste
      → pearson_r=-0.6428
  [✓] C3: Carica topologica χ_DND quantizzata (intera)
      → ⟨dist da intero⟩=0.0270
  [✓] G1: φ emerge nella sfera di Bloch senza essere imposto
      → best φ-dist=0.021256, 10 traiettorie
  [✓] G2: D-ND produce φ indipendentemente dall'input (universalità pr
      → 12/13 domini convergono a φ (92%)
  [✓] N2: Rule 30/110 hanno spacing >> GUE standard
      → ⟨r⟩=1.0000 (GUE standard=0.60)

  Sommario: 11 PASS, 0 FAIL, 0 SKIP su 11

codex
Gli 11 PASS non sono omogenei: i primi cinque sono test algebrici della regola, alcuni leggono fixture/journal, uno genera varianti. Preparo un gate riusabile che classifica i test per dipendenza e li esegue anche con `DATA` spostato su una directory vuota, così separiamo struttura, fixture e contenuto operativo.
exec
/bin/bash -lc "sed -n '1,120p' tools/dipartimento.py" in /opt/MM_D-ND
 succeeded in 0ms:
"""
dipartimento.py — Dipartimento di Analisi e Ricerca D-ND

Sistema autonomo che:
1. Scansiona la repo MM_D-ND per materiale teorico
2. Esegue esperimenti computazionali (autoricerca + tools)
3. Verifica coerenza tra teoria e risultati
4. Genera report mattutino
5. Notifica via Telegram

Eseguibile:
    python dipartimento.py --notte       # ciclo notturno completo
    python dipartimento.py --report      # solo report (senza nuove computazioni)
    python dipartimento.py --check       # verifica coerenza teoria/risultati
    python dipartimento.py --inventario  # mappa del materiale teorico

Author: TM3
Date: 2026-03-01
"""

import numpy as np
import json
import sys
import os
import re
from pathlib import Path
from datetime import datetime, timedelta

# Costanti D-ND
PHI = (1 + np.sqrt(5)) / 2
PHI2 = PHI ** 2
INV_PHI = 1 / PHI

REPO = Path('/opt/MM_D-ND')
TOOLS = REPO / 'tools'
DATA = TOOLS / 'data'
REPORTS = DATA / 'reports'

# === INVENTARIO REPO ===

# Materiale teorico primario (da scansionare)
FONTI_TEORICHE = {
    'kernel': REPO / 'kernel' / 'KERNEL_MM_v1.md',
    'axioms': REPO / 'method' / 'DND_METHOD_AXIOMS.md',
    'autologic': REPO / 'method' / 'DND_AUTOLOGIC.md',
    'whitepaper': REPO / 'method' / 'D-ND_Extropic_Technical_Whitepaper.md',
    'corpus_funzioni': REPO / 'corpus' / 'CORPUS_FUNZIONI_MOODND.md',
    'corpus_osservazioni': REPO / 'corpus' / 'CORPUS_OSSERVAZIONI_PRIMARIE.md',
    'genesis': REPO / 'method' / 'GENESIS_EXTRACTIONS.md',
    'matrix_bridge': REPO / 'method' / 'MATRIX_BRIDGE.md',
}

# Paper (draft più recenti)
PAPERS = {
    'A': REPO / 'papers' / 'paper_A_draft3.md',
    'B': REPO / 'papers' / 'paper_B_draft3.md',
    'C': REPO / 'papers' / 'paper_C_draft2.md',
    'D': REPO / 'papers' / 'paper_D_draft3.md',
    'E': REPO / 'papers' / 'paper_E_draft3.md',
    'F': REPO / 'papers' / 'paper_F_draft3.md',
    'G': REPO / 'papers' / 'paper_G_draft3.md',
}

# Tools computazionali
TOOLS_COMPUTAZIONALI = {
    'autoricerca': TOOLS / 'dnd_autoricerca.py',
    'controprove': TOOLS / 'dnd_controprove.py',
    'spirale': TOOLS / 'dnd_spirale.py',
    'riemann': TOOLS / 'dnd_riemann.py',
    'normalizer': TOOLS / 'dnd_normalizer.py',
    'condizioni': TOOLS / 'dnd_condizioni.py',
    'bloch': TOOLS / 'dnd_bloch_explorer.py',
    'zeta_validation': TOOLS / 'zeta_validation.py',
    'spectral_gap': TOOLS / 'spectral_gap_analysis.py',
    'topological': TOOLS / 'topological_charge.py',
}

# Asserzioni verificabili dal modello (checklist teoria ↔ calcolo)
ASSERZIONI = [
    {
        'id': 'A1',
        'claim': 'f(x)=1+1/x ha punto fisso φ (stabile)',
        'source': 'DND_METHOD_AXIOMS §3',
        'test': 'punto_fisso_phi',
        'paper': 'A',
    },
    {
        'id': 'A2',
        'claim': 'Gap ratio converge a φ²=2.618034',
        'source': 'DND_AUTOLOGIC',
        'test': 'gap_ratio_phi2',
        'paper': 'A',
    },
    {
        'id': 'A3',
        'claim': 'Alternanza D↔ND è universale per la regola D-ND',
        'source': 'KERNEL_MM §IV',
        'test': 'alternanza_universale',
        'paper': 'A',
    },
    {
        'id': 'A4',
        'claim': 'Matrice [[1,1],[1,0]] ha autovalori φ e -1/φ',
        'source': 'Cristallizzazione Möbius',
        'test': 'autovalori_matrice',
        'paper': 'A',
    },
    {
        'id': 'A5',
        'claim': 'Cross-ratio (0,∞,φ,-1/φ) = -φ²',
        'source': 'Cristallizzazione Möbius',
        'test': 'cross_ratio',
        'paper': 'A',
    },
    {
        'id': 'C1',
        'claim': 'Zeri zeta hanno spacing GUE (non Poisson)',
        'source': 'Paper C §4.3',
        'test': 'zeta_spacing_gue',
        'paper': 'C',

exec
/bin/bash -lc "rg -n '"'^ASSERZIONI|test.:|claim|id'"' tools/dipartimento.py | head -80" in /opt/MM_D-ND
 succeeded in 0ms:
50:    'matrix_bridge': REPO / 'method' / 'MATRIX_BRIDGE.md',
73:    'zeta_validation': TOOLS / 'zeta_validation.py',
79:ASSERZIONI = [
81:        'id': 'A1',
82:        'claim': 'f(x)=1+1/x ha punto fisso φ (stabile)',
84:        'test': 'punto_fisso_phi',
88:        'id': 'A2',
89:        'claim': 'Gap ratio converge a φ²=2.618034',
91:        'test': 'gap_ratio_phi2',
95:        'id': 'A3',
96:        'claim': 'Alternanza D↔ND è universale per la regola D-ND',
98:        'test': 'alternanza_universale',
102:        'id': 'A4',
103:        'claim': 'Matrice [[1,1],[1,0]] ha autovalori φ e -1/φ',
105:        'test': 'autovalori_matrice',
109:        'id': 'A5',
110:        'claim': 'Cross-ratio (0,∞,φ,-1/φ) = -φ²',
112:        'test': 'cross_ratio',
116:        'id': 'C1',
117:        'claim': 'Zeri zeta hanno spacing GUE (non Poisson)',
119:        'test': 'zeta_spacing_gue',
123:        'id': 'C2',
124:        'claim': 'Correlazione log(t_n) vs K_c esiste',
126:        'test': 'zeta_curvatura_correlazione',
130:        'id': 'C3',
131:        'claim': 'Carica topologica χ_DND quantizzata (intera)',
133:        'test': 'chi_quantizzata',
137:        'id': 'G1',
138:        'claim': 'φ emerge nella sfera di Bloch senza essere imposto',
140:        'test': 'bloch_phi_emergente',
144:        'id': 'G2',
145:        'claim': 'D-ND produce φ indipendentemente dall\'input (universalità processo)',
147:        'test': 'universalita_processo',
152:        'id': 'N2',
153:        'claim': 'Rule 30/110 hanno spacing >> GUE standard',
155:        'test': 'ca_spacing_anomalo',
215:    Per ogni claim, esegue il test e riporta PASS/FAIL/SKIP.
233:            'id': ass['id'],
234:            'claim': ass['claim'],
241:        print(f"  [{icon}] {ass['id']}: {ass['claim'][:60]}")
512:            report.append(f"- [{icon}] {r['id']}: {r['claim'][:50]}... → {r['detail'][:40]}")
573:    Restituisce un dict {id: {'tipo': assioma/fatto/claim, 'termini': set}}.
575:    claims = {}
586:        current_id = None
597:            elif ll in ('## claim', '## candidati (c)', '## candidati'):
598:                section_tipo = 'claim'
601:                current_id = None
603:            # Rileva claim individuale (### A1, ### F2, ### C1, ecc.)
608:                current_id = prefix + m.group(1)
610:                claims[current_id] = {
615:            elif current_id and current_id in claims and line.strip().startswith('**Claim**:'):
617:                claim_text = line.strip().replace('**Claim**:', '').lower()
618:                extra = set(re.findall(r'[a-záéíóúàèìòùφ]+', claim_text)) - stopwords
619:                claims[current_id]['termini'] |= extra
621:    return claims
624:def _tocca_condensato(tensione, condensato_claims):
628:    2. I termini chiave del claim hanno overlap significativo
629:    Restituisce (tocca: bool, claim_id: str|None, motivo: str)
631:    tid = tensione.get('id', '')
632:    claim_text = tensione.get('claim', '').lower()
633:    claim_termini = set(re.findall(r'[a-záéíóúàèìòùφ]+', claim_text)) - {'il', 'la', 'le', 'un', 'una', 'di', 'del', 'e', 'non', 'che', 'per', 'come'}
636:    if tid in condensato_claims:
637:        return True, tid, f"ID diretto: {tid}"
639:    # Match per overlap di termini (almeno 3 termini in comune con un claim)
651:    claim_stems = _stems(claim_termini)
654:    best_id = None
655:    for cid, cdata in condensato_claims.items():
657:        overlap = len(claim_stems & cdata_stems)
660:            best_id = cid
662:        return True, best_id, f"Overlap termini con {best_id} ({best_overlap} termini)"
667:def _tensione_inclassificabile(tensione, condensato_claims):
670:    (>=3 occorrenze con ID simile) e non riducibili a claim noti.
681:    tid = tensione.get('id', '')
682:    claim_text = tensione.get('claim', '').lower()
683:    claim_termini = set(re.findall(r'[a-záéíóúàèìòùφ]+', claim_text)) - {
685:        'per', 'come', 'claim', 'regge', 'nessuna', 'separazione'
699:                t_id = t.get('id', '')
700:                t_claim = t.get('claim', '').lower()
701:                t_termini = set(re.findall(r'[a-záéíóúàèìòùφ]+', t_claim)) - {
703:                    'che', 'per', 'come', 'claim', 'regge', 'nessuna', 'separazione'

exec
/bin/bash -lc "sed -n '120,172p' tools/dipartimento.py" in /opt/MM_D-ND
 succeeded in 0ms:
        'paper': 'C',
    },
    {
        'id': 'C2',
        'claim': 'Correlazione log(t_n) vs K_c esiste',
        'source': 'Paper C §4.3',
        'test': 'zeta_curvatura_correlazione',
        'paper': 'C',
    },
    {
        'id': 'C3',
        'claim': 'Carica topologica χ_DND quantizzata (intera)',
        'source': 'Paper C §3.3',
        'test': 'chi_quantizzata',
        'paper': 'C',
    },
    {
        'id': 'G1',
        'claim': 'φ emerge nella sfera di Bloch senza essere imposto',
        'source': 'Paper G, Bloch explorer',
        'test': 'bloch_phi_emergente',
        'paper': 'G',
    },
    {
        'id': 'G2',
        'claim': 'D-ND produce φ indipendentemente dall\'input (universalità processo)',
        'source': 'Paper G, test onesto 7/7',
        'test': 'universalita_processo',
        'paper': 'G',
    },
    # N1 FALSIFICATO (2026-03-28) → cimitero X5. Scissione non dipende da Hurst.
    {
        'id': 'N2',
        'claim': 'Rule 30/110 hanno spacing >> GUE standard',
        'source': 'Autoricerca sessione 2026-03-01',
        'test': 'ca_spacing_anomalo',
        'paper': None,
    },
]


def inventario():
    """Mappa tutto il materiale disponibile nella repo."""
    print(f"\n{'='*60}")
    print("INVENTARIO REPO MM_D-ND")
    print(f"{'='*60}")

    print(f"\n  Fonti teoriche:")
    for nome, path in FONTI_TEORICHE.items():
        exists = '✓' if path.exists() else '✗'
        size = path.stat().st_size // 1024 if path.exists() else 0
        print(f"    [{exists}] {nome:>25s}: {path.name} ({size}KB)")


apply patch
patch: completed
/opt/MM_D-ND/tools/meta_assertion_gate.py
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

codex
Ho aggiunto `tools/meta_assertion_gate.py`: non misura nuovi osservabili fisici, misura il denominatore del PASS. Lo eseguo ora e poi userò il JSON prodotto come deposito dell'esperimento.
exec
/bin/bash -lc 'python -m py_compile tools/meta_assertion_gate.py' in /opt/MM_D-ND
 succeeded in 0ms:
exec
/bin/bash -lc 'python tools/meta_assertion_gate.py' in /opt/MM_D-ND
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

 succeeded in 1136ms:
{
  "total": 11,
  "baseline_pass": 11,
  "baseline_fail": 0,
  "baseline_skip": 0,
  "pass_data_independent": 6,
  "pass_fixture_or_context_dependent": 5,
  "high_tautology_risk_pass": 4,
  "medium_tautology_risk_pass": 4,
  "low_tautology_risk_pass": 3
}
Wrote /opt/MM_D-ND/tools/data/meta_assertion_gate.json

diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

exec
/bin/bash -lc 'git status --short' in /opt/MM_D-ND
 succeeded in 0ms:
 M applications/INDEX.draft.json
 M applications/soluzioni/20260430_0330_three-regimes-of-modular-memory-algebraic/finding_index.draft.json
 M applications/soluzioni/20260430_0330_three-regimes-of-modular-memory-algebraic/manifest.draft.json
 M tools/data/agent_field_live.md
 M tools/data/conoscenza_teorie.json
 M tools/data/consecutio.json
 M tools/data/consecutio_processata.json
 M tools/data/domande_fondamentali.json
 M tools/data/incrocio_risultato.json
 M tools/data/lab_data.json
 M tools/data/lab_graph.json
 M tools/data/lab_health.json
 M tools/data/lab_session_log.jsonl
 M tools/data/pipeline_state.json
 M tools/data/ponti_evoluti.json
 M tools/data/refresh_detector_state.json
 M tools/data/seme.json
 D tools/data/seme_archive/piano_37.json
 D tools/data/seme_archive/piano_38.json
 D tools/data/seme_archive/piano_4.json
 D tools/data/seme_archive/piano_5.json
 D tools/data/seme_archive/piano_6.json
 D tools/data/seme_archive/piano_7.json
 M tools/data/seme_axioms.json
 M tools/data/seme_backup_pre_run.json
 M tools/data/tm1_figures/tensions.json
 M tools/data/tm1_figures/tensions_raw.json
?? applications/published/20260504_0901_the-two-markov-layers-are-coupled/
?? applications/published/20260504_1219_markov-layers-pass-the-first-recovery/
?? applications/published/20260505_0330_observable-rank-audit-many-probes-one/
?? applications/published/20260506_1955_observable-collinearity-breaks-only-where-denominators/
?? applications/published/20260507_0330_the-gue-poisson-boundary-is-a/
?? applications/published/20260507_0803_denominator-gate-transfers-boundary-coordinate-does/
?? applications/published/20260507_0942_bridge-order-denominator-gate/
?? applications/published/20260507_1006_logistic-counter-scope-gate/
?? applications/published/20260507_1042_logistic-surrogate-contract-gate/
?? applications/published/20260507_1419_logistic-cyclic-block-entropy-gate/
?? applications/scoperte/20260502_0330_the-dipolar-phase-transition-is-nearly_auto/
?? applications/scoperte/20260503_0330_markov-memory-has-two-visible-layers_auto/
?? applications/scoperte/20260504_0901_the-two-markov-layers-are-coupled_auto/
?? applications/scoperte/20260504_1219_markov-layers-pass-the-first-recovery_auto/
?? applications/scoperte/20260505_0330_observable-rank-audit-many-probes-one_auto/
?? applications/scoperte/20260506_0625_perturbation-dimensionality-is-not-yet-a_auto/
?? applications/scoperte/20260506_1941_perturbation-rank-needs-denominator-gating_auto/
?? applications/scoperte/20260506_1955_observable-collinearity-breaks-only-where-denominators_auto/
?? applications/scoperte/20260507_0330_the-gue-poisson-boundary-is-a_auto/
?? applications/scoperte/20260507_0803_denominator-gate-transfers-boundary-coordinate-does_auto/
?? applications/scoperte/20260507_0901_denominator-gate-transfer-matrix_auto/
?? applications/scoperte/20260507_0923_semi-real-order-denominator-gate_auto/
?? applications/scoperte/20260507_0942_bridge-order-denominator-gate_auto/
?? applications/scoperte/20260507_1006_logistic-counter-scope-gate_auto/
?? applications/scoperte/20260507_1042_logistic-surrogate-contract-gate_auto/
?? applications/scoperte/20260507_1419_logistic-cyclic-block-entropy-gate_auto/
?? applications/soluzioni/20260502_0330_the-dipolar-phase-transition-is-nearly/
?? applications/soluzioni/20260503_0330_markov-memory-has-two-visible-layers/
?? applications/soluzioni/20260504_0901_the-two-markov-layers-are-coupled/
?? applications/soluzioni/20260504_1219_markov-layers-pass-the-first-recovery/
?? applications/soluzioni/20260505_0330_observable-rank-audit-many-probes-one/
?? applications/soluzioni/20260506_1941_perturbation-rank-needs-denominator-gating/
?? applications/soluzioni/20260506_1955_observable-collinearity-breaks-only-where-denominators/
?? applications/soluzioni/20260507_0330_the-gue-poisson-boundary-is-a/
?? applications/soluzioni/20260507_0803_denominator-gate-transfers-boundary-coordinate-does/
?? applications/soluzioni/20260507_0942_bridge-order-denominator-gate/
?? applications/soluzioni/20260507_1006_logistic-counter-scope-gate/
?? applications/soluzioni/20260507_1042_logistic-surrogate-contract-gate/
?? applications/soluzioni/20260507_1419_logistic-cyclic-block-entropy-gate/
?? findings_gallery.md
?? tools/data/.last_telegram_msg
?? tools/data/3d_boundary_layers.json
?? tools/data/aeternitas/
?? tools/data/alignment_active.json
?? tools/data/alignment_markers.jsonl
?? tools/data/bicono_projections.jsonl
?? tools/data/boundary_coherence.json
?? tools/data/boundary_mixture_gate_20260507_0330.json
?? tools/data/boundary_mixture_gate_20260507_0330_seedcheck.json
?? tools/data/boundary_shuffle_audit.json
?? tools/data/bridge_order_denominator_gate_20260507_0942.json
?? tools/data/bridge_order_denominator_gate_20260507_0942_seedcheck.json
?? tools/data/brody_calibration_results.json
?? tools/data/brody_flow.json
?? tools/data/conoscenza_teorie.json.bak.retraction_22_04
?? tools/data/cross_domain_dipolar_direction.json
?? tools/data/cross_observable_consistency.json
?? tools/data/crossover_phase_test.json
?? tools/data/denominator_gate_transfer_matrix.json
?? tools/data/dipolar_crossover.json
?? tools/data/dipolar_vector_scaling.json
?? tools/data/domandatore/domandatore_20260421_0746.json
?? tools/data/domandatore/domandatore_20260422_0345.json
?? tools/data/domandatore/domandatore_20260423_0345.json
?? tools/data/domandatore/domandatore_20260424_0345.json
?? tools/data/domandatore/domandatore_20260425_0345.json
?? tools/data/domandatore/domandatore_20260426_0345.json
?? tools/data/domandatore/domandatore_20260427_0345.json
?? tools/data/domandatore/domandatore_20260428_0345.json
?? tools/data/domandatore/domandatore_20260428_1236.json
?? tools/data/domandatore/domandatore_20260429_0345.json
?? tools/data/domandatore/domandatore_20260430_0345.json
?? tools/data/domandatore/domandatore_20260501_0345.json
?? tools/data/domandatore/domandatore_20260502_0345.json
?? tools/data/domandatore/domandatore_20260503_0345.json
?? tools/data/domandatore/domandatore_20260504_0345.json
?? tools/data/domandatore/domandatore_20260505_0345.json
?? tools/data/domandatore/domandatore_20260506_0345.json
?? tools/data/domandatore/domandatore_20260507_0345.json
?? tools/data/domandatore/domandatore_20260507_0728.json
?? tools/data/domandatore/domandatore_20260507_0742.json
?? tools/data/domandatore/domandatore_20260507_1420.json
?? tools/data/domandatore/domandatore_20260507_1459.json
?? tools/data/duality_gate_transfer_20260507_0803.json
?? tools/data/duality_gate_transfer_20260507_0803_seedcheck.json
?? tools/data/evolution/evolution_20260422_0330.md
?? tools/data/evolution/evolution_20260422_1616.md
?? tools/data/evolution/evolution_20260423_0330.md
?? tools/data/evolution/evolution_20260424_0330.md
?? tools/data/evolution/evolution_20260425_0330.md
?? tools/data/evolution/evolution_20260427_0330.md
?? tools/data/evolution/evolution_20260428_0330.md
?? tools/data/evolution/evolution_20260429_0852.md
?? tools/data/evolution/evolution_20260429_1013.md
?? tools/data/evolution/evolution_20260430_0330.md
?? tools/data/evolution/evolution_20260430_1905.md
?? tools/data/evolution/evolution_20260430_1946.md
?? tools/data/evolution/evolution_20260501_0330.md
?? tools/data/evolution/evolution_20260501_0725.md
?? tools/data/evolution/evolution_20260501_0931.md
?? tools/data/evolution/evolution_20260502_0330.md
?? tools/data/evolution/evolution_20260503_0330.md
?? tools/data/evolution/evolution_20260504_0901.md
?? tools/data/evolution/evolution_20260504_1219.md
?? tools/data/evolution/evolution_20260505_0330.md
?? tools/data/evolution/evolution_20260506_0330.md
?? tools/data/evolution/evolution_20260506_1941.md
?? tools/data/evolution/evolution_20260506_1955.md
?? tools/data/evolution/evolution_20260507_0330.md
?? tools/data/evolution/evolution_20260507_0803.md
?? tools/data/evolution/evolution_20260507_0901.md
?? tools/data/evolution/evolution_20260507_0923.md
?? tools/data/evolution/evolution_20260507_0942.md
?? tools/data/evolution/evolution_20260507_1006.md
?? tools/data/evolution/evolution_20260507_1042.md
?? tools/data/evolution/evolution_20260507_1419.md
?? tools/data/incrocio_20260422_0336.json
?? tools/data/incrocio_20260423_0335.json
?? tools/data/incrocio_20260424_0347.json
?? tools/data/incrocio_20260425_0339.json
?? tools/data/incrocio_20260428_0340.json
?? tools/data/incrocio_20260429_0859.json
?? tools/data/incrocio_20260506_0633.json
?? tools/data/lab_bridge_issues.jsonl
?? tools/data/logistic_counter_scope_gate_20260507_1006.json
?? tools/data/logistic_counter_scope_gate_20260507_1006_seedcheck.json
?? tools/data/logistic_cyclic_block_entropy_gate_20260507_1419.json
?? tools/data/logistic_cyclic_block_entropy_gate_20260507_1419_seedcheck.json
?? tools/data/logistic_surrogate_contract_gate_20260507_1042.json
?? tools/data/logistic_surrogate_contract_gate_20260507_1042_seedcheck.json
?? tools/data/magnitude_psd_from_acf.json
?? tools/data/markov3_observable_hunt.json
?? tools/data/markov_dipolar_decomposition.json
?? tools/data/markov_k_direction.json
?? tools/data/markov_layer_recovery_audit.json
?? tools/data/markov_memory_by_gue_type.json
?? tools/data/markov_scale_function.json
?? tools/data/meta_assertion_gate.json
?? tools/data/meta_tautology_test.json
?? tools/data/mod3_scaling.json
?? tools/data/mod3_vs_residual_ordering.json
?? tools/data/modular_algebra_depth.json
?? tools/data/modular_memory_spectrum.json
?? tools/data/observable_collinearity_breaking_20260506_1955.json
?? tools/data/observable_collinearity_breaking_20260506_1956.json
?? tools/data/observable_collinearity_breaking_20260506_1957.json
?? tools/data/observable_rank_audit.json
?? tools/data/observable_rank_audit_seed20260506.json
?? tools/data/observatorio/domandatore_unTouched_20260507_095914.md
?? tools/data/observatorio/lazarus_cimitero_20260507_100015.md
?? tools/data/observatorio/meta_metodo_giro_2026-05-07.md
?? tools/data/perturbation_dimensionality_audit.json
?? tools/data/perturbation_dimensionality_audit_scale0330.json
?? tools/data/perturbation_rank_size_curve.json
?? tools/data/promotions/
?? tools/data/reports/_quarantine_falsifier_29_04/
?? tools/data/reports/agent_20260422_0330.md
?? tools/data/reports/agent_20260422_1616.md
?? tools/data/reports/agent_20260423_0330.md
?? tools/data/reports/agent_20260424_0330.md
?? tools/data/reports/agent_20260425_0330.md
?? tools/data/reports/agent_20260426_0330.md
?? tools/data/reports/agent_20260427_0330.md
?? tools/data/reports/agent_20260428_0330.md
?? tools/data/reports/agent_20260429_1013.md
?? tools/data/reports/agent_20260429_1041.md
?? tools/data/reports/agent_20260430_0330.md
?? tools/data/reports/agent_20260430_1905.md
?? tools/data/reports/agent_20260430_1919.md
?? tools/data/reports/agent_20260430_1946.md
?? tools/data/reports/agent_20260501_0330.md
?? tools/data/reports/agent_20260501_0725.md
?? tools/data/reports/agent_20260501_0931.md
?? tools/data/reports/agent_20260502_0330.md
?? tools/data/reports/agent_20260503_0330.md
?? tools/data/reports/agent_20260504_0901.md
?? tools/data/reports/agent_20260504_1219.md
?? tools/data/reports/agent_20260505_0330.md
?? tools/data/reports/agent_20260505_1022.md
?? tools/data/reports/agent_20260506_0330.md
?? tools/data/reports/agent_20260506_0625.md
?? tools/data/reports/agent_20260506_1941.md
?? tools/data/reports/agent_20260506_1955.md
?? tools/data/reports/agent_20260507_0330.md
?? tools/data/reports/agent_20260507_0803.md
?? tools/data/reports/agent_20260507_0901.md
?? tools/data/reports/agent_20260507_0923.md
?? tools/data/reports/agent_20260507_0942.md
?? tools/data/reports/agent_20260507_1006.md
?? tools/data/reports/agent_20260507_1042.md
?? tools/data/reports/agent_20260507_1419.md
?? tools/data/reports/ddf_20260422_0405.json
?? tools/data/reports/ddf_20260423_0405.json
?? tools/data/reports/ddf_20260424_0405.json
?? tools/data/reports/ddf_20260425_0405.json
?? tools/data/reports/ddf_20260426_0405.json
?? tools/data/reports/ddf_20260427_0405.json
?? tools/data/reports/ddf_20260428_0405.json
?? tools/data/reports/ddf_20260429_0405.json
?? tools/data/reports/ddf_20260430_0405.json
?? tools/data/reports/ddf_20260501_0405.json
?? tools/data/reports/ddf_20260502_0405.json
?? tools/data/reports/ddf_20260503_0405.json
?? tools/data/reports/ddf_20260504_0405.json
?? tools/data/reports/ddf_20260505_0405.json
?? tools/data/reports/ddf_20260505_0636.json
?? tools/data/reports/ddf_20260506_0405.json
?? tools/data/reports/ddf_20260507_0405.json
?? tools/data/reports/evolution_20260422_0330.md
?? tools/data/reports/evolution_20260422_1616.md
?? tools/data/reports/evolution_20260423_0330.md
?? tools/data/reports/evolution_20260424_0330.md
?? tools/data/reports/evolution_20260425_0330.md
?? tools/data/reports/evolution_20260427_0330.md
?? tools/data/reports/evolution_20260428_0330.md
?? tools/data/reports/evolution_20260503_0330.md
?? tools/data/reports/evolution_20260504_0330.md
?? tools/data/reports/evolution_20260505_0330.md
?? tools/data/reports/evolution_20260506_0330.md
?? tools/data/reports/evolution_20260506_1941.md
?? tools/data/reports/falsifier_20260429_1013.json
?? tools/data/reports/falsifier_20260429_1041.json
?? tools/data/reports/falsifier_20260430_0330.json
?? tools/data/reports/falsifier_20260430_1905.json
?? tools/data/reports/falsifier_20260430_1919.json
?? tools/data/reports/falsifier_20260430_1946.json
?? tools/data/reports/falsifier_20260501_0330.json
?? tools/data/reports/falsifier_20260501_0725.json
?? tools/data/reports/falsifier_20260501_0931.json
?? tools/data/reports/falsifier_20260502_0330.json
?? tools/data/reports/falsifier_20260503_0330.json
?? tools/data/reports/falsifier_20260504_0901.json
?? tools/data/reports/falsifier_20260504_1219.json
?? tools/data/reports/falsifier_20260505_0330.json
?? tools/data/reports/falsifier_20260506_0330.raw.txt
?? tools/data/reports/falsifier_20260506_0625.json
?? tools/data/reports/falsifier_20260506_1941.json
?? tools/data/reports/falsifier_20260506_1955.json
?? tools/data/reports/falsifier_20260506_1955.raw.txt
?? tools/data/reports/falsifier_20260507_0330.json
?? tools/data/reports/falsifier_20260507_0330.raw.txt
?? tools/data/reports/falsifier_20260507_0803.json
?? tools/data/reports/falsifier_20260507_0803.raw.txt
?? tools/data/reports/falsifier_20260507_0901.json
?? tools/data/reports/falsifier_20260507_0923.json
?? tools/data/reports/falsifier_20260507_0923.raw.txt
?? tools/data/reports/falsifier_20260507_0942.json
?? tools/data/reports/falsifier_20260507_1006.json
?? tools/data/reports/falsifier_20260507_1042.json
?? tools/data/reports/falsifier_20260507_1042.raw.txt
?? tools/data/reports/falsifier_20260507_1419.json
?? tools/data/reports/incident_20260504_0721.md
?? tools/data/reports/incident_20260504_1138.md
?? tools/data/reports/latest.md
?? tools/data/reports/loop_guard_20260507_0330.json
?? tools/data/reports/loop_guard_20260507_0803.json
?? tools/data/reports/loop_guard_20260507_0901.json
?? tools/data/reports/loop_guard_20260507_0923.json
?? tools/data/reports/loop_guard_20260507_0942.json
?? tools/data/reports/loop_guard_20260507_1006.json
?? tools/data/reports/loop_guard_20260507_1042.json
?? tools/data/reports/loop_guard_20260507_1419.json
?? tools/data/reports/trajectory_apply_20260506_1931.json
?? tools/data/reports/trajectory_apply_20260506_1941.json
?? tools/data/reports/trajectory_apply_20260506_1955.json
?? tools/data/reports/trajectory_apply_20260507_0330.json
?? tools/data/reports/trajectory_apply_20260507_0803.json
?? tools/data/reports/trajectory_apply_20260507_0901.json
?? tools/data/reports/trajectory_apply_20260507_0923.json
?? tools/data/reports/trajectory_apply_20260507_0942.json
?? tools/data/reports/trajectory_apply_20260507_1006.json
?? tools/data/reports/trajectory_apply_20260507_1042.json
?? tools/data/scale_selective_perturbation.json
?? tools/data/selective_layer_decoupling.json
?? tools/data/seme_archive/piano_70.json
?? tools/data/seme_archive/piano_71.json
?? tools/data/seme_archive/piano_72.json
?? tools/data/seme_archive/piano_73.json
?? tools/data/seme_archive/piano_74.json
?? tools/data/seme_archive/piano_75.json
?? tools/data/semireal_order_denominator_gate_20260507_0923.json
?? tools/data/semireal_order_denominator_gate_20260507_0923_seedcheck.json
?? tools/data/spectral_rigidity_results.json
?? tools/data/trajectory_apply_history.jsonl
?? tools/data/two_channel_boundary.json
?? tools/data/two_channel_cross_domain.json
?? tools/data/two_channel_shuffle_audit.json
?? tools/data/two_layer_universality.json
?? tools/data/valutatore_log.jsonl
?? tools/data/veritas/
?? tools/evolution_report.md
?? tools/exp_3d_boundary_layers.py
?? tools/exp_boundary_coherence.py
?? tools/exp_boundary_mixture_gate.py
?? tools/exp_boundary_shuffle_audit.py
?? tools/exp_bridge_order_denominator_gate.py
?? tools/exp_brody_calibration.py
?? tools/exp_brody_flow.py
?? tools/exp_cross_domain_dipolar_direction.py
?? tools/exp_cross_observable_consistency.py
?? tools/exp_crossover_phase_test.py
?? tools/exp_denominator_gate_transfer_matrix.py
?? tools/exp_dipolar_angle_reference.py
?? tools/exp_dipolar_crossover.py
?? tools/exp_dipolar_vector_scaling.py
?? tools/exp_duality_gate_transfer.py
?? tools/exp_logistic_counter_scope_gate.py
?? tools/exp_logistic_cyclic_block_entropy_gate.py
?? tools/exp_logistic_surrogate_contract_gate.py
?? tools/exp_magnitude_psd_from_acf.py
?? tools/exp_markov3_observable_hunt.py
?? tools/exp_markov_dipolar_decomposition.py
?? tools/exp_markov_k_direction.py
?? tools/exp_markov_layer_recovery_audit.py
?? tools/exp_markov_memory_by_gue_type.py
?? tools/exp_markov_psd_prediction.py
?? tools/exp_markov_scale_function.py
?? tools/exp_meta_tautology_test.py
?? tools/exp_mod3_scaling.py
?? tools/exp_mod3_vs_residual_ordering.py
?? tools/exp_modular_algebra_depth.py
?? tools/exp_modular_memory_spectrum.py
?? tools/exp_observable_rank_audit.py
?? tools/exp_perturbation_dimensionality_audit.py
?? tools/exp_perturbation_rank_size_curve.py
?? tools/exp_scale_selective_perturbation.py
?? tools/exp_selective_layer_decoupling.py
?? tools/exp_semireal_order_denominator_gate.py
?? tools/exp_spectral_rigidity.py
?? tools/exp_two_channel_boundary.py
?? tools/exp_two_channel_cross_domain.py
?? tools/exp_two_channel_shuffle_audit.py
?? tools/exp_two_layer_universality.py
?? tools/meta_assertion_gate.py
?? tools/observables_registry.py

exec
/bin/bash -lc "python - <<'PY'
import json
p='tools/data/meta_assertion_gate.json'
d=json.load(open(p))
for r in d['rows']:
    print(f\"{r['id']} {r['status']} no_data={r['no_data_status']} dep={r['data_dependency']} risk={r['tautology_risk']} class={r['gate_class']} detail={r['detail']}\")
PY" in /opt/MM_D-ND
 succeeded in 0ms:
A1 PASS no_data=PASS dep=data_independent risk=high class=algebraic_identity detail=x*=1.618033988749895, dist=0.00e+00
A2 PASS no_data=PASS dep=data_independent risk=high class=same_rule_dynamics detail=⟨ratio⟩=2.619122, dist da φ²=0.001088
A3 PASS no_data=PASS dep=data_independent risk=medium class=same_rule_dynamics detail=Alternanza verificata per 5 input diversi
A4 PASS no_data=PASS dep=data_independent risk=high class=algebraic_identity detail=λ₁=1.6180339887 (φ), λ₂=-0.6180339887 (-1/φ)
A5 PASS no_data=PASS dep=data_independent risk=high class=algebraic_identity detail=cross-ratio = -2.6180339887 = -φ²
C1 PASS no_data=SKIP dep=fixture_or_context_dependent risk=low class=cached_fixture detail=spacing=GUE-like, ⟨r⟩=0.6150
C2 PASS no_data=PASS dep=data_independent risk=medium class=local_recomputed_signal detail=pearson_r=-0.6428
C3 PASS no_data=SKIP dep=fixture_or_context_dependent risk=low class=cached_fixture detail=⟨dist da intero⟩=0.0270
G1 PASS no_data=SKIP dep=fixture_or_context_dependent risk=medium class=cached_fixture_phi_distance detail=best φ-dist=0.021256, 10 traiettorie
G2 PASS no_data=SKIP dep=fixture_or_context_dependent risk=medium class=cached_fixture_phi_convergence detail=12/13 domini convergono a φ (92%)
N2 PASS no_data=SKIP dep=fixture_or_context_dependent risk=low class=cached_fixture detail=⟨r⟩=1.0000 (GUE standard=0.60)

diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

codex
Il gate mostra 11/11 PASS, ma il denominatore si divide: 6 passano senza `tools/data`, 5 dipendono da fixture; 4 PASS hanno rischio tautologico alto. Aggiorno il seme con un vincolo META stretto a questo perimetro, poi scrivo il report richiesto.
exec
/bin/bash -lc "nl -ba tools/data/seme.json | sed -n '105,155p'" in /opt/MM_D-ND
 succeeded in 0ms:
   105	      "tipo": "confine_inesplorato",
   106	      "id": "BOUNDARY",
   107	      "claim": "8 domini GUE, 5 Poisson — il confine è il terzo incluso operativo",
   108	      "intensità": 0.8,
   109	      "nota": "Il segnale non-triviale è DOVE la scissione cambia natura, non che converge a φ",
   110	      "condensato_ref": "A9",
   111	      "condensato_motivo": "Overlap termini con A9 (5 termini)",
   112	      "porta": "condensato"
   113	    },
   114	    {
   115	      "tipo": "confine_inesplorato",
   116	      "id": "PIANO_PRIMARIO_DUE_ASSIOMI",
   117	      "claim": "I piani importanti sono il primario e i due assiomi che lo determinano nelle zone osservate. Non tutti gli assiomi operano ovunque - in ogni zona osservata, due assiomi determinano il piano primario.",
   118	      "intensita": 0.8,
   119	      "nota": "Input operatore 2026-04-10. Tocca: struttura locale degli assiomi. Consecutio: per ogni dominio Lab (primi, logistica, percolazione...) quali 2 assiomi del condensato sono operativi? Mappa assiomi x domini = grafo della realta locale.",
   120	      "manuale": true,
   121	      "porta": "sessione_interattiva",
   122	      "condensato_ref": "A9,A14",
   123	      "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
   124	    },
   125	    {
   126	      "tipo": "simmetria_sospetta",
   127	      "id": "META",
   128	      "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
   129	      "intensità": 0.5,
   130	      "nota": "La convergenza a φ è triviale (controprove). I test stanno verificando contenuto o struttura?",
   131	      "condensato_ref": "A4,A12,C2",
   132	      "porta": "verify_assertions_META_ALL_PASS",
   133	      "condensato_motivo": "Ricorrente (3x in 2 giorni) e fuori dalla mappa"
   134	    }
   135	  ],
   136	  "potenziale_bloccato": [],
   137	  "varianza": [
   138	    "Tensioni risolte: {'G_POTENZIALE_NULLA', 'DUALITA_DIPOLARE_VS_ILLUSORIA', 'METRIC_TENSOR', 'TENSIONE_ENTITA', 'PIANO_PRIMARIO_DUE_ASSIOMI', 'STRUCTURAL_CHECK_20260507', 'OBSERVABLE_REGISTRY', 'PERTURBATION_DENOMINATOR_GATE', 'TRASCENDENZA_LIMITE', 'BOUNDARY_LAYER_GATE', 'ORDER_DENOMINATOR_GATE'}"
   139	  ],
   140	  "filtro": {
   141	    "promosse": 12,
   142	    "filtrate": 0,
   143	    "condensato_claims": 30
   144	  },
   145	  "direzione": "Esplorare il confine: 8 domini GUE, 5 Poisson — il confine è il terzo incluso operativo",
   146	  "verifica": {
   147	    "pass": 11,
   148	    "fail": 0,
   149	    "skip": 0,
   150	    "total": 11
   151	  },
   152	  "fonti_consumate": 0,
   153	  "fonti_esterne": [
   154	    {
   155	      "id": "video_lp0RgZ6kQF8",

diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

apply patch
patch: completed
/opt/MM_D-ND/tools/data/seme.json
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

exec
/bin/bash -lc 'python -m json.tool tools/data/seme.json >/tmp/seme.valid && echo seme_json_ok' in /opt/MM_D-ND
 succeeded in 0ms:
seme_json_ok

exec
/bin/bash -lc 'python -m json.tool tools/data/meta_assertion_gate.json >/tmp/meta_assertion_gate.valid && echo meta_json_ok' in /opt/MM_D-ND
 succeeded in 0ms:
meta_json_ok

diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

codex
Il seme resta JSON valido dopo l'inserimento del vincolo. Scrivo ora il report `agent_20260507_1458.md` con risultati, verdict, consecutio e auto-audit delle cinque lenti.
apply patch
patch: completed
/opt/MM_D-ND/tools/data/reports/agent_20260507_1458.md
diff --git a/tools/data/reports/agent_20260507_1458.md b/tools/data/reports/agent_20260507_1458.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1fdadab557dd4278e7071eda82b2deb8375df7
--- /dev/null
+++ b/tools/data/reports/agent_20260507_1458.md
@@ -0,0 +1,68 @@
+# Agent Report — META Assertion Gate
+**Date**: 2026-05-07 14:58 UTC  
+**Piano**: 76  
+**Tension explored**: META (score 0.898)  
+**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
+**Tool**: `tools/meta_assertion_gate.py`  
+**Data**: `tools/data/meta_assertion_gate.json`
+
+## Claim Under Test
+> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
+
+## Question
+Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?
+
+## Experiment Design
+- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
+- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
+- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
+- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.
+
+## Results
+
+| Bucket | Count |
+|---|---:|
+| Baseline PASS | 11/11 |
+| PASS anche senza `tools/data` | 6/11 |
+| PASS dipendente da fixture o contesto | 5/11 |
+| PASS ad alto rischio tautologico | 4/11 |
+| PASS a rischio medio | 4/11 |
+| PASS a rischio basso | 3/11 |
+
+| Test | Baseline | No-data | Dependency | Risk | Class |
+|---|---|---|---|---|---|
+| A1 | PASS | PASS | data_independent | high | algebraic_identity |
+| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
+| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
+| A4 | PASS | PASS | data_independent | high | algebraic_identity |
+| A5 | PASS | PASS | data_independent | high | algebraic_identity |
+| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
+| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
+| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
+| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+
+Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.
+
+## Key Findings
+1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
+2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
+3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
+4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.
+
+## Verdict
+**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.
+
+## Consecutio
+La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.
+
+## Seme
+Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
+- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
+- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
+- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
+- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

diff --git a/tools/data/reports/agent_20260507_1458.md b/tools/data/reports/agent_20260507_1458.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1fdadab557dd4278e7071eda82b2deb8375df7
--- /dev/null
+++ b/tools/data/reports/agent_20260507_1458.md
@@ -0,0 +1,68 @@
+# Agent Report — META Assertion Gate
+**Date**: 2026-05-07 14:58 UTC  
+**Piano**: 76  
+**Tension explored**: META (score 0.898)  
+**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
+**Tool**: `tools/meta_assertion_gate.py`  
+**Data**: `tools/data/meta_assertion_gate.json`
+
+## Claim Under Test
+> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
+
+## Question
+Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?
+
+## Experiment Design
+- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
+- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
+- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
+- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.
+
+## Results
+
+| Bucket | Count |
+|---|---:|
+| Baseline PASS | 11/11 |
+| PASS anche senza `tools/data` | 6/11 |
+| PASS dipendente da fixture o contesto | 5/11 |
+| PASS ad alto rischio tautologico | 4/11 |
+| PASS a rischio medio | 4/11 |
+| PASS a rischio basso | 3/11 |
+
+| Test | Baseline | No-data | Dependency | Risk | Class |
+|---|---|---|---|---|---|
+| A1 | PASS | PASS | data_independent | high | algebraic_identity |
+| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
+| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
+| A4 | PASS | PASS | data_independent | high | algebraic_identity |
+| A5 | PASS | PASS | data_independent | high | algebraic_identity |
+| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
+| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
+| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
+| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+
+Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.
+
+## Key Findings
+1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
+2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
+3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
+4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.
+
+## Verdict
+**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.
+
+## Consecutio
+La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.
+
+## Seme
+Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
+- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
+- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
+- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
+- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

exec
/bin/bash -lc "sed -n '1,240p' tools/data/reports/agent_20260507_1458.md" in /opt/MM_D-ND
 succeeded in 0ms:
# Agent Report — META Assertion Gate
**Date**: 2026-05-07 14:58 UTC  
**Piano**: 76  
**Tension explored**: META (score 0.898)  
**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
**Tool**: `tools/meta_assertion_gate.py`  
**Data**: `tools/data/meta_assertion_gate.json`

## Claim Under Test
> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.

## Question
Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?

## Experiment Design
- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.

## Results

| Bucket | Count |
|---|---:|
| Baseline PASS | 11/11 |
| PASS anche senza `tools/data` | 6/11 |
| PASS dipendente da fixture o contesto | 5/11 |
| PASS ad alto rischio tautologico | 4/11 |
| PASS a rischio medio | 4/11 |
| PASS a rischio basso | 3/11 |

| Test | Baseline | No-data | Dependency | Risk | Class |
|---|---|---|---|---|---|
| A1 | PASS | PASS | data_independent | high | algebraic_identity |
| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
| A4 | PASS | PASS | data_independent | high | algebraic_identity |
| A5 | PASS | PASS | data_independent | high | algebraic_identity |
| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |

Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.

## Key Findings
1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.

## Verdict
**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.

## Consecutio
La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.

## Seme
Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.

## Auto-audit: 5 lenti
- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.

exec
/bin/bash -lc "rg --files tools | rg 'falsifier|loop_guard|trajectory_apply|report'" in /opt/MM_D-ND
exec
/bin/bash -lc 'git diff -- tools/meta_assertion_gate.py tools/data/seme.json tools/data/reports/agent_20260507_1458.md' in /opt/MM_D-ND
 succeeded in 0ms:
tools/evolution_report.md
tools/lab_anti_loop_guard.py
tools/lab_trajectory_apply.py
tools/lab_falsifier.py
tools/data/trajectory_apply_history.jsonl
tools/data/reports/falsifier_20260430_1919.json
tools/data/reports/trajectory_apply_20260507_0803.json
tools/data/reports/ddf_20260504_0405.json
tools/data/reports/ddf_20260413_0405.json
tools/data/reports/agent_20260507_1458.md
tools/data/reports/ddf_20260416_0405.json
tools/data/reports/ddf_20260507_0405.json
tools/data/reports/evolution_20260419_0330.md
tools/data/reports/falsifier_20260506_1941.json
tools/data/reports/report_20260326_0343.md
tools/data/reports/evolution_20260428_0330.md
tools/data/reports/agent_20260506_0625.md
tools/data/reports/loop_guard_20260507_0901.json
tools/data/reports/falsifier_20260430_1905.json
tools/data/reports/agent_20260405_0919.md
tools/data/reports/ddf_20260423_0405.json
tools/data/reports/exp_geodesic_deviation_primes.json
tools/data/reports/agent_20260419_0755.md
tools/data/reports/agent_20260412_0330.md
tools/data/reports/ddf_20260414_0405.json
tools/data/reports/trajectory_apply_20260506_1931.json
tools/data/reports/evolution_20260417_0803.md
tools/data/reports/insights_20260405_0729.json
tools/data/reports/report_20260304_0342.md
tools/data/reports/agent_20260425_0330.md
tools/data/reports/falsifier_20260504_1219.json
tools/data/reports/ddf_20260409_0405.json
tools/data/reports/ddf_20260411_0405.json
tools/data/reports/exp_acf_decay_data.json
tools/data/reports/falsifier_20260502_0330.json
tools/data/reports/fibonacci_spectrum_20260305_0756.json
tools/data/reports/trace_map_20260305_0843.json
tools/data/reports/report_20260404_0330.md
tools/data/reports/next_exec_20260314_0342.json
tools/data/reports/agent_20260507_0942.md
tools/data/reports/report_20260306_0341.md
tools/data/reports/ddf_20260502_0405.json
tools/data/reports/ddf_20260503_0405.json
tools/data/reports/next_exec_20260330_0344.json
tools/data/reports/loop_guard_20260507_0803.json
tools/data/reports/agent_20260507_0901.md
tools/data/reports/ddf_20260315_0811.json
tools/data/reports/ddf_20260320_0405.json
tools/data/reports/report_20260331_1809.md
tools/data/reports/falsifier_20260507_0923.raw.txt
tools/data/reports/ddf_20260316_0405.json
tools/data/reports/ddf_20260506_0405.json
tools/data/reports/agent_20260504_1219.md
tools/data/reports/loop_guard_20260507_1042.json
tools/data/reports/agent_20260507_1006.md
tools/data/reports/insights_20260306_1834.json
tools/data/reports/trajectory_apply_20260507_0330.json
tools/data/reports/falsifier_20260507_1006.json
tools/data/reports/ddf_20260422_0405.json
tools/data/reports/ddf_20260318_0405.json
tools/data/reports/agent_20260507_0803.md
tools/data/reports/next_exec_20260401_0346.json
tools/data/reports/ddf_20260427_0405.json
tools/data/reports/next_exec_20260331_0345.json
tools/data/reports/report_20260404_1852.md
tools/data/reports/falsifier_20260507_0803.raw.txt
tools/data/reports/exp_excess_scaling_20260405.json
tools/data/reports/exp_ricci_primes.json
tools/data/reports/report_20260405_0715.md
tools/data/reports/falsifier_20260430_1946.json
tools/data/reports/ddf_20260426_0405.json
tools/data/reports/report_20260307_0342.md
tools/data/reports/report_20260303_0341.md
tools/data/reports/next_exec_20260305_1111.json
tools/data/reports/evolution_20260422_1616.md
tools/data/reports/falsifier_20260501_0330.json
tools/data/reports/agent_20260426_0330.md
tools/data/reports/exp_number_variance_test.json
tools/data/reports/agent_20260505_1022.md
tools/data/reports/mapping_validation_2026-04-21.json
tools/data/reports/ddf_20260329_0405.json
tools/data/reports/report_20260305_2121.md
tools/data/reports/ddf_20260317_0405.json
tools/data/reports/ddf_20260315_0815.json
tools/data/reports/ddf_20260419_0405.json
tools/data/reports/agent_20260407_0637.md
tools/data/reports/agent_20260408_0330.md
tools/data/reports/agent_20260406_1030.md
tools/data/reports/falsifier_20260507_1042.raw.txt
tools/data/reports/report_20260305_0342.md
tools/data/reports/evolution_20260422_0330.md
tools/data/reports/agent_20260505_0330.md
tools/data/reports/ddf_20260331_0405.json
tools/data/reports/gap_labeling_20260306_1834.json
tools/data/reports/agent_20260503_0330.md
tools/data/reports/exp_boundary_growth_20260405_0914.json
tools/data/reports/ddf_20260417_0405.json
tools/data/reports/ddf_20260505_0405.json
tools/data/reports/loop_guard_20260507_0330.json
tools/data/reports/report_20260330_0344.md
tools/data/reports/falsifier_20260501_0725.json
tools/data/reports/agent_20260405_0825.md
tools/data/reports/agent_20260406_0714.md
tools/data/reports/report_20260315_0801.md
tools/data/reports/falsifier_20260429_1041.json
tools/data/reports/gap_labeling_20260306_0341.json
tools/data/reports/agent_20260422_0330.md
tools/data/reports/evolution_20260418_0330.md
tools/data/reports/ddf_20260505_0636.json
tools/data/reports/ddf_20260322_0405.json
tools/data/reports/ddf_20260424_0405.json
tools/data/reports/agent_20260504_0901.md
tools/data/reports/ddf_20260430_0405.json
tools/data/reports/insights_20260401_0346.json
tools/data/reports/report_20260405_0330.md
tools/data/reports/loop_guard_20260507_0923.json
tools/data/reports/fibonacci_spectrum_20260306_0342.json
tools/data/reports/agent_20260506_0330.md
tools/data/reports/loop_guard_20260507_1419.json
tools/data/reports/next_exec_20260328_0344.json
tools/data/reports/falsifier_20260507_0923.json
tools/data/reports/incident_20260504_0721.md
tools/data/reports/ddf_20260324_0405.json
tools/data/reports/ddf_20260327_0405.json
tools/data/reports/agent_20260419_0330.md
tools/data/reports/ddf_20260410_0405.json
tools/data/reports/agent_20260422_1616.md
tools/data/reports/next_exec_20260327_0344.json
tools/data/reports/falsifier_20260507_1419.json
tools/data/reports/ddf_20260321_0405.json
tools/data/reports/agent_20260506_1941.md
tools/data/reports/ddf_20260418_0405.json
tools/data/reports/trajectory_apply_20260506_1941.json
tools/data/reports/next_exec_20260306_1834.json
tools/data/reports/ddf_20260406_0405.json
tools/data/reports/exp_boundary_20260405_0825.json
tools/data/reports/next_exec_20260403_0330.json
tools/data/reports/falsifier_20260506_0330.raw.txt
tools/data/reports/falsifier_20260506_1955.raw.txt
tools/data/reports/falsifier_20260507_0330.json
tools/data/reports/trajectory_apply_20260507_1006.json
tools/data/reports/agent_20260429_1013.md
tools/data/reports/falsifier_20260501_0931.json
tools/data/reports/evolution_20260424_0330.md
tools/data/reports/evolution_20260427_0330.md
tools/data/reports/cycle_20260315_0346.json
tools/data/reports/loop_guard_20260507_1006.json
tools/data/reports/lagrangiana_20260305_1048.json
tools/data/reports/exp_crossover_universality.json
tools/data/reports/trajectory_apply_20260506_1955.json
tools/data/reports/hierarchy_data.json
tools/data/reports/insights_20260315_0346.json
tools/data/reports/agent_20260507_0923.md
tools/data/reports/agent_20260410_0330.md
tools/data/reports/ddf_20260428_0405.json
tools/data/reports/agent_20260430_0330.md
tools/data/reports/falsifier_20260507_0803.json
tools/data/reports/gap_labeling_20260305_1111.json
tools/data/reports/next_exec_20260329_0343.json
tools/data/reports/agent_20260424_0330.md
tools/data/reports/next_exec_20260405_0729.json
tools/data/reports/fibonacci_spectrum_20260306_1834.json
tools/data/reports/report_20260329_0343.md
tools/data/reports/agent_20260506_1955.md
tools/data/reports/agent_20260423_0330.md
tools/data/reports/agent_20260430_1905.md
tools/data/reports/trajectory_apply_20260507_1042.json
tools/data/reports/agent_20260421_0330.md
tools/data/reports/gap_labeling_20260307_0342.json
tools/data/reports/evolution_20260420_0330.md
tools/data/reports/ddf_20260501_0405.json
tools/data/reports/next_exec_20260307_0342.json
tools/data/reports/ddf_20260326_0405.json
tools/data/reports/ddf_20260420_0405.json
tools/data/reports/next_exec_20260405_0330.json
tools/data/reports/ddf_20260402_0405.json
tools/data/reports/ddf_20260415_0405.json
tools/data/reports/exp_desitter_unification.json
tools/data/reports/loop_guard_20260507_0942.json
tools/data/reports/report_20260402_0344.md
tools/data/reports/insights_20260329_0343.json
tools/data/reports/incident_20260504_1138.md
tools/data/reports/agent_20260416_0330.md
tools/data/reports/report_20260314_0342.md
tools/data/reports/ddf_20260401_0405.json
tools/data/reports/report_20260315_0342.md
tools/data/reports/ddf_20260403_0405.json
tools/data/reports/tension_projection_screening_2026-04-21.json
tools/data/reports/exp_metric_tensor_diag_long.json
tools/data/reports/falsifier_20260503_0330.json
tools/data/reports/phi_vs_silver_falsification_20260306.json
tools/data/reports/falsifier_20260507_0901.json
tools/data/reports/insights_20260305_0852.json
tools/data/reports/agent_20260507_0330.md
tools/data/reports/trace_map_20260305_0844.json
tools/data/reports/cycle_20260306_0342.json
tools/data/reports/ddf_20260405_0405.json
tools/data/reports/trajectory_apply_20260507_0942.json
tools/data/reports/agent_20260501_0931.md
tools/data/reports/agent_20260429_1041.md
tools/data/reports/ddf_20260325_0405.json
tools/data/reports/falsifier_20260505_0330.json
tools/data/reports/gap_labeling_20260315_0343.json
tools/data/reports/ddf_20260404_0405.json
tools/data/reports/cycle_20260305_0844.json
tools/data/reports/evolution_20260505_0330.md
tools/data/reports/report_20260403_0330.md
tools/data/reports/agent_20260417_0803.md
tools/data/reports/falsifier_20260507_0330.raw.txt
tools/data/reports/insights_20260403_0330.json
tools/data/reports/agent_diag2.md
tools/data/reports/evolution_20260506_0330.md
tools/data/reports/next_exec_20260404_0330.json
tools/data/reports/report_20260328_0344.md
tools/data/reports/evolution_20260421_0330.md
tools/data/reports/evolution_20260425_0330.md
tools/data/reports/agent_20260418_0330.md
tools/data/reports/agent_test_0406.md
tools/data/reports/evolution_20260423_0330.md
tools/data/reports/agent_20260413_0330.md
tools/data/reports/report_20260401_0346.md
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0852.md
tools/data/reports/_quarantine_falsifier_29_04/falsifier_20260429_0958.json
tools/data/reports/_quarantine_falsifier_29_04/falsifier_20260429_0852.json
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0833.md
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0958.md
tools/data/reports/_quarantine_falsifier_29_04/evolution_20260429_0852.md
tools/data/reports/_quarantine_falsifier_29_04/evolution_20260429_0958.md
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0829.md
tools/data/reports/agent_20260502_0330.md
tools/data/reports/falsifier_20260504_0901.json
tools/data/reports/lagrangiana_20260305_1042.json
tools/data/reports/trajectory_apply_20260507_0923.json
tools/data/reports/agent_20260411_0330.md
tools/data/reports/report_20260302_0341.md
tools/data/reports/agent_20260430_1946.md
tools/data/reports/agent_20260427_0330.md
tools/data/reports/ddf_20260330_0405.json
tools/data/reports/ddf_20260408_0405.json
tools/data/reports/next_exec_20260326_0343.json
tools/data/reports/next_exec_20260402_0344.json
tools/data/reports/agent_20260507_1419.md
tools/data/reports/insights_20260306_0342.json
tools/data/reports/agent_20260405_0914.md
tools/data/reports/next_exec_20260306_0342.json
tools/data/reports/falsifier_20260506_0625.json
tools/data/reports/exp_dR_brody_connection.json
tools/data/reports/insights_20260307_0342.json
tools/data/reports/agent_20260415_0330.md
tools/data/reports/ddf_20260421_0405.json
tools/data/reports/agent_20260501_0330.md
tools/data/reports/evolution_20260504_0330.md
tools/data/reports/agent_test_field.md
tools/data/reports/agent_20260409_0330.md
tools/data/reports/falsifier_20260507_1042.json
tools/data/reports/report_20260331_0345.md
tools/data/reports/ddf_20260425_0405.json
tools/data/reports/agent_20260420_0330.md
tools/data/reports/evolution_20260506_1941.md
tools/data/reports/gap_labeling_20260305_0843.json
tools/data/reports/falsifier_20260507_0942.json
tools/data/reports/report_20260402_0756.md
tools/data/reports/agent_20260428_0330.md
tools/data/reports/agent_20260430_1919.md
tools/data/reports/fibonacci_spectrum_20260305_0844.json
tools/data/reports/cycle_20260307_0342.json
tools/data/reports/ddf_20260328_0405.json
tools/data/reports/exp_psd_prime_gaps.json
tools/data/reports/falsifier_20260506_1955.json
tools/data/reports/evolution_20260503_0330.md
tools/data/reports/ddf_20260407_0405.json
tools/data/reports/falsifier_20260429_1013.json
tools/data/reports/agent_20260507_1042.md
tools/data/reports/exp_brody_crossover_20260405.json
tools/data/reports/cycle_20260306_1834.json
tools/data/reports/ddf_20260323_0405.json
tools/data/reports/next_exec_20260315_0346.json
tools/data/reports/agent_20260501_0725.md
tools/data/reports/falsifier_20260430_0330.json
tools/data/reports/trajectory_apply_20260507_0901.json
tools/data/reports/agent_20260405_0916.md
tools/data/reports/ddf_20260429_0405.json
tools/data/reports/ddf_20260319_0405.json
tools/data/reports/ddf_20260412_0405.json
tools/data/reports/report_20260327_0344.md

 succeeded in 0ms:
diff --git a/tools/data/seme.json b/tools/data/seme.json
index db10e4e..f61d616 100644
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -1,6 +1,6 @@
 {
-  "timestamp": "2026-05-07T10:49:04.273096",
-  "piano": 75,
+  "timestamp": "2026-05-07T14:25:01.011848",
+  "piano": 76,
   "tensioni": [
     {
       "id": "OBSERVABLE_REGISTRY",
@@ -38,7 +38,7 @@
     {
       "tipo": "vincolo",
       "id": "ORDER_DENOMINATOR_GATE",
-      "claim": "Il denominator gate trasferisce come supporto one-sided dell'ordine quando l'ordine e visibile agli osservabili del perimetro, non come endpoint-stable support a due poli. Nel perimetro sintetico agent_20260507_0901, 4/4 domini non-BOUNDARY hanno endpoint_stable_observables=[] e polo coerente stable_count 3.0-5.0. Nel perimetro semi-reale agent_20260507_0923, primi e zeta trasferiscono (primi: SR,L1,triple_var; zeta: SR,L2), ma logistic_return_intervals e blank: stable_count coerente 0.0-0.2. Nel perimetro bridge agent_20260507_0942, prime_metric_delta_gamma_abs, prime_metric_dR_abs, zeta_trace_residual_step5_abs e hydrogen_bound_level_spacings trasferiscono su tutti i 5 osservabili canonici con endpoint_stable_observables=[]; e supporto perimetro-bridge, non universalita del gate. Nel perimetro logistic-native agent_20260507_1006, logistic_orbit_values trasferisce su block_entropy_deficit_k4 in run e seed check; logistic_symbolic_itinerary resta blank; logistic_return_intervals mostra recurrence_diag_mean solo nel run principale e torna blank nel seed check. La beta 0.10/0.30/0.40/0.50 resta coordinata del protocollo quando compare, non coordinata universale. Nel perimetro surrogate-contract agent_20260507_1042, logistic_orbit_values trasferisce solo tramite block_entropy_deficit_k4 e sopravvive a marginal_shuffle, circular_shift e block_shuffle in run e seed check; logistic_symbolic_itinerary resta blank; logistic_return_intervals non replica (recurrence_diag_mean compare contro marginal/block nel run principale ma sparisce nel seed check). Il supporto logistic rimasto e orbit-block-entropy, non return/generating-partition support. Circular-shift z usa denominatori molto piccoli: il prossimo nodo e separare grammatica locale da artefatto del taglio lineare.",
+      "claim": "Il denominator gate trasferisce come supporto one-sided dell'ordine quando l'ordine e visibile agli osservabili del perimetro, non come endpoint-stable support a due poli. Nel perimetro sintetico agent_20260507_0901, 4/4 domini non-BOUNDARY hanno endpoint_stable_observables=[] e polo coerente stable_count 3.0-5.0. Nel perimetro semi-reale agent_20260507_0923, primi e zeta trasferiscono (primi: SR,L1,triple_var; zeta: SR,L2), ma logistic_return_intervals e blank: stable_count coerente 0.0-0.2. Nel perimetro bridge agent_20260507_0942, prime_metric_delta_gamma_abs, prime_metric_dR_abs, zeta_trace_residual_step5_abs e hydrogen_bound_level_spacings trasferiscono su tutti i 5 osservabili canonici con endpoint_stable_observables=[]; e supporto perimetro-bridge, non universalita del gate. Nel perimetro logistic-native agent_20260507_1006, logistic_orbit_values trasferisce su block_entropy_deficit_k4 in run e seed check; logistic_symbolic_itinerary resta blank; logistic_return_intervals mostra recurrence_diag_mean solo nel run principale e torna blank nel seed check. La beta 0.10/0.30/0.40/0.50 resta coordinata del protocollo quando compare, non coordinata universale. Nel perimetro surrogate-contract agent_20260507_1042, logistic_orbit_values trasferisce solo tramite block_entropy_deficit_k4 e sopravvive a marginal_shuffle, circular_shift e block_shuffle in run e seed check; logistic_symbolic_itinerary resta blank; logistic_return_intervals non replica (recurrence_diag_mean compare contro marginal/block nel run principale ma sparisce nel seed check). Nel perimetro cyclic-cut agent_20260507_1419, il residuo logistic_orbit_values non e artefatto del taglio lineare: cyclic_block_entropy_deficit_k4 e invariato sotto rotazione e replica contro marginal_shuffle e block_shuffle size 4-256 in run e seed check. Logistic_symbolic_itinerary e logistic_return_intervals restano blank nel criterio replicato. Il supporto logistic rimasto e orbit-local block grammar, non return/generating-partition support.",
       "intensita": 0.92,
       "porta": "META",
       "manuale": true,
@@ -122,6 +122,17 @@
       "condensato_ref": "A9,A14",
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
+    {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
     {
       "tipo": "simmetria_sospetta",
       "id": "META",
@@ -135,14 +146,14 @@
   ],
   "potenziale_bloccato": [],
   "varianza": [
-    "Tensioni risolte: {'OBSERVABLE_REGISTRY', 'PERTURBATION_DENOMINATOR_GATE', 'PIANO_PRIMARIO_DUE_ASSIOMI', 'TRAJECTORY_APPLY_20260507_1006', 'TENSIONE_ENTITA', 'TRAJECTORY_APPLY_20260507_0803', 'BOUNDARY_LAYER_GATE', 'ORDER_DENOMINATOR_GATE', 'TRAJECTORY_APPLY_20260507_0942', 'DUALITA_DIPOLARE_VS_ILLUSORIA', 'METRIC_TENSOR', 'G_POTENZIALE_NULLA', 'TRAJECTORY_APPLY_20260507_0901', 'TRASCENDENZA_LIMITE'}"
+    "Tensioni risolte: {'G_POTENZIALE_NULLA', 'DUALITA_DIPOLARE_VS_ILLUSORIA', 'METRIC_TENSOR', 'TENSIONE_ENTITA', 'PIANO_PRIMARIO_DUE_ASSIOMI', 'STRUCTURAL_CHECK_20260507', 'OBSERVABLE_REGISTRY', 'PERTURBATION_DENOMINATOR_GATE', 'TRASCENDENZA_LIMITE', 'BOUNDARY_LAYER_GATE', 'ORDER_DENOMINATOR_GATE'}"
   ],
   "filtro": {
-    "promosse": 16,
+    "promosse": 12,
     "filtrate": 0,
     "condensato_claims": 30
   },
-  "direzione": "Esplorare il confine: La trascendenza e il limite attuale del modello. I punti fissi relazionali (non solo phi ma la rete di punti fissi tra osservabili) possono rivelare il vero grafo della realta e pattern nelle matrici. Il confine non e nella matematica - e nel passaggio tra piani.",
+  "direzione": "Esplorare il confine: 8 domini GUE, 5 Poisson — il confine è il terzo incluso operativo",
   "verifica": {
     "pass": 11,
     "fail": 0,
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}

diff --git a/tools/data/reports/agent_20260507_1458.md b/tools/data/reports/agent_20260507_1458.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1fdadab557dd4278e7071eda82b2deb8375df7
--- /dev/null
+++ b/tools/data/reports/agent_20260507_1458.md
@@ -0,0 +1,68 @@
+# Agent Report — META Assertion Gate
+**Date**: 2026-05-07 14:58 UTC  
+**Piano**: 76  
+**Tension explored**: META (score 0.898)  
+**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
+**Tool**: `tools/meta_assertion_gate.py`  
+**Data**: `tools/data/meta_assertion_gate.json`
+
+## Claim Under Test
+> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
+
+## Question
+Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?
+
+## Experiment Design
+- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
+- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
+- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
+- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.
+
+## Results
+
+| Bucket | Count |
+|---|---:|
+| Baseline PASS | 11/11 |
+| PASS anche senza `tools/data` | 6/11 |
+| PASS dipendente da fixture o contesto | 5/11 |
+| PASS ad alto rischio tautologico | 4/11 |
+| PASS a rischio medio | 4/11 |
+| PASS a rischio basso | 3/11 |
+
+| Test | Baseline | No-data | Dependency | Risk | Class |
+|---|---|---|---|---|---|
+| A1 | PASS | PASS | data_independent | high | algebraic_identity |
+| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
+| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
+| A4 | PASS | PASS | data_independent | high | algebraic_identity |
+| A5 | PASS | PASS | data_independent | high | algebraic_identity |
+| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
+| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
+| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
+| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+
+Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.
+
+## Key Findings
+1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
+2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
+3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
+4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.
+
+## Verdict
+**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.
+
+## Consecutio
+La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.
+
+## Seme
+Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
+- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
+- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
+- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
+- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

exec
/bin/bash -lc 'python tools/lab_falsifier.py --help' in /opt/MM_D-ND
 succeeded in 0ms:
usage: lab_falsifier.py [-h] --report REPORT --output OUTPUT
                        [--timeout TIMEOUT]

Counter-pole gate for the lab

options:
  -h, --help         show this help message and exit
  --report REPORT    Path to agent_TS.md
  --output OUTPUT    Path for falsifier_TS.json output
  --timeout TIMEOUT  LLM call timeout seconds

diff --git a/tools/data/reports/agent_20260507_1458.md b/tools/data/reports/agent_20260507_1458.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1fdadab557dd4278e7071eda82b2deb8375df7
--- /dev/null
+++ b/tools/data/reports/agent_20260507_1458.md
@@ -0,0 +1,68 @@
+# Agent Report — META Assertion Gate
+**Date**: 2026-05-07 14:58 UTC  
+**Piano**: 76  
+**Tension explored**: META (score 0.898)  
+**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
+**Tool**: `tools/meta_assertion_gate.py`  
+**Data**: `tools/data/meta_assertion_gate.json`
+
+## Claim Under Test
+> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
+
+## Question
+Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?
+
+## Experiment Design
+- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
+- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
+- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
+- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.
+
+## Results
+
+| Bucket | Count |
+|---|---:|
+| Baseline PASS | 11/11 |
+| PASS anche senza `tools/data` | 6/11 |
+| PASS dipendente da fixture o contesto | 5/11 |
+| PASS ad alto rischio tautologico | 4/11 |
+| PASS a rischio medio | 4/11 |
+| PASS a rischio basso | 3/11 |
+
+| Test | Baseline | No-data | Dependency | Risk | Class |
+|---|---|---|---|---|---|
+| A1 | PASS | PASS | data_independent | high | algebraic_identity |
+| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
+| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
+| A4 | PASS | PASS | data_independent | high | algebraic_identity |
+| A5 | PASS | PASS | data_independent | high | algebraic_identity |
+| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
+| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
+| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
+| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+
+Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.
+
+## Key Findings
+1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
+2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
+3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
+4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.
+
+## Verdict
+**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.
+
+## Consecutio
+La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.
+
+## Seme
+Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
+- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
+- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
+- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
+- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

codex
Il report è scritto e il diff mostra solo il vincolo nuovo dentro il seme; il resto del seme era già avanzato al piano 76 prima del mio inserimento. Lancio anche il counter-pole locale sul report per vedere se il gate segnala problemi formali.
exec
/bin/bash -lc 'python tools/lab_falsifier.py --report tools/data/reports/agent_20260507_1458.md --output tools/data/reports/falsifier_20260507_1458.json --timeout 120' in /opt/MM_D-ND
diff --git a/tools/data/reports/agent_20260507_1458.md b/tools/data/reports/agent_20260507_1458.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1fdadab557dd4278e7071eda82b2deb8375df7
--- /dev/null
+++ b/tools/data/reports/agent_20260507_1458.md
@@ -0,0 +1,68 @@
+# Agent Report — META Assertion Gate
+**Date**: 2026-05-07 14:58 UTC  
+**Piano**: 76  
+**Tension explored**: META (score 0.898)  
+**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
+**Tool**: `tools/meta_assertion_gate.py`  
+**Data**: `tools/data/meta_assertion_gate.json`
+
+## Claim Under Test
+> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
+
+## Question
+Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?
+
+## Experiment Design
+- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
+- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
+- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
+- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.
+
+## Results
+
+| Bucket | Count |
+|---|---:|
+| Baseline PASS | 11/11 |
+| PASS anche senza `tools/data` | 6/11 |
+| PASS dipendente da fixture o contesto | 5/11 |
+| PASS ad alto rischio tautologico | 4/11 |
+| PASS a rischio medio | 4/11 |
+| PASS a rischio basso | 3/11 |
+
+| Test | Baseline | No-data | Dependency | Risk | Class |
+|---|---|---|---|---|---|
+| A1 | PASS | PASS | data_independent | high | algebraic_identity |
+| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
+| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
+| A4 | PASS | PASS | data_independent | high | algebraic_identity |
+| A5 | PASS | PASS | data_independent | high | algebraic_identity |
+| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
+| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
+| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
+| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+
+Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.
+
+## Key Findings
+1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
+2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
+3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
+4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.
+
+## Verdict
+**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.
+
+## Consecutio
+La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.
+
+## Seme
+Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
+- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
+- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
+- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
+- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

diff --git a/tools/data/reports/agent_20260507_1458.md b/tools/data/reports/agent_20260507_1458.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1fdadab557dd4278e7071eda82b2deb8375df7
--- /dev/null
+++ b/tools/data/reports/agent_20260507_1458.md
@@ -0,0 +1,68 @@
+# Agent Report — META Assertion Gate
+**Date**: 2026-05-07 14:58 UTC  
+**Piano**: 76  
+**Tension explored**: META (score 0.898)  
+**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
+**Tool**: `tools/meta_assertion_gate.py`  
+**Data**: `tools/data/meta_assertion_gate.json`
+
+## Claim Under Test
+> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
+
+## Question
+Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?
+
+## Experiment Design
+- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
+- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
+- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
+- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.
+
+## Results
+
+| Bucket | Count |
+|---|---:|
+| Baseline PASS | 11/11 |
+| PASS anche senza `tools/data` | 6/11 |
+| PASS dipendente da fixture o contesto | 5/11 |
+| PASS ad alto rischio tautologico | 4/11 |
+| PASS a rischio medio | 4/11 |
+| PASS a rischio basso | 3/11 |
+
+| Test | Baseline | No-data | Dependency | Risk | Class |
+|---|---|---|---|---|---|
+| A1 | PASS | PASS | data_independent | high | algebraic_identity |
+| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
+| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
+| A4 | PASS | PASS | data_independent | high | algebraic_identity |
+| A5 | PASS | PASS | data_independent | high | algebraic_identity |
+| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
+| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
+| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
+| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+
+Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.
+
+## Key Findings
+1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
+2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
+3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
+4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.
+
+## Verdict
+**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.
+
+## Consecutio
+La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.
+
+## Seme
+Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
+- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
+- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
+- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
+- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

 exited 2 in 30678ms:
      [provider: codex-cli unavailable, next]
      [provider: claude-cli unavailable, next]
      [provider: openrouter unavailable, next]
[falsifier] chain failed: all providers in chain ['codex-cli', 'claude-cli', 'openrouter'] failed (check codex auth, claude auth, OPENROUTER_API_KEY env)
[falsifier] LLM call failed (exit=1). Conservative: BLOCK.

exec
/bin/bash -lc "test -f tools/data/reports/falsifier_20260507_1458.json && sed -n '1,220p' tools/data/reports/falsifier_20260507_1458.json || true" in /opt/MM_D-ND
 succeeded in 0ms:
exec
/bin/bash -lc 'git status --short tools/meta_assertion_gate.py tools/data/meta_assertion_gate.json tools/data/seme.json tools/data/reports/agent_20260507_1458.md tools/data/reports/falsifier_20260507_1458.json' in /opt/MM_D-ND
 succeeded in 0ms:
 M tools/data/seme.json
?? tools/data/meta_assertion_gate.json
?? tools/data/reports/agent_20260507_1458.md
?? tools/meta_assertion_gate.py

diff --git a/tools/data/reports/agent_20260507_1458.md b/tools/data/reports/agent_20260507_1458.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1fdadab557dd4278e7071eda82b2deb8375df7
--- /dev/null
+++ b/tools/data/reports/agent_20260507_1458.md
@@ -0,0 +1,68 @@
+# Agent Report — META Assertion Gate
+**Date**: 2026-05-07 14:58 UTC  
+**Piano**: 76  
+**Tension explored**: META (score 0.898)  
+**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
+**Tool**: `tools/meta_assertion_gate.py`  
+**Data**: `tools/data/meta_assertion_gate.json`
+
+## Claim Under Test
+> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
+
+## Question
+Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?
+
+## Experiment Design
+- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
+- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
+- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
+- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.
+
+## Results
+
+| Bucket | Count |
+|---|---:|
+| Baseline PASS | 11/11 |
+| PASS anche senza `tools/data` | 6/11 |
+| PASS dipendente da fixture o contesto | 5/11 |
+| PASS ad alto rischio tautologico | 4/11 |
+| PASS a rischio medio | 4/11 |
+| PASS a rischio basso | 3/11 |
+
+| Test | Baseline | No-data | Dependency | Risk | Class |
+|---|---|---|---|---|---|
+| A1 | PASS | PASS | data_independent | high | algebraic_identity |
+| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
+| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
+| A4 | PASS | PASS | data_independent | high | algebraic_identity |
+| A5 | PASS | PASS | data_independent | high | algebraic_identity |
+| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
+| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
+| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
+| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+
+Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.
+
+## Key Findings
+1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
+2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
+3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
+4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.
+
+## Verdict
+**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.
+
+## Consecutio
+La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.
+
+## Seme
+Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
+- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
+- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
+- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
+- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

exec
/bin/bash -lc "sed -n '1,220p' tools/data/lab_health.json" in /opt/MM_D-ND
 succeeded in 0ms:
{
  "run_timestamp": "20260507_1419",
  "autopsy_run_at": "2026-05-07T14:58:50.961668+00:00",
  "jsonl_path": null,
  "raw_log_bytes": 429098,
  "report_present": true,
  "session_stats": null,
  "status": "completed",
  "regressive_node": null,
  "recommendation": "cycle completato via provider non-claude (codex/openrouter). Session jsonl non disponibile per autopsy dettagliata.",
  "_note": "completed_no_jsonl"
}
diff --git a/tools/data/reports/agent_20260507_1458.md b/tools/data/reports/agent_20260507_1458.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1fdadab557dd4278e7071eda82b2deb8375df7
--- /dev/null
+++ b/tools/data/reports/agent_20260507_1458.md
@@ -0,0 +1,68 @@
+# Agent Report — META Assertion Gate
+**Date**: 2026-05-07 14:58 UTC  
+**Piano**: 76  
+**Tension explored**: META (score 0.898)  
+**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
+**Tool**: `tools/meta_assertion_gate.py`  
+**Data**: `tools/data/meta_assertion_gate.json`
+
+## Claim Under Test
+> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
+
+## Question
+Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?
+
+## Experiment Design
+- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
+- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
+- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
+- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.
+
+## Results
+
+| Bucket | Count |
+|---|---:|
+| Baseline PASS | 11/11 |
+| PASS anche senza `tools/data` | 6/11 |
+| PASS dipendente da fixture o contesto | 5/11 |
+| PASS ad alto rischio tautologico | 4/11 |
+| PASS a rischio medio | 4/11 |
+| PASS a rischio basso | 3/11 |
+
+| Test | Baseline | No-data | Dependency | Risk | Class |
+|---|---|---|---|---|---|
+| A1 | PASS | PASS | data_independent | high | algebraic_identity |
+| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
+| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
+| A4 | PASS | PASS | data_independent | high | algebraic_identity |
+| A5 | PASS | PASS | data_independent | high | algebraic_identity |
+| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
+| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
+| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
+| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+
+Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.
+
+## Key Findings
+1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
+2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
+3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
+4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.
+
+## Verdict
+**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.
+
+## Consecutio
+La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.
+
+## Seme
+Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
+- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
+- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
+- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
+- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

codex
Completato.

Ho eseguito l’esperimento META e scritto il report in [agent_20260507_1458.md](/opt/MM_D-ND/tools/data/reports/agent_20260507_1458.md).

Artefatti creati:
- [meta_assertion_gate.py](/opt/MM_D-ND/tools/meta_assertion_gate.py)
- [meta_assertion_gate.json](/opt/MM_D-ND/tools/data/meta_assertion_gate.json)

Risultato centrale: il `11/11 PASS` non è un denominatore unico. Nel gate:
- `6/11` test passano anche senza `tools/data`
- `5/11` dipendono da fixture o contesto
- `4/11` PASS sono algebra/same-rule ad alto rischio tautologico

Ho aggiornato [seme.json](/opt/MM_D-ND/tools/data/seme.json) con il vincolo `META_ASSERTION_GATE`.

Verifiche eseguite:
- `python tools/dnd_scenario.py --best`
- `python tools/dipartimento.py --check`
- `python tools/dnd_controprove.py`
- `python tools/meta_assertion_gate.py`
- `python -m py_compile tools/meta_assertion_gate.py`
- validazione JSON di `seme.json` e `meta_assertion_gate.json`

Nota: ho tentato anche `lab_falsifier.py`, ma tutti i provider LLM locali risultano non disponibili; nessun output falsifier è stato generato.
diff --git a/tools/data/reports/agent_20260507_1458.md b/tools/data/reports/agent_20260507_1458.md
new file mode 100644
index 0000000000000000000000000000000000000000..ab1fdadab557dd4278e7071eda82b2deb8375df7
--- /dev/null
+++ b/tools/data/reports/agent_20260507_1458.md
@@ -0,0 +1,68 @@
+# Agent Report — META Assertion Gate
+**Date**: 2026-05-07 14:58 UTC  
+**Piano**: 76  
+**Tension explored**: META (score 0.898)  
+**observables_registry**: N/A — nessun osservabile canonico SR/SR2/L1/L2/triple_var usato  
+**Tool**: `tools/meta_assertion_gate.py`  
+**Data**: `tools/data/meta_assertion_gate.json`
+
+## Claim Under Test
+> Tutti i 11 test passano — verifica che non stiamo testando solo tautologie.
+
+## Question
+Il PASS 11/11 di `tools/dipartimento.py --check` misura contenuto operativo o un denominatore misto che combina algebra, fixture e segnali locali?
+
+## Experiment Design
+- **Baseline**: esecuzione degli 11 test di `dipartimento.verifica_asserzioni`.
+- **No-data gate**: riesecuzione degli stessi test con `dipartimento.DATA` puntato a una directory vuota temporanea.
+- **Classificazione**: ogni test riceve `gate_class`, `tautology_risk`, `no_data_status`, `data_dependency`.
+- **Fonti**: Verificato da `tools/dipartimento.py`, `tools/meta_assertion_gate.py`, `tools/data/meta_assertion_gate.json`. Inferito: la lettura strutturale del denominatore.
+
+## Results
+
+| Bucket | Count |
+|---|---:|
+| Baseline PASS | 11/11 |
+| PASS anche senza `tools/data` | 6/11 |
+| PASS dipendente da fixture o contesto | 5/11 |
+| PASS ad alto rischio tautologico | 4/11 |
+| PASS a rischio medio | 4/11 |
+| PASS a rischio basso | 3/11 |
+
+| Test | Baseline | No-data | Dependency | Risk | Class |
+|---|---|---|---|---|---|
+| A1 | PASS | PASS | data_independent | high | algebraic_identity |
+| A2 | PASS | PASS | data_independent | high | same_rule_dynamics |
+| A3 | PASS | PASS | data_independent | medium | same_rule_dynamics |
+| A4 | PASS | PASS | data_independent | high | algebraic_identity |
+| A5 | PASS | PASS | data_independent | high | algebraic_identity |
+| C1 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| C2 | PASS | PASS | data_independent | medium | local_recomputed_signal |
+| C3 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+| G1 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_distance |
+| G2 | PASS | SKIP | fixture_or_context_dependent | medium | cached_fixture_phi_convergence |
+| N2 | PASS | SKIP | fixture_or_context_dependent | low | cached_fixture |
+
+Numeri di dettaglio: C1 spacing GUE-like con `<r>=0.6150`; C2 `pearson_r=-0.6428`; C3 distanza media da intero `0.0270`; G1 best phi-distance `0.021256`; G2 `12/13` domini convergono a phi; N2 `<r>=1.0000`.
+
+## Key Findings
+1. **Il PASS 11/11 non e un denominatore unico.** Sei test sopravvivono senza `tools/data`; cinque test cadono a SKIP quando le fixture spariscono.
+2. **Il nucleo A1-A5 e prevalentemente algebra della regola.** A1, A4 e A5 sono identita o chiusure dirette della definizione; A2 e A3 misurano dinamica della stessa mappa, non un dominio esterno.
+3. **C2 e il solo segnale locale ricalcolato dentro il gate.** Non usa fixture, ma resta un test piccolo e thresholded su primi sotto 10000.
+4. **C1, C3, G1, G2 e N2 sono replay di deposito.** Sono utili come controllo di coerenza del lab; non contano come cinque nuove conferme indipendenti a ogni ciclo.
+
+## Verdict
+**CONSTRAINT on META**: il campo non deve piu leggere `11/11 PASS` come evidenza singola. Nel perimetro `agent_20260507_1458`, la verifica si scinde in algebra/same-rule, segnale locale ricalcolato, e fixture replay. Ogni claim futuro sulla verifica deve riportare `gate_class`, `no_data_status` e `data_dependency` per test.
+
+## Consecutio
+La prossima inversione vive nel nodo regressivo di `dipartimento.verifica_asserzioni`: il sommario PASS/FAIL deve aggregare per classe di denominatore, non solo per stato. Il prossimo cycle puo trasformare `meta_assertion_gate.py` in gate del report mattutino, dopo un secondo run su seed invariato.
+
+## Seme
+Aggiornato `tools/data/seme.json` con tensione/vincolo `META_ASSERTION_GATE`.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: nessun claim di zero/sempre/mai. I conteggi sono dichiarati nel perimetro esatto degli 11 test.
+- **L2 quantita vs ratio**: riporto sia count assoluti sia frazioni implicite; nessun confronto tra spazi di taglia diversa decide il claim.
+- **L3 no silent patching**: META non e risolta. Viene ristretto il denominatore del PASS.
+- **L4 edge cases**: C2 resta separato: passa senza fixture ma non entra nel bucket algebraico.
+- **L5 re-discovery**: classificare test per dipendenza da fixture e rischio tautologico e audit metodologico standard. Non taggo NEW.
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 0d59cc54e3e68dc5da66adb61eb5709dd6580326..f61d61663e82a09e25834399cee1b76d158a0acf
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -123,6 +123,17 @@
       "condensato_motivo": "A9 (terzo incluso) opera CON il piano. A14 (cascata) propaga - ma propaga cosa, se solo 2 assiomi sono attivi per zona?"
     },
     {
+      "tipo": "vincolo",
+      "id": "META_ASSERTION_GATE",
+      "claim": "Il PASS 11/11 della verifica non e un denominatore unico. Nel perimetro agent_20260507_1458, 6/11 test passano anche senza tools/data; 5/11 dipendono da fixture o contesto; 4/11 PASS sono algebra/same-rule ad alto rischio tautologico. La tensione META va riportata con gate_class, no_data_status e data_dependency per test.",
+      "intensita": 0.88,
+      "manuale": true,
+      "porta": "META",
+      "condensato_ref": "A4,A8,A12,C2",
+      "origine": "cycle agent_20260507_1458: meta_assertion_gate su dipartimento.py verifica_asserzioni",
+      "added_at": "2026-05-07T14:58:00+00:00"
+    },
+    {
       "tipo": "simmetria_sospetta",
       "id": "META",
       "claim": "Tutti i 11 test passano — verifica che non stiamo testando solo tautologie",
@@ -309,4 +320,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/tools/meta_assertion_gate.py b/tools/meta_assertion_gate.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be72ac7d92accd3da355e44976caee9c6535f83
--- /dev/null
+++ b/tools/meta_assertion_gate.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+"""
+META assertion gate for the D-ND verification checklist.
+
+The gate separates the 11 PASS result into:
+- checks that are independent from tools/data fixtures;
+- checks that replay cached data fixtures;
+- checks that recompute a small local signal.
+
+It does not replace dipartimento.py --check. It audits what that PASS means.
+"""
+
+import argparse
+import contextlib
+import json
+import tempfile
+from datetime import datetime, timezone
+from pathlib import Path
+
+import dipartimento
+
+
+REPO = Path("/opt/MM_D-ND")
+DEFAULT_OUT = REPO / "tools" / "data" / "meta_assertion_gate.json"
+
+
+GATE_MAP = {
+    "A1": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "fixed point is the defining equation iterated against PHI",
+    },
+    "A2": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "high",
+        "reason": "gap ratio is the derivative geometry of the same map",
+    },
+    "A3": {
+        "class": "same_rule_dynamics",
+        "tautology_risk": "medium",
+        "reason": "alternation is tested only inside the declared D-ND map",
+    },
+    "A4": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "eigenvalues are the closed algebra of M",
+    },
+    "A5": {
+        "class": "algebraic_identity",
+        "tautology_risk": "high",
+        "reason": "cross-ratio is assigned by the same PHI poles",
+    },
+    "C1": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on autoricerca_journal data",
+    },
+    "C2": {
+        "class": "local_recomputed_signal",
+        "tautology_risk": "medium",
+        "reason": "recomputes a small prime-gaps correlation with a fixed threshold",
+    },
+    "C3": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on topological_charge_results data",
+    },
+    "G1": {
+        "class": "cached_fixture_phi_distance",
+        "tautology_risk": "medium",
+        "reason": "depends on stored Bloch phi_distance",
+    },
+    "G2": {
+        "class": "cached_fixture_phi_convergence",
+        "tautology_risk": "medium",
+        "reason": "depends on stored convergence labels in autoricerca_journal",
+    },
+    "N2": {
+        "class": "cached_fixture",
+        "tautology_risk": "low",
+        "reason": "depends on cellular automata entries in autoricerca_journal",
+    },
+}
+
+
+def run_one(test_name):
+    try:
+        passed, detail = dipartimento._esegui_test(test_name)
+        return {"status": "PASS" if passed else "FAIL", "detail": detail}
+    except Exception as exc:
+        return {"status": "SKIP", "detail": str(exc)}
+
+
+def run_suite():
+    rows = []
+    for assertion in dipartimento.ASSERZIONI:
+        audit = GATE_MAP.get(assertion["id"], {})
+        result = run_one(assertion["test"])
+        rows.append(
+            {
+                "id": assertion["id"],
+                "test": assertion["test"],
+                "claim": assertion["claim"],
+                "status": result["status"],
+                "detail": result["detail"],
+                "gate_class": audit.get("class", "unclassified"),
+                "tautology_risk": audit.get("tautology_risk", "unknown"),
+                "audit_reason": audit.get("reason", ""),
+            }
+        )
+    return rows
+
+
+@contextlib.contextmanager
+def patched_data(path):
+    original = dipartimento.DATA
+    dipartimento.DATA = path
+    try:
+        yield
+    finally:
+        dipartimento.DATA = original
+
+
+def count(rows, key, value):
+    return sum(1 for row in rows if row.get(key) == value)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out", default=str(DEFAULT_OUT))
+    args = parser.parse_args()
+
+    baseline = run_suite()
+    with tempfile.TemporaryDirectory(prefix="dnd_meta_empty_data_") as tmp:
+        with patched_data(Path(tmp)):
+            no_data = run_suite()
+
+    no_data_by_id = {row["id"]: row for row in no_data}
+    rows = []
+    for row in baseline:
+        nd = no_data_by_id[row["id"]]
+        merged = dict(row)
+        merged["no_data_status"] = nd["status"]
+        merged["no_data_detail"] = nd["detail"]
+        merged["data_dependency"] = (
+            "data_independent" if nd["status"] == row["status"] == "PASS" else "fixture_or_context_dependent"
+        )
+        rows.append(merged)
+
+    summary = {
+        "total": len(rows),
+        "baseline_pass": count(rows, "status", "PASS"),
+        "baseline_fail": count(rows, "status", "FAIL"),
+        "baseline_skip": count(rows, "status", "SKIP"),
+        "pass_data_independent": sum(
+            1 for row in rows if row["status"] == "PASS" and row["data_dependency"] == "data_independent"
+        ),
+        "pass_fixture_or_context_dependent": sum(
+            1
+            for row in rows
+            if row["status"] == "PASS" and row["data_dependency"] == "fixture_or_context_dependent"
+        ),
+        "high_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "high"
+        ),
+        "medium_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "medium"
+        ),
+        "low_tautology_risk_pass": sum(
+            1 for row in rows if row["status"] == "PASS" and row["tautology_risk"] == "low"
+        ),
+    }
+
+    payload = {
+        "timestamp": datetime.now(timezone.utc).isoformat(),
+        "source": "tools/dipartimento.py::verifica_asserzioni",
+        "summary": summary,
+        "rows": rows,
+    }
+
+    out = Path(args.out)
+    out.parent.mkdir(parents=True, exist_ok=True)
+    out.write_text(json.dumps(payload, indent=2, ensure_ascii=False) + "\n")
+    print(json.dumps(summary, indent=2))
+    print(f"Wrote {out}")
+
+
+if __name__ == "__main__":
+    main()

tokens used
110,255
Completato.

Ho eseguito l’esperimento META e scritto il report in [agent_20260507_1458.md](/opt/MM_D-ND/tools/data/reports/agent_20260507_1458.md).

Artefatti creati:
- [meta_assertion_gate.py](/opt/MM_D-ND/tools/meta_assertion_gate.py)
- [meta_assertion_gate.json](/opt/MM_D-ND/tools/data/meta_assertion_gate.json)

Risultato centrale: il `11/11 PASS` non è un denominatore unico. Nel gate:
- `6/11` test passano anche senza `tools/data`
- `5/11` dipendono da fixture o contesto
- `4/11` PASS sono algebra/same-rule ad alto rischio tautologico

Ho aggiornato [seme.json](/opt/MM_D-ND/tools/data/seme.json) con il vincolo `META_ASSERTION_GATE`.

Verifiche eseguite:
- `python tools/dnd_scenario.py --best`
- `python tools/dipartimento.py --check`
- `python tools/dnd_controprove.py`
- `python tools/meta_assertion_gate.py`
- `python -m py_compile tools/meta_assertion_gate.py`
- validazione JSON di `seme.json` e `meta_assertion_gate.json`

Nota: ho tentato anche `lab_falsifier.py`, ma tutti i provider LLM locali risultano non disponibili; nessun output falsifier è stato generato.
