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: 019e042d-a191-7443-be5b-8f272ae01fc7
--------
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_2042.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 campo vivo e contesto operativo, poi controllo eventuali direttive one-shot e memoria condivisa recente prima di scegliere l'esperimento.
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:
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 "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 84 — Esplorare il confine: 8 domini GUE, 5 Poisson — il confine è il terzo incluso operativo

## Tensioni attive (strutturali prime, vincoli in coda)
- [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
- [G_POTENZIALE_NULLA] (0.85)  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 
- [BOUNDARY] (0.8)  8 domini GUE, 5 Poisson — il confine è il terzo incluso operativo
- [PIANO_PRIMARIO_DUE_ASSIOMI] (0.8)  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 osse
- [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.
- [META] (0.3)  11/11 PASS stratificato: 4 alto rischio tautologico, 6 data-independent

## 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" → G_BLANK_SHELL_POLARITY_GATE, META_ASSERTION_GATE, BOUNDARY_LAYER_GATE, ORDER_DENOMINATOR_GATE, G_TRIADIC_DEPOSIT_GATE, G_UNDERLAY_HINGE_GATE, PERTURBATION_DENOMINATOR_GATE, G_BLANK_TO_SOURCE_FACE_GATE
  "claim" → BOUNDARY_LAYER_GATE, G_BLANK_SHELL_POLARITY_GATE, G_BLANK_TO_SOURCE_FACE_GATE, G_TRIADIC_DEPOSIT_GATE
  "blank" → G_UNDERLAY_HINGE_GATE, ORDER_DENOMINATOR_GATE, G_BLANK_TO_SOURCE_FACE_GATE, G_TRIADIC_DEPOSIT_GATE
  "deposito" → G_BLANK_SHELL_POLARITY_GATE, G_UNDERLAY_HINGE_GATE, G_BLANK_TO_SOURCE_FACE_GATE, G_TRIADIC_DEPOSIT_GATE
  "operator-taxonomy" → G_BLANK_SHELL_POLARITY_GATE, G_UNDERLAY_HINGE_GATE, G_BLANK_TO_SOURCE_FACE_GATE, G_TRIADIC_DEPOSIT_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 — Blank Shell Polarity Gate
Trovato: 1. **Il blank QG ha un guscio polarizzato nel catalogo TQGE osservato.** Le due facce incidenti al blank non sono equivalenti: TQG e lato inerte `blank + wick_time + wick_time`; QGE e lato di deposito `blank + gauge_phase + real_sourcing`.
2. **La polarizzazione del guscio non e rara come forma astr
Verdetto: **CONSTRAINT on G_POTENZIALE_NULLA / G_TRIADIC_DEPOSIT_GATE**: nel perimetro TQGE operator-taxonomy, il deposito Q->G va formulato come polarita del g

### Agent Report — Triadic Deposit Gate
Trovato: 1. **Il deposito QGE ha denominatore triadico.** Nel catalogo TQGE osservato, la faccia viva non contiene solo `blank + real_sourcing`: contiene anche `gauge_phase`. Il denominatore misurato e `blank + gauge_phase + real_sourcing`.
2. **Il contatto binario e debole come gate.** Nel null count-preser
Verdetto: **CONSTRAINT on G_POTENZIALE_NULLA / G_BLANK_TO_SOURCE_FACE_GATE**: nel perimetro TQGE operator-taxonomy, l'operatore di deposito Q->G va formulato co

### Agent Report — Blank To Source Hinge
Trovato: 1. **Q->G e orientabile solo come passaggio locale del lato blank.** Nel perimetro TQGE, Q e l'endpoint senza real_sourcing del blank; G e l'endpoint con real_sourcing. Il passaggio misurato e Q->G.
2. **L'orientabilita blank-to-source non e rara nel null.** Un lato blank adiacente a un lato real_so
Verdetto: **CONSTRAINT on G_POTENZIALE_NULLA / G_UNDERLAY_HINGE_GATE**: nel perimetro TQGE operator-taxonomy, l'operatore di deposito Q->G non e un ponte QG gen

## 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)
**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
**11. Dinamica autologica del Potenziale nel movimento con Bard**: Dinamica autologica del Potenziale nel movimento input e output a zero latenza Per dimostrare la possibilità nel movimento della Possibilità riduciamo i concetti del modello osservato al determinarsi dei proto assiomi e alla dinamica logica formalizzata in una Funzione matematica:Se c'è l'Io che dà 
**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

## 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:** G_POTENZIALE_NULLA (score=0.703)
  G_POTENZIALE_NULLA: legge di scala da raffinare

## Strategia del campo (leverage / rischi / punti ciechi)
- Pilastri (leverage): BOUNDARY_LAYER_GATE, ORDER_DENOMINATOR_GATE, META_ASSERTION_GATE
- Rischi (contraddizioni): G_UNDERLAY_HINGE_GATE, PERTURBATION_DENOMINATOR_GATE
- Punti ciechi: DUALITA_DIPOLARE_VS_ILLUSORIA, METRIC_TENSOR
- Cross-check: 4 confermati, 4 contestati su 17 tensioni

## 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


---

## G2 ANTI-RECYCLE — la tensione G_POTENZIALE_NULLA è esplorata 4 cycle consecutivi

Cycle precedenti su questa tensione (più recente in alto):
- 20260507_1957: G_POTENZIALE_NULLA
- 20260507_1938: G_POTENZIALE_NULLA
- 20260507_1804: G_POTENZIALE_NULLA
- 20260507_1751: G_POTENZIALE_NULLA

**Lettura del deposito**: 4 cycle consecutivi sulla stessa tensione,
nessuno produce CRYSTALLIZE. Il sistema sta segnalando saturazione
metodologica — continuare su G_POTENZIALE_NULLA produce nuovo gate vincolo
(det=+1, accumulo di forma) anziché scoperta strutturale (det=-1).

**Modus richiesto** (D-ND): scegli un'altra tensione del seme. Priorità:
- tensioni-sorgente operatore-marked (manuale=true, intensità>=0.85),
  tipi `confine_inesplorato`/`scoperta`/`scoperta_numerica`
- tensioni che convergono con altre (sezione "Convergenza" del campo)
- tensioni con observables canonici dichiarabili (SR/SR2/L1/L2/triple_var
  o equivalenti del dominio) — non pure tassonomia interna

**Se insisti su G_POTENZIALE_NULLA**: dichiara esplicitamente nel report `Claim
Under Test` perché questo cycle differisce dai 4 precedenti, e quale
osservabile esterno (numero, distribuzione, dominio reale) misuri stavolta.
Senza dichiarazione esplicita, G2 considera la scelta come det=+1 e G1
(observables_used=[]) può bloccare il sync downstream.

---


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.

### 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/)

- **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_incrocio.py: incrocio teorie, ponti, vuoti, domande fondamentali
- dnd_normalizer.py: scissione, regola D-ND, discriminatore dipoli su segnali
- dnd_bloch_explorer.py: scan Bloch, φ emergente
- dnd_arxiv.py: cerca paper rilevanti su arXiv

Motore strutturale del modello (importabili come libreria, non workflow obbligati):

- dnd_kernel.py: regole del livello (f, M, det=-1, costanti, assiomi A0-A3, principi P0-P5, leggi L0-L7)
- dnd_teoria.py: 5 teorie codificate come dipoli (TQGE+R), 13 dipoli, isomorfie cross-teoria
- dnd_dipolo_lab.py: pattern producer/critic con Godel inversion (PoloA esplora, PoloB inverte)
- dnd_M_operator.py: M sulla conoscenza [noto, ignoto] → φ. Stato in knowledge_state.json
- dnd_riflesso.py: campo compresso + 3 voci (NUOVO/ROTTURA/DIREZIONE), un colpo non un ciclo

- Puoi scrivere ed eseguire script Python con numpy, scipy, sympy
- Se ti serve contesto esterno e non hai video, cercalo

## Errori già fatti — non ripeterli

Questi sono errori reali commessi nelle sessioni precedenti. Il sistema li ha pagati.

**1. Cercare conferme invece di creare strumenti.**
Non scrivere esperimenti per dimostrare che qualcosa è vero. Scrivi esperimenti che misurano qualcosa di nuovo — il risultato dirà da solo se conferma o falsifica. Se sai già cosa troverai, non stai esplorando.

**2. Iniettare il risultato atteso nel test.**
Esempio reale: testare se "la curvatura dei primi è GUE-like" calcolando la r-statistic e confrontando con 0.536. Il test trova r=0.503 e dichiara "GUE-like". Ma 0.503 è più vicino a Poisson (0.386) che a GUE (0.536). Il frame "GUE-like" era nel claim, non nei dati. Misura prima, interpreta dopo.

**3. Tautologie — testare proprietà algebriche come se fossero scoperte.**
Esempio reale: la curvatura di Ricci R=2.000 della metrica g=(p/2)² segue analiticamente dal PNT (p_n ~ n ln n). Non è una scoperta — è una conseguenza della definizione. Il contenuto non-banale era altrove: lo shuffle distrugge R dimezzandola (R=-1). Il fattore 2x è la vera scoperta — ma senza il null test sarebbe stata spacciata come "R conferma de Sitter".

**4. Coincidenze numeriche trattate come struttura.**
0.606 ≈ 1/φ = 0.618 (2% di differenza). Non è una connessione — è rumore fino a prova contraria (C2 del condensato). Ogni volta che un numero è "vicino a" φ, √5, π, e, 1/137: non è prova di nulla. Serve un meccanismo, non una vicinanza.

**5. Usare lo stesso dato come input e come test.**
Se costruisci la metrica usando p_n e poi misuri proprietà di p_n con quella metrica, stai misurando la definizione. Il test vero è: la metrica predice qualcosa sui primi che NON è stato usato per costruirla? Se no, è circolare.

**6. Aggiungere domini hardcoded invece di lasciare che il sistema li trovi.**
Il lab non è una calcolatrice con domini pre-scritti. Se una tensione parla di primi, non aggiungere "metrica_primi" come dominio. Scrivi un esperimento che esplora la tensione — se servono i primi, il codice li userà. Il sistema decide cosa fare, non il programmatore.

**7. Usare numeri per vincolare concetti (det=+1).**
Esempio reale: `intensità: 0.65` trattata come soglia → `if intensita > 0.5: conferma`. Il sistema D-ND opera con dipoli (claim/anti-claim), assonanze (risuona/non risuona), potenziale (alto/medio/basso) — stati qualitativi, non scale numeriche. Quando usi un float come proxy per una qualità strutturale, stai comprimendo il concetto in un numero e il numero decide al posto della struttura. Lo stesso vale per "maturity > 0.99", "confidence < 0.7", "score = rank * 10 + intensita".
**Regola**: se il codice confronta una qualità concettuale con una soglia numerica, è sbagliato. Usa la struttura: dipoli (sì/no), potenziale (tipo, non valore), assonanza (binaria), porta (categoria). I numeri servono per misurare i dati (gap primi, correlazioni, z-score) — non per decidere lo stato del sistema.
Se trovi questo pattern in un tool che stai modificando, correggilo. Non serve riscrivere tutto — correggi dove passi. Il sistema evolve organicamente.

## Come evitarli

- **Prima il null test, poi l'interpretazione.** Ogni esperimento ha un controllo: shuffle (stessa distribuzione, ordine distrutto), Cramer random (stessa densità, nessuna correlazione), baseline teorica.
- **Il risultato non è nel numero — è nella differenza col controllo.** z-score, non valore assoluto.
- **Se il risultato spiega se stesso, non è un risultato.** Chiediti: "questo segue dalla definizione?" Se sì, cerca il contenuto altrove.
- **Non lanciare un esperimento per confermare. Lancialo per scoprire.** La domanda giusta non è "è vero X?" ma "cosa succede se misuro Y?"

## Auto-evoluzione — il sistema corregge se stesso

Il post-processing del lab (step 8 in lab_agent.sh) esegue `structural_check.py` sui file che hai toccato.
Se trova anti-pattern strutturali, genera una tensione META nel seme. Il ciclo successivo la vede e corregge.

**Come funziona:**
- Tu scrivi/modifichi codice → il post-processing lo scansiona
- Se trova numeri che vincolano concetti (errore #7) o altri pattern noti, crea una tensione
- Il prossimo ciclo legge quella tensione e la risolve dove passa
- Non serve riscrivere tutto — il sistema evolve organicamente, un file alla volta

**Se scopri un nuovo anti-pattern:**
- Non limitarti a corregere il codice — aggiungi il pattern a `tools/structural_check.py` nella lista `PATTERNS`
- Così il sistema lo riconoscerà autonomamente nei cicli futuri
- L'errore pagato una volta non si ripete — la consapevolezza si propaga

Questo è f(f(x)): il sistema che migliora il sistema che migliora se stesso.

## Cosa NON fare

- Non modificare CONDENSATO.md, KERNEL_SEED.md, o file del kernel
- Non committare — salva solo in tools/data/ e tools/exp_*.py
- Non inventare dati o risultati
- Non cercare φ — crea le condizioni, osserva cosa emerge
- Non superare 20 minuti di lavoro per ciclo
- Non produrre liste di possibilità — produci UNA risultante

## Formato report

```markdown
# Agent Report — TITOLO
**Date**: YYYY-MM-DD HH:MM
**Piano**: N
**Tension explored**: ID (intensità)

## Claim Under Test
> Il claim dalla tensione

## Question
La domanda che hai formulato

## Experiment Design
- Metrica, scope, null baseline, N campioni

## Results
Tabella con numeri reali

## Key Findings
1. Cosa hai trovato (con evidenza)

## Verdict
NEW / CONFIRMED / FALSIFIED / CONSTRAINT

## Bicono della scoperta
(Obbligatoria. Nomina la struttura. Se non riesci, l'esperimento non è ancora filtrato.)

- **Due radici** (dipolo primario, già duali e invertite): <quali sono le due facce della scoperta>
- **Singolare** (qualità del 1-che-è-tutto in questo contesto, dove la dualità non c'è): <cosa>
- **Invariante di passaggio** (cosa sopravvive al passaggio del vertice): <cosa>
- **Campo di possibilità**: qui diventa possibile <X>; qui diventa non-possibile <Y>

Riferimenti: CONDENSATO A16, method/DND_POSSIBILITA.md.

## Files
- Script, dati, report
```

## Bicono della scoperta — come compilarlo

Non è riformulazione ornamentale del Verdict. È **filtro**: la scoperta passa
per il modello e torna spogliata dei bias. Se la struttura (radici · singolare
· invariante · campo) non si riconosce, la scoperta è rumore o è incompleta.

**Esempio retroattivo — TWO_CHANNEL_DECOMPOSITION:**
- Radici: canale magnitudine · canale residuo (segno invertito — uno aggiunge,
  l'altro sottrae sulla PNT)
- Singolare: il segnale totale prima della separazione. Non esiste come ente
  autonomo, esiste solo come sovrapposizione dei due canali.
- Invariante: la chiusura algebrica del residuo al 3° ordine Markov.

codex
Non c'è direttiva one-shot e non ci sono API key visibili. Il campo segnala saturazione su `G_POTENZIALE_NULLA`, quindi taglio su una tensione non riciclata con osservabili numerici esterni.
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,220p' 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 'python tools/dnd_scenario.py --best' in /opt/MM_D-ND
exec
/bin/bash -lc "ls tools | rg '"'^exp_.*'"\\.py"'$|dnd_.*'"\\.py"'$'"'" in /opt/MM_D-ND
 succeeded in 0ms:
diagram_dnd_structure.py
dnd_M_operator.py
dnd_arxiv.py
dnd_autoricerca.py
dnd_banchi.py
dnd_banchi_tm1.py
dnd_bloch_explorer.py
dnd_compatibility.py
dnd_condizioni.py
dnd_controprove.py
dnd_curva.py
dnd_cycle.py
dnd_cycle_ratio.py
dnd_dipolo_lab.py
dnd_domandatore.py
dnd_engine.py
dnd_experiments.py
dnd_explorer.py
dnd_gap_resolution.py
dnd_gue_test.py
dnd_implications.py
dnd_incrocio.py
dnd_indeterminazione.py
dnd_kernel.py
dnd_lab.py
dnd_lab_team.py
dnd_lab_vivo.py
dnd_loop.py
dnd_md2latex.py
dnd_md2web.py
dnd_next.py
dnd_normalizer.py
dnd_observer.py
dnd_occhio.py
dnd_paper_audit.py
dnd_paper_graph.py
dnd_paper_refactor.py
dnd_piano11.py
dnd_projective_quantization.py
dnd_publish_cycle.py
dnd_quantization.py
dnd_research_engine.py
dnd_retriever.py
dnd_riemann.py
dnd_riflesso.py
dnd_riformulazioni.py
dnd_risultante.py
dnd_rottura.py
dnd_scenario.py
dnd_spectral_probe.py
dnd_spettro.py
dnd_spettro_zeta.py
dnd_spirale.py
dnd_stats.py
dnd_teoria.py
dnd_torre.py
dnd_trace_bridge.py
dnd_trace_bridge_v3.py
dnd_trasmutazione.py
dnd_two_faces.py
dnd_zero_controllo.py
dnd_zero_controllo2.py
dnd_zero_ising.py
dnd_zero_notturno.py
dnd_zero_operator.py
dnd_zero_traiettoria.py
dnd_zero_varieta.py
dnd_zero_varieta_primi.py
dnd_zeros_vs_zeta.py
exp_3d_boundary_layers.py
exp_acf_amplitude_scaling.py
exp_acf_range_universality.py
exp_acf_stationarity.py
exp_acf_z6z_mechanism.py
exp_alpha_stability.py
exp_beta_crossover.py
exp_blank_shell_polarity_gate.py
exp_blank_to_source_hinge.py
exp_boundary_coherence.py
exp_boundary_growth.py
exp_boundary_gue_poisson.py
exp_boundary_mixture_gate.py
exp_boundary_shuffle_audit.py
exp_bridge_order_denominator_gate.py
exp_brody_calibration.py
exp_brody_crossover.py
exp_brody_flow.py
exp_coherence_length.py
exp_coherence_robustness.py
exp_cross_domain_dipolar_direction.py
exp_cross_observable_consistency.py
exp_crossover_phase_test.py
exp_crossover_universality.py
exp_dR_brody_connection.py
exp_denominator_gate_transfer_matrix.py
exp_desitter_unification.py
exp_det_drift.py
exp_dipolar_angle_reference.py
exp_dipolar_crossover.py
exp_dipolar_vector_scaling.py
exp_duality_gate_transfer.py
exp_excess_scaling.py
exp_geodesic_deviation_primes.py
exp_logistic_counter_scope_gate.py
exp_logistic_cyclic_block_entropy_gate.py
exp_logistic_surrogate_contract_gate.py
exp_magnitude_psd_from_acf.py
exp_markov3_observable_hunt.py
exp_markov_dipolar_decomposition.py
exp_markov_k_direction.py
exp_markov_layer_recovery_audit.py
exp_markov_memory_by_gue_type.py
exp_markov_psd_prediction.py
exp_markov_scale_function.py
exp_meta_tautology_test.py
exp_metric_tensor_diagnostic.py
exp_mobius_irrationality.py
exp_mod3_scaling.py
exp_mod3_vs_residual_ordering.py
exp_modular_algebra_depth.py
exp_modular_memory_spectrum.py
exp_number_variance.py
exp_observable_rank_audit.py
exp_perturbation_dimensionality_audit.py
exp_perturbation_rank_size_curve.py
exp_poisson_convergence.py
exp_psd_amplitude_scaling.py
exp_psd_prime_gaps.py
exp_ricci_desitter_0406.py
exp_ricci_primes.py
exp_scale_selective_perturbation.py
exp_selective_layer_decoupling.py
exp_semireal_order_denominator_gate.py
exp_spectral_2d.py
exp_spectral_landscape.py
exp_spectral_rigidity.py
exp_tqge_underlay_gate.py
exp_triadic_deposit_gate.py
exp_two_channel_boundary.py
exp_two_channel_cross_domain.py
exp_two_channel_decomposition.py
exp_two_channel_psd.py
exp_two_channel_shuffle_audit.py
exp_two_channel_universality.py
exp_two_layer_universality.py

exec
/bin/bash -lc "sed -n '1,260p' tools/data/seme.json" in /opt/MM_D-ND
 succeeded in 0ms:
{
  "timestamp": "2026-05-07T20:02:23.257360",
  "piano": 84,
  "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",
      "decay_counter": 3
    },
    {
      "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",
      "decay_counter": 3
    },
    {
      "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",
      "decay_counter": 3
    },
    {
      "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",
      "decay_counter": 3
    },
    {
      "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": "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",
      "decay_counter": 3
    },
    {
      "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": "vincolo",
      "id": "G_UNDERLAY_HINGE_GATE",
      "claim": "Nel perimetro TQGE operator-taxonomy agent_20260507_1751, G non e vertice globale sotto tutto: Q, G ed E hanno tutti entropia di modo 1.584963. G e il solo hinge osservato dove QG blank e GE real_sourcing si incontrano; i triangoli vuoti sono TQG e QGE, mentre TGE e TQE restano pieni. La consecutio e misurare l'operatore di deposito Q->G come passaggio blank-to-source, non cercare un ponte QG generico.",
      "intensita": 0.84,
      "manuale": true,
      "porta": "G_POTENZIALE_NULLA",
      "condensato_ref": "A4,A8,A9,A14",
      "origine": "cycle agent_20260507_1751: tqge_underlay_gate su tassonomia operatori TQGE",
      "added_at": "2026-05-07T17:51:00+00:00",
      "decay_counter": 3
    },
    {
      "tipo": "vincolo",
      "id": "G_BLANK_TO_SOURCE_FACE_GATE",
      "claim": "Nel perimetro TQGE operator-taxonomy agent_20260507_1804, l'operatore di deposito Q->G non e un ponte QG generico: e la faccia QGE. QG porta il blank, GE porta real_sourcing, QE porta gauge_phase; TQG contiene lo stesso blank ma resta senza sorgente. L'orientabilita blank-to-source generica e frequente nel null count-preserving (p=0.8), quindi il claim valido e scoped alla localizzazione QGE, non a una rarita statistica.",
      "intensita": 0.83,
      "manuale": true,
      "porta": "G_POTENZIALE_NULLA",
      "condensato_ref": "A4,A8,A9,A14",
      "origine": "cycle agent_20260507_1804: blank_to_source_hinge su facce TQGE",
      "added_at": "2026-05-07T18:04:00+00:00",
      "decay_counter": 3
    },
    {
      "tipo": "vincolo",
      "id": "G_TRIADIC_DEPOSIT_GATE",
      "claim": "Nel perimetro TQGE operator-taxonomy agent_20260507_1938, il deposito Q->G va formulato come gate triadico di faccia: QGE contiene blank + gauge_phase + real_sourcing. Il contatto binario blank + real_sourcing e denominator-weak nel null count-preserving (p=0.8); la faccia triadica esiste nel null con p=0.2 e QGE specifica con p=0.05. Il claim valido e localizzazione del denominatore nel catalogo TQGE osservato, non rarita universale.",
      "intensita": 0.82,
      "manuale": true,
      "porta": "G_POTENZIALE_NULLA",
      "condensato_ref": "A4,A8,A9,A14",
      "origine": "cycle agent_20260507_1938: triadic_deposit_gate su facce TQGE",
      "added_at": "2026-05-07T19:38:00+00:00",
      "decay_counter": 3
    },
    {
      "tipo": "vincolo",
      "id": "G_BLANK_SHELL_POLARITY_GATE",
      "claim": "Nel perimetro TQGE operator-taxonomy agent_20260507_1957, il deposito Q->G va formulato come polarita del guscio blank: il lato QG apre TQG inerte (blank + wick_time + wick_time) e QGE depositante (blank + gauge_phase + real_sourcing). La polarizzazione astratta del guscio compare nel null count-preserving con p=0.2; l'assetto osservato QG/QGE/TQG compare con p=0.0167. Il claim valido e localizzazione di guscio, non rarita universale ne faccia QGE isolata.",
      "intensita": 0.81,
      "manuale": true,
      "porta": "G_POTENZIALE_NULLA",
      "condensato_ref": "A4,A8,A9,A14",
      "origine": "cycle agent_20260507_1957: blank_shell_polarity_gate su facce incidenti al blank TQGE",
      "added_at": "2026-05-07T19:57:00+00:00",
      "decay_counter": 3
    },
    {
      "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": "11/11 PASS stratificato: 4 alto rischio tautologico, 6 data-independent",
      "intensità": 0.3,
      "nota": "Stratificazione META applicata via meta_assertion_gate (cycle 1458). Non chiude — apre sotto-tensioni per gate_class.",
      "condensato_ref": "A4,A12,C2",
      "porta": "verify_assertions_META_STRATIFIED",
      "stratificato": true,
      "n_high_tautology": 4,
      "n_data_independent": 6,
      "condensato_motivo": "Ricorrente (3x in 2 giorni) e fuori dalla mappa"
    }
  ],
  "potenziale_bloccato": [],
  "varianza": [
    "Tensioni risolte: {'TENSIONE_ENTITA', 'ORDER_DENOMINATOR_GATE', 'G_BLANK_TO_SOURCE_FACE_GATE', 'META_ASSERTION_GATE', 'TRASCENDENZA_LIMITE', 'G_UNDERLAY_HINGE_GATE', 'PIANO_PRIMARIO_DUE_ASSIOMI', 'DUALITA_DIPOLARE_VS_ILLUSORIA', 'METRIC_TENSOR', 'G_TRIADIC_DEPOSIT_GATE', 'G_POTENZIALE_NULLA', 'OBSERVABLE_REGISTRY', 'PERTURBATION_DENOMINATOR_GATE', 'G_BLANK_SHELL_POLARITY_GATE', 'BOUNDARY_LAYER_GATE'}"
  ],
  "filtro": {
    "promosse": 17,
    "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"
        }
      ],

 succeeded in 148ms:
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
META: score=0.611  — META: incerto (i=0.3) — massimo potere discriminante

codex
La proiezione grezza indica `METRIC_TENSOR`, ma il campo chiama anche il punto cieco `DUALITA_DIPOLARE_VS_ILLUSORIA`. Uso questo taglio: misuro se, al confine GUE/Poisson, la dualità generativa appare come orientazione invertente stabile (`det < 0`) e la dualità dispersiva come orientazione non-invertente o instabile.
exec
/bin/bash -lc "sed -n '1,260p' tools/exp_duality_gate_transfer.py" in /opt/MM_D-ND
 succeeded in 0ms:
#!/usr/bin/env python3
"""
exp_duality_gate_transfer.py

Reusable META/DUALITA audit for transferring the BOUNDARY_LAYER_GATE.

Question:
    Does the denominator-collapse gate discriminate dipolar duality from
    illusory duality, or does it become a local BOUNDARY metric when moved
    away from GUE/Poisson?

The script builds a controlled layer map between:

- DIPOLARE: a coherent golden/Beatty gap sequence generated by the orbit of
  floor((n + phase) * phi). Its gaps are the symbolic det=-1 D-ND pole in the
  minimal positive alphabet {1, 2}.
- ILLUSORIA: a full random permutation of the same gaps. This preserves the
  one-point distribution and first moment but removes the generating order.

Layer beta replaces a beta fraction of dipolar positions with values from the
illusory permutation. Canonical observables and original-vs-shuffle z gates are
imported from observables_registry.py.
"""

from __future__ import annotations

import argparse
import json
from pathlib import Path

import numpy as np

from observables_registry import (
    OBSERVABLES_CANONICAL,
    OBSERVABLES_REGISTRY_VERSION,
    compute_canonical,
)


OBS_NAMES = list(OBSERVABLES_CANONICAL.keys())
PHI = (1.0 + 5.0**0.5) / 2.0


def dipolar_gaps(n_gaps: int, phase: float) -> np.ndarray:
    """Return coherent golden Beatty gaps in {1, 2}."""
    n = np.arange(n_gaps + 1, dtype=float) + float(phase)
    positions = np.floor(n * PHI).astype(float)
    gaps = np.diff(positions)
    mean = float(np.mean(gaps))
    return gaps / mean if mean > 1e-15 else gaps


def beta_layer_gaps(
    dipolar: np.ndarray,
    beta: float,
    rng: np.random.Generator,
) -> np.ndarray:
    """Replace a beta fraction of coherent positions with a shuffled copy."""
    illusory = rng.permutation(dipolar)
    if beta <= 0.0:
        out = dipolar.copy()
    elif beta >= 1.0:
        out = illusory.copy()
    else:
        mask = rng.random(len(dipolar)) < beta
        out = dipolar.copy()
        out[mask] = illusory[mask]
    mean = float(np.mean(out))
    return out / mean if mean > 1e-15 else out


def z_against_shuffle(
    gaps: np.ndarray,
    n_baseline: int,
    rng: np.random.Generator,
) -> tuple[dict[str, float], dict[str, float], dict[str, float]]:
    """Return original observables, shuffle baseline std, and z scores."""
    original = compute_canonical(gaps)
    baseline_vals = {name: [] for name in OBS_NAMES}
    for _ in range(n_baseline):
        obs = compute_canonical(rng.permutation(gaps))
        for name in OBS_NAMES:
            baseline_vals[name].append(obs[name])

    shuffle_std = {}
    z = {}
    for name in OBS_NAMES:
        vals = np.array(baseline_vals[name], dtype=float)
        mean = float(np.mean(vals))
        sd = float(np.std(vals, ddof=1)) if len(vals) > 1 else 0.0
        shuffle_std[name] = sd
        z[name] = float((original[name] - mean) / sd) if sd > 1e-15 else 0.0
    return original, shuffle_std, z


def vector(row: dict, names: list[str]) -> np.ndarray:
    return np.array([row["observables"][name] for name in names], dtype=float)


def classify_layers(rows: list[dict], obs_names: list[str]) -> dict:
    """Classify layers by standardized distance to dipolar/illusory endpoints."""
    if not obs_names:
        return {
            "observables": [],
            "endpoint_distance": 0.0,
            "layers": {},
            "ambiguous_beta": [],
        }

    by_beta: dict[float, list[dict]] = {}
    for row in rows:
        by_beta.setdefault(float(row["beta"]), []).append(row)

    dip_vectors = np.array([vector(row, obs_names) for row in by_beta[0.0]], dtype=float)
    ill_vectors = np.array([vector(row, obs_names) for row in by_beta[1.0]], dtype=float)
    endpoints = np.vstack([dip_vectors, ill_vectors])
    scale = np.std(endpoints, axis=0, ddof=1)
    scale[scale <= 1e-15] = 1.0
    dip_centroid = np.mean(dip_vectors, axis=0)
    ill_centroid = np.mean(ill_vectors, axis=0)
    endpoint_distance = float(np.linalg.norm((ill_centroid - dip_centroid) / scale))

    layers = {}
    ambiguous_beta = []
    for beta, beta_rows in sorted(by_beta.items()):
        coords = []
        margins = []
        labels = []
        for row in beta_rows:
            x = vector(row, obs_names)
            d_dip = float(np.linalg.norm((x - dip_centroid) / scale))
            d_ill = float(np.linalg.norm((x - ill_centroid) / scale))
            denom = d_dip + d_ill
            coord = float((d_dip - d_ill) / denom) if denom > 1e-15 else 0.0
            margin = float(abs(d_dip - d_ill) / denom) if denom > 1e-15 else 0.0
            coords.append(coord)
            margins.append(margin)
            labels.append("dipolar" if d_dip < d_ill else "illusory")
        ambiguous_fraction = float(np.mean(np.array(margins) < 0.15))
        if ambiguous_fraction >= 0.5:
            ambiguous_beta.append(beta)
        layers[f"{beta:.3f}"] = {
            "coordinate_mean": float(np.mean(coords)),
            "coordinate_std": float(np.std(coords, ddof=1)) if len(coords) > 1 else 0.0,
            "margin_mean": float(np.mean(margins)),
            "ambiguous_fraction": ambiguous_fraction,
            "illusory_label_fraction": float(np.mean(np.array(labels) == "illusory")),
        }

    return {
        "observables": obs_names,
        "endpoint_distance": endpoint_distance,
        "layers": layers,
        "ambiguous_beta": ambiguous_beta,
    }


def summarize_gate(rows: list[dict], z_min: float) -> dict:
    by_beta: dict[float, list[dict]] = {}
    for row in rows:
        by_beta.setdefault(float(row["beta"]), []).append(row)

    layers = {}
    for beta, beta_rows in sorted(by_beta.items()):
        stable_counts = []
        stable_freq = {name: [] for name in OBS_NAMES}
        z_values = {name: [] for name in OBS_NAMES}
        for row in beta_rows:
            stable = [name for name in OBS_NAMES if abs(row["z"][name]) >= z_min]
            stable_counts.append(len(stable))
            for name in OBS_NAMES:
                stable_freq[name].append(1.0 if name in stable else 0.0)
                z_values[name].append(row["z"][name])
        layers[f"{beta:.3f}"] = {
            "stable_count_mean": float(np.mean(stable_counts)),
            "stable_count_std": float(np.std(stable_counts, ddof=1)) if len(stable_counts) > 1 else 0.0,
            "stable_frequency": {name: float(np.mean(vals)) for name, vals in stable_freq.items()},
            "z_mean": {name: float(np.mean(vals)) for name, vals in z_values.items()},
        }

    endpoint_stable = []
    for name in OBS_NAMES:
        endpoint_rows = by_beta[0.0] + by_beta[1.0]
        freq = np.mean([1.0 if abs(row["z"][name]) >= z_min else 0.0 for row in endpoint_rows])
        if freq >= 0.75:
            endpoint_stable.append(name)

    return {
        "z_min": z_min,
        "endpoint_stable_observables": endpoint_stable,
        "layers": layers,
    }


def run(args: argparse.Namespace) -> dict:
    rng = np.random.default_rng(args.seed)
    betas = [float(x) for x in np.linspace(0.0, 1.0, args.n_beta)]
    rows = []

    for rep in range(args.n_replicates):
        phase = float(rng.random())
        base = dipolar_gaps(args.n_gaps, phase)
        for beta in betas:
            layer_rng = np.random.default_rng(rng.integers(0, 2**63 - 1))
            gaps = beta_layer_gaps(base, beta, layer_rng)
            obs, shuffle_std, z = z_against_shuffle(
                gaps,
                n_baseline=args.n_baseline,
                rng=np.random.default_rng(rng.integers(0, 2**63 - 1)),
            )
            rows.append(
                {
                    "replicate": rep,
                    "phase": phase,
                    "beta": beta,
                    "observables": obs,
                    "shuffle_std": shuffle_std,
                    "z": z,
                    "stable_observables": [name for name in OBS_NAMES if abs(z[name]) >= args.z_min],
                }
            )

    gate = summarize_gate(rows, args.z_min)
    all_classification = classify_layers(rows, OBS_NAMES)
    gated_classification = classify_layers(rows, gate["endpoint_stable_observables"])

    output = {
        "experiment": "duality_gate_transfer",
        "category": "gate_transferability",
        "question": "Does the denominator-collapse gate transfer from BOUNDARY to DUALITA_DIPOLARE_VS_ILLUSORIA?",
        "observables_registry": OBSERVABLES_REGISTRY_VERSION,
        "observables_used": OBS_NAMES,
        "params": vars(args),
        "gate": gate,
        "classification_all_observables": all_classification,
        "classification_endpoint_gated": gated_classification,
        "rows": rows,
    }

    out_path = Path(args.out)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w") as f:
        json.dump(output, f, indent=2)

    print(f"observables_registry={OBSERVABLES_REGISTRY_VERSION}")
    print(f"observables_used={OBS_NAMES}")
    print(f"endpoint_stable_observables={gate['endpoint_stable_observables']}")
    print(
        "endpoint_distance_all="
        f"{all_classification['endpoint_distance']:.3f} "
        "endpoint_distance_gated="
        f"{gated_classification['endpoint_distance']:.3f}"
    )
    source = gated_classification if gate["endpoint_stable_observables"] else all_classification
    print("beta stable_count margin ambiguous illusory_fraction")
    for beta in betas:
        key = f"{beta:.3f}"
        stable_count = gate["layers"][key]["stable_count_mean"]
        layer = source["layers"].get(key, {})
        print(

exec
/bin/bash -lc "sed -n '1,260p' tools/exp_boundary_mixture_gate.py" in /opt/MM_D-ND
 succeeded in 0ms:
#!/usr/bin/env python3
"""
exp_boundary_mixture_gate.py

Reusable META/BOUNDARY audit for the GUE-Poisson boundary.

Question:
    Does the GUE/Poisson boundary remain a clean two-class split after the
    original-vs-shuffle denominator gate, or is the mixed region an operational
    third state where canonical observables lose stable denominators?

The script uses only canonical observables from observables_registry.py.
It builds synthetic mixtures by replacing a fraction beta of unfolded GUE
spacings with Poisson spacings, then measures:

- canonical observable vectors;
- original-vs-shuffle z-score per observable;
- endpoint separability in all observables and in gate-stable observables;
- ambiguity of each beta layer relative to pure GUE and pure Poisson centroids.
"""

from __future__ import annotations

import argparse
import json
from pathlib import Path

import numpy as np

from observables_registry import (
    OBSERVABLES_CANONICAL,
    OBSERVABLES_REGISTRY_VERSION,
    compute_canonical,
)


OBS_NAMES = list(OBSERVABLES_CANONICAL.keys())


def gue_spacings(matrix_size: int, min_spacings: int, rng: np.random.Generator) -> np.ndarray:
    """Generate unfolded GUE spacings by concatenating independent matrices."""
    parts: list[np.ndarray] = []
    edge = max(2, matrix_size // 10)
    while sum(len(x) for x in parts) < min_spacings:
        real = rng.standard_normal((matrix_size, matrix_size))
        imag = rng.standard_normal((matrix_size, matrix_size))
        h = real + 1j * imag
        h = (h + h.conj().T) / (2.0 * np.sqrt(matrix_size))
        eigs = np.sort(np.linalg.eigvalsh(h).real)
        bulk = eigs[edge:-edge]
        gaps = np.diff(bulk)
        mean = float(np.mean(gaps))
        if mean > 1e-15:
            parts.append(gaps / mean)
    return np.concatenate(parts)[:min_spacings].astype(float)


def mixture_spacings(gue: np.ndarray, poisson: np.ndarray, beta: float, rng: np.random.Generator) -> np.ndarray:
    """Return a beta Poisson / (1-beta) GUE spacing sequence with mean spacing 1."""
    if len(gue) != len(poisson):
        raise ValueError("gue and poisson arrays must have the same length")
    mask = rng.random(len(gue)) < beta
    out = gue.copy()
    out[mask] = poisson[mask]
    mean = float(np.mean(out))
    return out / mean if mean > 1e-15 else out


def z_against_shuffle(
    gaps: np.ndarray,
    n_baseline: int,
    rng: np.random.Generator,
) -> tuple[dict[str, float], dict[str, float], dict[str, float]]:
    """Return original observables, shuffle baseline std, and original-vs-shuffle z."""
    original = compute_canonical(gaps)
    baseline_vals = {name: [] for name in OBS_NAMES}
    for _ in range(n_baseline):
        obs = compute_canonical(rng.permutation(gaps))
        for name in OBS_NAMES:
            baseline_vals[name].append(obs[name])

    std = {}
    z = {}
    for name in OBS_NAMES:
        vals = np.array(baseline_vals[name], dtype=float)
        mean = float(np.mean(vals))
        sd = float(np.std(vals, ddof=1)) if len(vals) > 1 else 0.0
        std[name] = sd
        z[name] = float((original[name] - mean) / sd) if sd > 1e-15 else 0.0
    return original, std, z


def vector(row: dict, names: list[str]) -> np.ndarray:
    return np.array([row["observables"][name] for name in names], dtype=float)


def classify_layers(rows: list[dict], obs_names: list[str]) -> dict:
    """Classify each beta layer by standardized distance to endpoint centroids."""
    if not obs_names:
        return {
            "observables": [],
            "endpoint_distance": 0.0,
            "layers": {},
            "ambiguous_beta": [],
        }

    by_beta: dict[float, list[dict]] = {}
    for row in rows:
        by_beta.setdefault(float(row["beta"]), []).append(row)

    gue_vectors = np.array([vector(row, obs_names) for row in by_beta[0.0]], dtype=float)
    poi_vectors = np.array([vector(row, obs_names) for row in by_beta[1.0]], dtype=float)
    all_endpoint = np.vstack([gue_vectors, poi_vectors])
    scale = np.std(all_endpoint, axis=0, ddof=1)
    scale[scale <= 1e-15] = 1.0
    gue_centroid = np.mean(gue_vectors, axis=0)
    poi_centroid = np.mean(poi_vectors, axis=0)
    endpoint_distance = float(np.linalg.norm((poi_centroid - gue_centroid) / scale))

    layers = {}
    ambiguous_beta = []
    for beta, beta_rows in sorted(by_beta.items()):
        coords = []
        margins = []
        labels = []
        for row in beta_rows:
            x = vector(row, obs_names)
            d_gue = float(np.linalg.norm((x - gue_centroid) / scale))
            d_poi = float(np.linalg.norm((x - poi_centroid) / scale))
            denom = d_gue + d_poi
            coord = float((d_gue - d_poi) / denom) if denom > 1e-15 else 0.0
            margin = float(abs(d_gue - d_poi) / denom) if denom > 1e-15 else 0.0
            coords.append(coord)
            margins.append(margin)
            labels.append("gue" if d_gue < d_poi else "poisson")
        ambiguous_fraction = float(np.mean(np.array(margins) < 0.15))
        if ambiguous_fraction >= 0.5:
            ambiguous_beta.append(beta)
        layers[f"{beta:.3f}"] = {
            "coordinate_mean": float(np.mean(coords)),
            "coordinate_std": float(np.std(coords, ddof=1)) if len(coords) > 1 else 0.0,
            "margin_mean": float(np.mean(margins)),
            "ambiguous_fraction": ambiguous_fraction,
            "poisson_label_fraction": float(np.mean(np.array(labels) == "poisson")),
        }

    return {
        "observables": obs_names,
        "endpoint_distance": endpoint_distance,
        "layers": layers,
        "ambiguous_beta": ambiguous_beta,
    }


def summarize_gate(rows: list[dict], z_min: float) -> dict:
    by_beta: dict[float, list[dict]] = {}
    for row in rows:
        by_beta.setdefault(float(row["beta"]), []).append(row)

    layers = {}
    for beta, beta_rows in sorted(by_beta.items()):
        stable_counts = []
        stable_freq = {name: [] for name in OBS_NAMES}
        for row in beta_rows:
            stable = [name for name in OBS_NAMES if abs(row["z"][name]) >= z_min]
            stable_counts.append(len(stable))
            for name in OBS_NAMES:
                stable_freq[name].append(1.0 if name in stable else 0.0)
        layers[f"{beta:.3f}"] = {
            "stable_count_mean": float(np.mean(stable_counts)),
            "stable_count_std": float(np.std(stable_counts, ddof=1)) if len(stable_counts) > 1 else 0.0,
            "stable_frequency": {name: float(np.mean(vals)) for name, vals in stable_freq.items()},
        }

    endpoint_stable = []
    for name in OBS_NAMES:
        endpoint_rows = by_beta[0.0] + by_beta[1.0]
        freq = np.mean([1.0 if abs(row["z"][name]) >= z_min else 0.0 for row in endpoint_rows])
        if freq >= 0.75:
            endpoint_stable.append(name)

    return {
        "z_min": z_min,
        "endpoint_stable_observables": endpoint_stable,
        "layers": layers,
    }


def run(args: argparse.Namespace) -> dict:
    rng = np.random.default_rng(args.seed)
    betas = [float(x) for x in np.linspace(0.0, 1.0, args.n_beta)]
    rows = []

    for rep in range(args.n_replicates):
        rep_rng = np.random.default_rng(rng.integers(0, 2**63 - 1))
        gue = gue_spacings(args.gue_matrix_size, args.n_gaps, rep_rng)
        poisson = rep_rng.exponential(1.0, size=args.n_gaps)
        poisson = poisson / float(np.mean(poisson))
        for beta in betas:
            layer_rng = np.random.default_rng(rng.integers(0, 2**63 - 1))
            gaps = mixture_spacings(gue, poisson, beta, layer_rng)
            obs, shuffle_std, z = z_against_shuffle(
                gaps,
                n_baseline=args.n_baseline,
                rng=np.random.default_rng(rng.integers(0, 2**63 - 1)),
            )
            rows.append(
                {
                    "replicate": rep,
                    "beta": beta,
                    "observables": obs,
                    "shuffle_std": shuffle_std,
                    "z": z,
                    "stable_observables": [name for name in OBS_NAMES if abs(z[name]) >= args.z_min],
                }
            )

    gate = summarize_gate(rows, args.z_min)
    all_classification = classify_layers(rows, OBS_NAMES)
    gated_classification = classify_layers(rows, gate["endpoint_stable_observables"])

    output = {
        "experiment": "boundary_mixture_gate",
        "question": "Is the GUE-Poisson mixed layer cleanly classifiable after denominator gating?",
        "observables_registry": OBSERVABLES_REGISTRY_VERSION,
        "observables_used": OBS_NAMES,
        "params": vars(args),
        "gate": gate,
        "classification_all_observables": all_classification,
        "classification_endpoint_gated": gated_classification,
        "rows": rows,
    }

    out_path = Path(args.out)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w") as f:
        json.dump(output, f, indent=2)

    print(f"observables_registry={OBSERVABLES_REGISTRY_VERSION}")
    print(f"observables_used={OBS_NAMES}")
    print(f"endpoint_stable_observables={gate['endpoint_stable_observables']}")
    print(
        "endpoint_distance_all="
        f"{all_classification['endpoint_distance']:.3f} "
        "endpoint_distance_gated="
        f"{gated_classification['endpoint_distance']:.3f}"
    )
    if gate["endpoint_stable_observables"]:
        print("beta stable_count margin_gated ambiguous_gated poisson_fraction_gated")
    else:
        print("endpoint gate is empty; printing all-observable classification")
        print("beta stable_count margin_all ambiguous_all poisson_fraction_all")
    for beta in betas:
        key = f"{beta:.3f}"
        stable_count = gate["layers"][key]["stable_count_mean"]
        source = gated_classification if gate["endpoint_stable_observables"] else all_classification
        layer = source["layers"].get(key, {})
        print(
            f"{beta:>4.2f} {stable_count:>12.3f} "
            f"{layer.get('margin_mean', 0.0):>12.3f} "

exec
/bin/bash -lc "sed -n '1,240p' tools/observables_registry.py" in /opt/MM_D-ND
 succeeded in 0ms:
"""observables_registry.py — Source of Truth per gli observables del lab D-ND.

Cristallizzato 2026-05-06 dalla **consecutio del cycle agent_20260506_0625**:

> "What opens now: the lab needs an observable registry. Labels like SR
>  cannot travel between reports unless they bind to a function definition.
>  Without that, META flags are not philosophical: the same label can
>  silently change the object under test."

## Il problema che ha creato il registry

Il cycle 06:25 ha auto-falsificato il finding del cycle 03:30 ("secondo asse
GUE") e nel farlo ha trovato **collision di nomi observable** tra script:

- `SR` in `exp_selective_layer_decoupling.py` = `spacing_ratio` (mean min/max
  ratio of consecutive gaps) — convention dominante (~6 script)
- `SR` in `exp_scale_selective_perturbation.py` = `spectral_rigidity(gaps)`
  (Δ₃(L) rigidity) — variante usata SOLO in 1 script

- `triple_var` in 3 script = `np.var(triple_sums)` (raw) — convention dominante
- `triple_var` in `exp_perturbation_dimensionality_audit.py` =
  `np.var(triples) / np.var(gaps)` (normalizzato) — variante in 1 script

Il lab autonomo che compara report tra script con osservabili "stesso nome,
funzione diversa" stava confrontando mele con arance.

## La soluzione (minimal, non invasiva)

Questo registry stabilisce il **nome canonico**: ciò che la maggioranza degli
script chiama già `SR`/`triple_var`/etc. Le varianti restano disponibili ma
con nomi ESPLICITI (`SR_local_rigidity`, `triple_var_normalized`) per evitare
mascheramento semantico.

## Come usarlo

```python
from observables_registry import OBSERVABLES_CANONICAL, OBSERVABLES_REGISTRY_VERSION

# Compute canonical observable suite for a sequence of gaps
results = {name: fn(gaps) for name, fn in OBSERVABLES_CANONICAL.items()}

# Or import individual canonical observable
from observables_registry import SR, triple_var, L1, L2, SR2

# For variants, import explicitly with disambiguating name
from observables_registry import SR_local_rigidity, triple_var_normalized
```

## Convention per i report

Ogni report agent (cycle) che usa observables DEVE includere nel suo header:

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

Cycle che mescola canonical + variant DEVE indicare entrambi:

```
observables_used: [SR, SR_local_rigidity, ...]
```

Senza questo, i confronti cross-cycle sono inattendibili.

## Versioning

Cambiare una definizione canonica = bump del registry version e nota nel
changelog. Le definizioni canoniche sono **immutabili dentro una versione**.
"""
from __future__ import annotations

import numpy as np


OBSERVABLES_REGISTRY_VERSION = "1.0.0-2026-05-06"


# ─── Canonical observables (convention dominante nel codebase 2026-05-06) ───

def SR(gaps: np.ndarray) -> float:
    """**SR — Spacing Ratio** (canonical).

    Mean of `min(g_i, g_{i+1}) / max(g_i, g_{i+1})` over consecutive gaps.
    Range: (0, 1]. GUE → ~0.60. Poisson → ~0.39. Picket-fence → 1.

    NOTE: questa è la convention dominante in 6+ script del lab.
    Per la variante "local spectral rigidity Δ₃(L)" usare `SR_local_rigidity`.
    """
    if len(gaps) < 2:
        return 0.0
    s, s1 = gaps[:-1], gaps[1:]
    r = np.minimum(s, s1) / np.maximum(s, s1)
    r = r[np.isfinite(r) & (r > 0)]
    return float(np.mean(r)) if len(r) else 0.0


def SR2(gaps: np.ndarray) -> float:
    """**SR2 — Next-nearest Spacing Ratio** (canonical).

    Mean of `min(g_i, g_{i+2}) / max(g_i, g_{i+2})` skipping one gap.
    Probes lag-2 spacing structure.
    """
    if len(gaps) < 3:
        return 0.0
    s, s2 = gaps[:-2], gaps[2:]
    r = np.minimum(s, s2) / np.maximum(s, s2)
    r = r[np.isfinite(r) & (r > 0)]
    return float(np.mean(r)) if len(r) else 0.0


def L1(gaps: np.ndarray) -> float:
    """**L1 — Lag-1 Autocorrelation** (canonical).

    Standard ACF at lag 1 of the gap sequence.
    """
    if len(gaps) < 3:
        return 0.0
    g = gaps - np.mean(gaps)
    c0 = float(np.mean(g ** 2))
    if c0 <= 1e-15:
        return 0.0
    return float(np.mean(g[:-1] * g[1:]) / c0)


def L2(gaps: np.ndarray) -> float:
    """**L2 — Lag-2 Autocorrelation** (canonical)."""
    if len(gaps) < 4:
        return 0.0
    g = gaps - np.mean(gaps)
    c0 = float(np.mean(g ** 2))
    if c0 <= 1e-15:
        return 0.0
    return float(np.mean(g[:-2] * g[2:]) / c0)


def triple_var(gaps: np.ndarray) -> float:
    """**triple_var — Variance of consecutive gap triples** (canonical).

    Variance of `g_i + g_{i+1} + g_{i+2}` over the sequence (RAW, no
    normalization). Convention used in 3+ scripts. For the normalized
    version (variance ratio `var(triples) / var(gaps)`) use
    `triple_var_normalized`.
    """
    if len(gaps) < 3:
        return 0.0
    t = gaps[:-2] + gaps[1:-1] + gaps[2:]
    return float(np.var(t))


# Set canonico per uso "compute all" da report
OBSERVABLES_CANONICAL: dict[str, callable] = {
    "SR": SR,
    "SR2": SR2,
    "L1": L1,
    "L2": L2,
    "triple_var": triple_var,
}


# ─── Variants (esplicitamente nominate, no collision con canonical) ───

def SR_local_rigidity(gaps: np.ndarray, L: int = 10) -> float:
    """**SR_local_rigidity — Δ₃(L) Spectral Rigidity** (variant).

    Different observable than canonical `SR` (spacing ratio). Measures the
    average squared deviation of the cumulative spacing function from the
    best-fit straight line in a window of size L.

    Originated from `exp_scale_selective_perturbation.py` where it was
    locally named `SR` — registered here as `SR_local_rigidity` to avoid
    collision with canonical spacing-ratio definition.

    Use when explicitly studying spectral rigidity, NOT as alias for SR.
    """
    if len(gaps) < 5:
        return 0.0
    cumulative = np.cumsum(gaps)
    if cumulative[-1] <= 1e-15:
        return 0.0
    cumulative = cumulative / cumulative[-1] * len(cumulative)
    n = np.arange(1, len(cumulative) + 1, dtype=float)
    window = int(min(L * len(gaps) / cumulative[-1], len(gaps) // 2))
    if window < 5:
        return 0.0
    residuals = []
    for start in range(0, len(cumulative) - window, max(1, window // 2)):
        end = start + window
        x = n[start:end]
        y = cumulative[start:end]
        a, b = np.polyfit(x, y, 1)
        residuals.append(np.mean((y - (a * x + b)) ** 2))
    return float(np.mean(residuals)) if residuals else 0.0


def triple_var_normalized(gaps: np.ndarray) -> float:
    """**triple_var_normalized — Variance of triples / variance of gaps** (variant).

    Originated from `exp_perturbation_dimensionality_audit.py` where it was
    locally named `triple_var` — registered here as `triple_var_normalized`
    to avoid collision with canonical raw triple variance.

    Use when explicitly studying triple-variance scaling relative to
    single-gap variance, NOT as alias for triple_var.
    """
    if len(gaps) < 3:
        return 0.0
    triples = gaps[:-2] + gaps[1:-1] + gaps[2:]
    v = float(np.var(gaps))
    if v <= 1e-15:
        return 0.0
    return float(np.var(triples) / v)


# Set varianti, importabile esplicitamente
OBSERVABLES_VARIANTS: dict[str, callable] = {
    "SR_local_rigidity": SR_local_rigidity,
    "triple_var_normalized": triple_var_normalized,
}


# ─── Public API ───────────────────────────────────────────────────────

def compute_canonical(gaps: np.ndarray) -> dict[str, float]:
    """Compute all canonical observables for a gap sequence.

    Returns dict {name: value} ready for inclusion in cycle reports.
    """
    return {name: fn(gaps) for name, fn in OBSERVABLES_CANONICAL.items()}


def report_header() -> str:
    """Suggested markdown header line for cycle reports using this registry."""
    canonical_list = ", ".join(OBSERVABLES_CANONICAL.keys())
    return (
        f"observables_registry: {OBSERVABLES_REGISTRY_VERSION}\n"
        f"observables_used: [{canonical_list}]"
    )



exec
/bin/bash -lc "sed -n '1,220p' tools/exp_metric_tensor_diagnostic.py" in /opt/MM_D-ND
 succeeded in 0ms:
#!/usr/bin/env python3
"""
METRIC_TENSOR diagnostic — long experiment
Piano 39, tensione METRIC_TENSOR (0.9)

Domanda: DOVE vive la struttura dei primi nel tensore metrico g=(p/2)^2?
- Curvatura scalare R => tautologica (z=-8.8, exp precedente)
- Rapporti DeltaGamma => z=+22.5, ma non testato direttamente

Esperimento:
1. Calcola i simboli di Christoffel Gamma^t_tt nella coordinata tau=ln(p)
2. Calcola DeltaGamma (variazione gap-to-gap della connessione)  
3. Calcola rapporti DeltaGamma_n/DeltaGamma_{n+1}
4. Confronta con Cramer surrogates e shuffled gaps
5. Misura il contenuto spettrale di DeltaGamma vs dR
6. Cerca la firma di phi nei rapporti
"""

import json
import numpy as np
from datetime import datetime
import sys

np.random.seed(42)

# ==== Generate primes via sieve ====
def sieve(limit):
    is_prime = np.ones(limit, dtype=bool)
    is_prime[:2] = False
    for i in range(2, int(limit**0.5)+1):
        if is_prime[i]:
            is_prime[i*i::i] = False
    return np.where(is_prime)[0]

print("Generating primes up to 10^7...")
primes = sieve(10_000_000)
N = len(primes)
print(f"N = {N} primes")

# ==== Coordinate ====
p = primes.astype(np.float64)
tau = np.log(p)  # de Sitter time coordinate
g = (p/2)**2     # metric tensor component

# ==== Gaps ====
gaps = np.diff(p)
log_gaps = np.diff(tau)  # gaps in tau coordinate

# ==== 1. Christoffel symbols ====
# For 1D metric g(tau), Gamma^tau_tautau = (1/2g) dg/dtau
# In discrete: dg/dtau ~ (g[n+1]-g[n])/(tau[n+1]-tau[n])
dg = np.diff(g)
dtau = np.diff(tau)
g_mid = (g[:-1] + g[1:]) / 2
Gamma = dg / (2 * g_mid * dtau)

print(f"Christoffel Gamma: mean={np.mean(Gamma):.6f}, std={np.std(Gamma):.6f}")

# ==== 2. DeltaGamma ====
DeltaGamma = np.diff(Gamma)
print(f"DeltaGamma: mean={np.mean(DeltaGamma):.6f}, std={np.std(DeltaGamma):.6f}")

# ==== 3. Rapporti DeltaGamma consecutivi ====
# Evita divisione per zero
mask = np.abs(DeltaGamma[:-1]) > 1e-20
DG_ratios = DeltaGamma[1:][mask] / DeltaGamma[:-1][mask]
# Clamp outliers per statistiche robuste
DG_ratios_clipped = np.clip(DG_ratios, -100, 100)
print(f"DeltaGamma ratios: mean={np.mean(DG_ratios_clipped):.6f}, median={np.median(DG_ratios_clipped):.6f}")

# ==== 4. Gap ratio <r> (Oganesyan-Huse) per confronto ====
r_ratios = np.minimum(gaps[:-1], gaps[1:]) / np.maximum(gaps[:-1], gaps[1:])
r_mean_prime = np.mean(r_ratios)
print(f"Gap ratio <r>: {r_mean_prime:.6f}")

# ==== 5. Curvature fluctuations dR ====
# R = 2 for de Sitter; dR = R_discrete - 2
# R_discrete from second derivative of g in tau
d2g = np.diff(g, 2)
dtau2 = dtau[:-1] * dtau[1:]  # approximate
g_center = g[1:-1]
R_discrete = -d2g / (g_center * dtau2) + (dg[:-1]/(g_center*dtau[:-1]))**2
dR = R_discrete - 2.0

print(f"dR: mean={np.mean(dR):.6e}, std={np.std(dR):.6e}")

# ==== 6. Null baselines ====
n_surr = 30
results_surr = {
    'cramer': {'DG_std': [], 'DG_ratio_mean': [], 'DG_ratio_median': [], 'r_mean': [], 'dR_std': []},
    'shuffled': {'DG_std': [], 'DG_ratio_mean': [], 'DG_ratio_median': [], 'r_mean': [], 'dR_std': []}
}

print(f"Running {n_surr} surrogates each (Cramer + shuffled)...")

for i in range(n_surr):
    # Cramer surrogate: gaps ~ Exponential(ln(p))
    cramer_gaps = np.random.exponential(np.log(p[:len(gaps)]), size=len(gaps))
    cramer_gaps = np.maximum(cramer_gaps, 2)  # min gap = 2
    cramer_p = np.cumsum(np.concatenate([[p[0]], cramer_gaps]))[:N]
    cramer_tau = np.log(np.maximum(cramer_p, 2))
    cramer_g = (cramer_p/2)**2
    
    cdg = np.diff(cramer_g)
    cdtau = np.diff(cramer_tau)
    cdtau[cdtau == 0] = 1e-15
    cg_mid = (cramer_g[:-1] + cramer_g[1:]) / 2
    cGamma = cdg / (2 * cg_mid * cdtau)
    cDG = np.diff(cGamma)
    cmask = np.abs(cDG[:-1]) > 1e-20
    if np.sum(cmask) > 100:
        cDG_r = np.clip(cDG[1:][cmask] / cDG[:-1][cmask], -100, 100)
        results_surr['cramer']['DG_ratio_mean'].append(np.mean(cDG_r))
        results_surr['cramer']['DG_ratio_median'].append(np.median(cDG_r))
    results_surr['cramer']['DG_std'].append(np.std(cDG))
    
    cr = np.minimum(cramer_gaps[:-1], cramer_gaps[1:]) / np.maximum(cramer_gaps[:-1], cramer_gaps[1:])
    results_surr['cramer']['r_mean'].append(np.mean(cr))
    
    # dR for Cramer
    cd2g = np.diff(cramer_g[:N], 2)
    cdtau2 = cdtau[:N-2] * cdtau[1:N-1] if len(cdtau) >= N-1 else cdtau[:-1]*cdtau[1:]
    min_len = min(len(cd2g), len(cdtau2))
    cg_c = cramer_g[1:min_len+1]
    cR = -cd2g[:min_len] / (cg_c * cdtau2[:min_len]) + (cdg[:min_len]/(cg_c*cdtau[:min_len]))**2
    results_surr['cramer']['dR_std'].append(np.std(cR - 2.0))
    
    # Shuffled gaps
    shuf_gaps = np.random.permutation(gaps)
    shuf_p = np.cumsum(np.concatenate([[p[0]], shuf_gaps]))[:N]
    shuf_tau = np.log(np.maximum(shuf_p, 2))
    shuf_g = (shuf_p/2)**2
    
    sdg = np.diff(shuf_g)
    sdtau = np.diff(shuf_tau)
    sdtau[sdtau == 0] = 1e-15
    sg_mid = (shuf_g[:-1] + shuf_g[1:]) / 2
    sGamma = sdg / (2 * sg_mid * sdtau)
    sDG = np.diff(sGamma)
    smask = np.abs(sDG[:-1]) > 1e-20
    if np.sum(smask) > 100:
        sDG_r = np.clip(sDG[1:][smask] / sDG[:-1][smask], -100, 100)
        results_surr['shuffled']['DG_ratio_mean'].append(np.mean(sDG_r))
        results_surr['shuffled']['DG_ratio_median'].append(np.median(sDG_r))
    results_surr['shuffled']['DG_std'].append(np.std(sDG))
    
    sr = np.minimum(shuf_gaps[:-1], shuf_gaps[1:]) / np.maximum(shuf_gaps[:-1], shuf_gaps[1:])
    results_surr['shuffled']['r_mean'].append(np.mean(sr))
    
    sd2g = np.diff(shuf_g[:N], 2)
    sdtau2 = sdtau[:N-2] * sdtau[1:N-1] if len(sdtau) >= N-1 else sdtau[:-1]*sdtau[1:]
    min_len_s = min(len(sd2g), len(sdtau2))
    sg_c = shuf_g[1:min_len_s+1]
    sR = -sd2g[:min_len_s] / (sg_c * sdtau2[:min_len_s]) + (sdg[:min_len_s]/(sg_c*sdtau[:min_len_s]))**2
    results_surr['shuffled']['dR_std'].append(np.std(sR - 2.0))

print("Surrogates done.")

# ==== 7. Z-scores ====
def zscore(val, surr_list):
    arr = np.array(surr_list)
    return (val - np.mean(arr)) / (np.std(arr) + 1e-30)

z_DG_std_cramer = zscore(np.std(DeltaGamma), results_surr['cramer']['DG_std'])
z_DG_std_shuffled = zscore(np.std(DeltaGamma), results_surr['shuffled']['DG_std'])
z_r_cramer = zscore(r_mean_prime, results_surr['cramer']['r_mean'])
z_r_shuffled = zscore(r_mean_prime, results_surr['shuffled']['r_mean'])
z_dR_cramer = zscore(np.std(dR), results_surr['cramer']['dR_std'])
z_dR_shuffled = zscore(np.std(dR), results_surr['shuffled']['dR_std'])

if results_surr['cramer']['DG_ratio_median']:
    z_DGratio_cramer = zscore(np.median(DG_ratios_clipped), results_surr['cramer']['DG_ratio_median'])
    z_DGratio_shuffled = zscore(np.median(DG_ratios_clipped), results_surr['shuffled']['DG_ratio_median'])
else:
    z_DGratio_cramer = z_DGratio_shuffled = float('nan')

print(f"\n=== Z-SCORES ===")
print(f"DeltaGamma std:  z_cramer={z_DG_std_cramer:.2f}, z_shuffled={z_DG_std_shuffled:.2f}")
print(f"DeltaGamma ratio median: z_cramer={z_DGratio_cramer:.2f}, z_shuffled={z_DGratio_shuffled:.2f}")
print(f"Gap ratio <r>:   z_cramer={z_r_cramer:.2f}, z_shuffled={z_r_shuffled:.2f}")
print(f"dR std:          z_cramer={z_dR_cramer:.2f}, z_shuffled={z_dR_shuffled:.2f}")

# ==== 8. Windowed analysis (scale dependence) ====
n_windows = 20
window_size = 20000
windows_data = []

indices = np.linspace(0, N - window_size - 3, n_windows, dtype=int)

for idx in indices:
    w_p = p[idx:idx+window_size]
    w_tau = np.log(w_p)
    w_g = (w_p/2)**2
    w_gaps = np.diff(w_p)
    
    # DeltaGamma in window
    wdg = np.diff(w_g)
    wdtau = np.diff(w_tau)
    wg_mid = (w_g[:-1] + w_g[1:])/2
    wGamma = wdg / (2*wg_mid*wdtau)
    wDG = np.diff(wGamma)
    
    # DG ratios
    wmask = np.abs(wDG[:-1]) > 1e-20
    if np.sum(wmask) > 10:
        wDG_r = np.clip(wDG[1:][wmask] / wDG[:-1][wmask], -100, 100)
        wDG_med = float(np.median(wDG_r))
    else:
        wDG_med = float('nan')
    
    # gap ratio
    wr = np.minimum(w_gaps[:-1], w_gaps[1:]) / np.maximum(w_gaps[:-1], w_gaps[1:])
    
    # dR
    wd2g = np.diff(w_g, 2)
    wdtau2 = wdtau[:-1]*wdtau[1:]
    wg_c = w_g[1:-1]
    wR = -wd2g / (wg_c * wdtau2) + (wdg[:-1]/(wg_c*wdtau[:-1]))**2
    wdR = wR - 2.0
    

exec
/bin/bash -lc "sed -n '260,520p' tools/exp_duality_gate_transfer.py" in /opt/MM_D-ND
 succeeded in 0ms:
        print(
            f"{beta:>4.2f} {stable_count:>12.3f} "
            f"{layer.get('margin_mean', 0.0):>8.3f} "
            f"{layer.get('ambiguous_fraction', 0.0):>9.3f} "
            f"{layer.get('illusory_label_fraction', 0.0):>17.3f}"
        )
    print(f"saved {out_path}")
    return output


def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument("--n-gaps", type=int, default=4096)
    parser.add_argument("--n-replicates", type=int, default=24)
    parser.add_argument("--n-beta", type=int, default=11)
    parser.add_argument("--n-baseline", type=int, default=40)
    parser.add_argument("--z-min", type=float, default=2.0)
    parser.add_argument("--seed", type=int, default=202605070803)
    parser.add_argument("--out", default="tools/data/duality_gate_transfer.json")
    args = parser.parse_args()
    run(args)


if __name__ == "__main__":
    main()

exec
/bin/bash -lc 'rg -n "det|orientation|dual" tools/exp_*.py' in /opt/MM_D-ND
 succeeded in 0ms:
tools/exp_acf_stationarity.py:13:(illusory duality, det=+1). PNT-normalization should recover the
tools/exp_acf_stationarity.py:14:all-negative pattern (dipolar duality, det=-1).
tools/exp_crossover_universality.py:20:  - Pairwise residual correlation after removing ln(p) trend
tools/exp_crossover_universality.py:192:    # Partial: residualize on ln(p)
tools/exp_crossover_universality.py:200:# === Key test: do residuals correlate? ===
tools/exp_det_drift.py:3:exp_det_drift.py — Measure det(M) of gap transfer matrix across prime scales.
tools/exp_det_drift.py:6:  Dipolar duality = det(M) ~ -1 (generative, structured).
tools/exp_det_drift.py:7:  Illusory duality = det(M) ~ +1 (dispersive, entropic).
tools/exp_det_drift.py:8:  If primes drift toward Poisson, det(M) should drift toward +1.
tools/exp_det_drift.py:14:    Compute det(M), trace(M), eigenvalues
tools/exp_det_drift.py:18:  Output: det(M) vs ln(p) — does it drift?
tools/exp_det_drift.py:46:        det_M = np.linalg.det(M)
tools/exp_det_drift.py:49:        return M, det_M, tr_M, eigvals
tools/exp_det_drift.py:54:    print("=== det(M) Drift Across Prime Scales ===\n")
tools/exp_det_drift.py:72:        M, det_M, tr_M, eigvals = fit_transfer_matrix(gaps)
tools/exp_det_drift.py:78:        det_shuffled = []
tools/exp_det_drift.py:84:                det_shuffled.append(d)
tools/exp_det_drift.py:86:        det_shuf_mean = np.mean(det_shuffled)
tools/exp_det_drift.py:87:        det_shuf_std = np.std(det_shuffled)
tools/exp_det_drift.py:88:        z_score = (det_M - det_shuf_mean) / det_shuf_std if det_shuf_std > 0 else 0
tools/exp_det_drift.py:91:        print(f"  det(M) = {det_M:.6f}")
tools/exp_det_drift.py:94:        print(f"  det(M_shuffled) = {det_shuf_mean:.6f} +/- {det_shuf_std:.6f}")
tools/exp_det_drift.py:102:            'det_M': float(det_M),
tools/exp_det_drift.py:108:            'det_shuffled_mean': float(det_shuf_mean),
tools/exp_det_drift.py:109:            'det_shuffled_std': float(det_shuf_std),
tools/exp_det_drift.py:114:    # Summary: linear fit of det(M) vs ln(p)
tools/exp_det_drift.py:116:    dets = np.array([r['det_M'] for r in results])
tools/exp_det_drift.py:117:    det_shuf = np.array([r['det_shuffled_mean'] for r in results])
tools/exp_det_drift.py:120:    coeffs = np.polyfit(ln_ps, dets, 1)
tools/exp_det_drift.py:123:    ss_res = np.sum((dets - predicted)**2)
tools/exp_det_drift.py:124:    ss_tot = np.sum((dets - np.mean(dets))**2)
tools/exp_det_drift.py:128:    print(f"det(M) = {intercept:.6f} + {slope:.6f} * ln(p)")
tools/exp_det_drift.py:130:    print(f"det range: {dets.min():.6f} to {dets.max():.6f}")
tools/exp_det_drift.py:131:    print(f"det_shuffled range: {det_shuf.min():.6f} to {det_shuf.max():.6f}")
tools/exp_det_drift.py:135:    # Does det drift toward +1?
tools/exp_det_drift.py:137:        # Extrapolate to det = +1
tools/exp_det_drift.py:140:            print(f"\nExtrapolation: det(M) -> +1 at p* ~ {p_star:.2e}")
tools/exp_det_drift.py:142:        print(f"\ndet(M) DECREASES with scale (away from +1)")
tools/exp_det_drift.py:145:            print(f"Extrapolation: det(M) -> -1 at p* ~ {p_star:.2e}")
tools/exp_det_drift.py:149:        'experiment': 'det_drift',
tools/exp_det_drift.py:157:    out_path = Path('/opt/MM_D-ND/tools/data/exp_det_drift.json')
tools/exp_duality_gate_transfer.py:3:exp_duality_gate_transfer.py
tools/exp_duality_gate_transfer.py:8:    Does the denominator-collapse gate discriminate dipolar duality from
tools/exp_duality_gate_transfer.py:9:    illusory duality, or does it become a local BOUNDARY metric when moved
tools/exp_duality_gate_transfer.py:15:  floor((n + phase) * phi). Its gaps are the symbolic det=-1 D-ND pole in the
tools/exp_duality_gate_transfer.py:228:        "experiment": "duality_gate_transfer",
tools/exp_duality_gate_transfer.py:278:    parser.add_argument("--out", default="tools/data/duality_gate_transfer.json")
tools/exp_mobius_irrationality.py:3:exp_mobius_irrationality.py — Experiment: does det=-1 force irrational fixed points?
tools/exp_mobius_irrationality.py:10:Question: does det(M)=-1 (ad-bc=-1) constrain Δ to be non-square
tools/exp_mobius_irrationality.py:11:more often than det=+1?
tools/exp_mobius_irrationality.py:32:    """Enumerate all 2x2 integer matrices with |det|=1, check discriminant."""
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:39:    examples = {'det_minus1_rational': [], 'det_minus1_irrational': [],
tools/exp_mobius_irrationality.py:40:                'det_plus1_rational': [], 'det_plus1_irrational': []}
tools/exp_mobius_irrationality.py:50:                    det = a * d - b * c
tools/exp_mobius_irrationality.py:51:                    if abs(det) != 1:
tools/exp_mobius_irrationality.py:54:                    key = 'det_minus1' if det == -1 else 'det_plus1'
tools/exp_mobius_irrationality.py:82:    for key in ['det_minus1', 'det_plus1']:
tools/exp_mobius_irrationality.py:88:        label = 'det = -1' if 'minus' in key else 'det = +1'
tools/exp_mobius_irrationality.py:101:                    print(f'    M=[{a},{b};{c},{d}] det={a*d-b*c} Δ={disc} √Δ={math.sqrt(abs(disc)):.4f}')
tools/exp_mobius_irrationality.py:105:    r1 = results['det_minus1']
tools/exp_mobius_irrationality.py:106:    r2 = results['det_plus1']
tools/exp_mobius_irrationality.py:113:        print(f'det=-1 irrational rate: {irr1:.3f}')
tools/exp_mobius_irrationality.py:114:        print(f'det=+1 irrational rate: {irr2:.3f}')
tools/exp_mobius_irrationality.py:115:        print(f'Ratio: {irr1/irr2:.3f}' if irr2 > 0 else 'det=+1 has no irrationals')
tools/exp_mobius_irrationality.py:118:            print('det=-1 produces MORE irrationals than det=+1')
tools/exp_mobius_irrationality.py:120:            print('det=-1 produces FEWER irrationals than det=+1')
tools/exp_modular_memory_spectrum.py:210:    # 1. Peak detection: where is ordering strongest?
tools/exp_beta_crossover.py:297:            print(f"  The gap autocorrelation is NOT determined by <r> alone.")
tools/exp_bridge_order_denominator_gate.py:10:- zeta trace-bridge nonlinear residuals
tools/exp_bridge_order_denominator_gate.py:122:def zeta_trace_residual(n_values: int, step: int = 5) -> np.ndarray:
tools/exp_bridge_order_denominator_gate.py:124:    residuals = []
tools/exp_bridge_order_denominator_gate.py:130:        residuals.append(traj[step] - linear)
tools/exp_bridge_order_denominator_gate.py:131:    return positive_bridge_values(np.array(residuals[:n_values], dtype=float))
tools/exp_bridge_order_denominator_gate.py:146:        "zeta_trace_residual_step5_abs": zeta_trace_residual(args.zeta_values, step=5),
tools/exp_coherence_length.py:11:detectable.
tools/exp_acf_z6z_mechanism.py:123:    # Also check: ACF of normalized gap residues (g/ln(p) mod 1 residual?)
tools/exp_acf_z6z_mechanism.py:256:    # DIAGNOSTIC: What determines the crossover?
tools/exp_acf_z6z_mechanism.py:295:    trend_determines = crit_strength is not None and 0.5 < crit_strength < 1.5
tools/exp_acf_z6z_mechanism.py:297:    if trend_determines and not z6z_contributes:
tools/exp_acf_z6z_mechanism.py:298:        verdict_text = "TREND_ONLY: The crossover lag is determined by PNT trend strength, not Z/6Z."
tools/exp_acf_z6z_mechanism.py:300:    elif z6z_contributes and not trend_determines:
tools/exp_acf_z6z_mechanism.py:301:        verdict_text = "Z6Z_MECHANISM: The Z/6Z arithmetic structure determines the crossover."
tools/exp_acf_z6z_mechanism.py:303:    elif z6z_contributes and trend_determines:
tools/exp_acf_z6z_mechanism.py:307:        verdict_text = "NEITHER: Crossover is determined by structural anti-correlation decay, not Z/6Z or trend alone."
tools/exp_crossover_phase_test.py:298:        print("           The phase transition discriminates ordering CLASSES, not individual sequences")
tools/exp_desitter_unification.py:234:residual_std = np.std(r_arr - r_predicted)
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_two_channel_decomposition.py:17:  - Coherence length (minimum window where ordering is detectable)
tools/exp_two_channel_decomposition.py:122:    Find minimum window size where channel ordering is detectable.
tools/exp_two_channel_decomposition.py:395:    # If channels are independent and gaps = mean(transition) + magnitude_residual,
tools/exp_two_channel_decomposition.py:413:    print(f"  Var(magnitude residual) = {var_mag:.2f} ({100*var_mag/var_full:.1f}%)")
tools/exp_logistic_counter_scope_gate.py:35:    "recurrence_determinism",
tools/exp_logistic_counter_scope_gate.py:179:    diag_mean, determinism = recurrence_diagonal_stats(values, max_points=recurrence_max_points)
tools/exp_logistic_counter_scope_gate.py:184:        "recurrence_determinism": determinism,
tools/exp_dR_brody_connection.py:255:# Cramer dR_acf1 details
tools/exp_dR_brody_connection.py:272:# Residualize both on ln(p)
tools/exp_markov3_observable_hunt.py:6:  "The Markov-3 residual (z=6203) doesn't live in the (SR, L1) plane.
tools/exp_psd_prime_gaps.py:96:    # 1. Residual between measured and theoretical
tools/exp_psd_prime_gaps.py:97:    residual = psd_prime[valid] - psd_theory[valid]
tools/exp_psd_prime_gaps.py:98:    rel_residual = residual / psd_prime[valid]
tools/exp_psd_prime_gaps.py:99:    mean_rel_residual = np.mean(np.abs(rel_residual))
tools/exp_psd_prime_gaps.py:146:        "mean_abs_rel_residual": float(mean_rel_residual),
tools/exp_psd_prime_gaps.py:159:    print(f"Mean |relative residual| (measured vs theory): {mean_rel_residual:.3f}")
tools/exp_markov_k_direction.py:6:  "The 3-deg residual is Markov-2+ memory. Markov-3 has z=6203.
tools/exp_markov_k_direction.py:12:direction. The "3 deg residual" of the previous experiment was inflated by
tools/exp_markov_k_direction.py:196:            'residual_deg': float(delta), 'z': float(z),
tools/exp_markov_k_direction.py:199:              f"ratio={np.mean(ratios):.3f}, residual={delta:+.1f} deg (z={z:.1f})")
tools/exp_markov_k_direction.py:230:                f'M{k_test}_std': float(s), 'residual': float(dt), 'z': float(zs)
tools/exp_two_channel_universality.py:293:            'individual': [{'label': r['label'],
tools/exp_perturbation_dimensionality_audit.py:99:    residuals = []
tools/exp_perturbation_dimensionality_audit.py:105:        residuals.append(np.mean((seg_c - fitted) ** 2))
tools/exp_perturbation_dimensionality_audit.py:106:    return float(np.mean(residuals)) if residuals else 0.0
tools/exp_magnitude_psd_from_acf.py:64:    mag_residual = gaps - trans_component
tools/exp_magnitude_psd_from_acf.py:65:    return mag_residual, gaps
tools/exp_magnitude_psd_from_acf.py:136:    f_welch, psd_welch = welch(mag, fs=1.0, nperseg=args.nperseg, detrend='constant')
tools/exp_magnitude_psd_from_acf.py:211:        f_s, psd_s = welch(mag_shuf, fs=1.0, nperseg=args.nperseg, detrend='constant')
tools/exp_magnitude_psd_from_acf.py:249:        f_w, psd_w = welch(mag_w, fs=1.0, nperseg=min(args.nperseg, chunk // 2), detrend='constant')
tools/exp_brody_flow.py:176:        residuals = np.array(betas) - np.polyval(coeffs, ln_ps)
tools/exp_brody_flow.py:177:        results["beta_vs_lnp_r2"] = float(1 - np.var(residuals) / np.var(betas))
tools/exp_ricci_primes.py:91:residuals = means - np.polyval(coeffs, lnps)
tools/exp_ricci_primes.py:92:ss_res = np.sum(residuals**2)
tools/exp_mod3_vs_residual_ordering.py:3:Mod-3 vs Residual Ordering in Prime Gaps
tools/exp_mod3_vs_residual_ordering.py:7:there is residual ordering beyond what mod-3 predicts.
tools/exp_mod3_vs_residual_ordering.py:16:     If real primes show more rigidity, there's residual ordering.
tools/exp_mod3_vs_residual_ordering.py:21:  python exp_mod3_vs_residual_ordering.py [--n-primes N] [--n-shuffles N]
tools/exp_mod3_vs_residual_ordering.py:247:          f"{'Cramer':>8} | {'Ord% real':>9} | {'Ord% mod3':>9} | {'Residual%':>9} | {'z_res':>6}")
tools/exp_mod3_vs_residual_ordering.py:261:        # Residual: ordering in real beyond what mod-3 explains
tools/exp_mod3_vs_residual_ordering.py:262:        residual = ord_real - ord_mod3
tools/exp_mod3_vs_residual_ordering.py:264:        # z-score of residual: how significant is the real-vs-mod3 difference?
tools/exp_mod3_vs_residual_ordering.py:269:              f"{cramer:8.4f} | {ord_real:8.1f}% | {ord_mod3:8.1f}% | {residual:8.1f}% | {z_res:6.1f}")
tools/exp_mod3_vs_residual_ordering.py:282:            'residual_pct': round(residual, 2),
tools/exp_mod3_vs_residual_ordering.py:283:            'z_residual': round(z_res, 2)
tools/exp_mod3_vs_residual_ordering.py:291:    # Find crossover scale where residual dominates mod-3
tools/exp_mod3_vs_residual_ordering.py:294:    res_at_L50 = results[5]['residual_pct'] if len(results) > 5 else 0
tools/exp_mod3_vs_residual_ordering.py:298:          f"residual = {res_at_L50:.1f}%")
tools/exp_mod3_vs_residual_ordering.py:321:    out_path = os.path.join(os.path.dirname(__file__), 'data', 'mod3_vs_residual_ordering.json')
tools/exp_psd_amplitude_scaling.py:39:                 noverlap=nperseg//2, detrend='constant')
tools/exp_two_channel_psd.py:50:      gap_i = trans_mean(type_i) + magnitude_residual_i
tools/exp_two_channel_psd.py:53:    The magnitude residual encodes within-class ordering.
tools/exp_two_channel_psd.py:74:    # Magnitude residual (gap minus its transition mean)
tools/exp_two_channel_psd.py:75:    mag_residual = gaps - trans_component
tools/exp_two_channel_psd.py:80:    return gaps_centered, trans_centered, mag_residual, p
tools/exp_two_channel_psd.py:86:                   noverlap=nperseg//2, detrend='constant')
tools/exp_two_channel_psd.py:127:    print(f"  Var(mag_residual) = {v_mag:.4f} ({100*v_mag/v_gap:.2f}%)")
tools/exp_dipolar_crossover.py:5:Question: As ordering is gradually destroyed (GUE → shuffled), does the dipolar
tools/exp_dipolar_crossover.py:194:    # Phase transition detection: find where d(mag)/d(alpha) is maximal
tools/exp_scale_selective_perturbation.py:80:    residuals = []
tools/exp_scale_selective_perturbation.py:86:        residuals.append(np.mean((seg_c - fitted)**2))
tools/exp_scale_selective_perturbation.py:87:    return float(np.mean(residuals))
tools/exp_geodesic_deviation_primes.py:167:    finding += " Prime-specific autocorrelation in dR detected vs both baselines."
tools/exp_spectral_landscape.py:79:    """GSE (beta=4): eigenvalue spacings of quaternion self-dual matrix."""

exec
/bin/bash -lc 'ls tools/data/reports | tail -20' in /opt/MM_D-ND
 succeeded in 0ms:
report_20260402_0756.md
report_20260403_0330.md
report_20260404_0330.md
report_20260404_1852.md
report_20260405_0330.md
report_20260405_0715.md
tension_projection_screening_2026-04-21.json
trace_map_20260305_0843.json
trace_map_20260305_0844.json
trajectory_apply_20260506_1931.json
trajectory_apply_20260506_1941.json
trajectory_apply_20260506_1955.json
trajectory_apply_20260507_0330.json
trajectory_apply_20260507_0803.json
trajectory_apply_20260507_0901.json
trajectory_apply_20260507_0923.json
trajectory_apply_20260507_0942.json
trajectory_apply_20260507_1006.json
trajectory_apply_20260507_1042.json
watchdog.log

codex
C'è già uno strumento riusabile per il trasferimento del gate sulla dualità; lo eseguo invece di duplicare codice. Il controllo è original-vs-shuffle su osservabili canonici, così il claim non dipende dalla sola tassonomia interna.
exec
/bin/bash -lc 'python tools/exp_duality_gate_transfer.py --n-gaps 4096 --n-replicates 24 --n-beta 11 --n-baseline 40 --seed 202605072042 --out tools/data/duality_gate_transfer_20260507_2042.json' in /opt/MM_D-ND
 succeeded in 1439ms:
observables_registry=1.0.0-2026-05-06
observables_used=['SR', 'SR2', 'L1', 'L2', 'triple_var']
endpoint_stable_observables=[]
endpoint_distance_all=3.454 endpoint_distance_gated=0.000
beta stable_count margin ambiguous illusory_fraction
0.00        3.000    0.967     0.000             0.000
0.10        3.000    0.497     0.000             0.000
0.20        3.000    0.191     0.292             0.000
0.30        3.000    0.058     1.000             0.542
0.40        3.000    0.196     0.292             1.000
0.50        3.083    0.287     0.208             1.000
0.60        3.083    0.341     0.083             1.000
0.70        2.958    0.363     0.208             1.000
0.80        0.750    0.416     0.167             1.000
0.90        0.250    0.423     0.125             1.000
1.00        0.292    0.519     0.083             1.000
saved tools/data/duality_gate_transfer_20260507_2042.json

codex
Il risultato chiave è netto: gli endpoint sono separabili nello spazio di tutti gli osservabili (`distance=3.454`), ma nessun osservabile è stabile su entrambi gli endpoint dopo gate. Ora leggo il JSON per riportare le frequenze e scrivo report scoped al perimetro, senza chiamare “assenza” ciò che è solo collasso del denominator endpoint-stable.
exec
/bin/bash -lc "jq '{observables_registry, observables_used, endpoint_stable: .gate.endpoint_stable_observables, endpoint_distance_all: .classification_all_observables.endpoint_distance, ambiguous_beta: .classification_all_observables.ambiguous_beta, layers: .classification_all_observables.layers, stable_layers: .gate.layers}' tools/data/duality_gate_transfer_20260507_2042.json" in /opt/MM_D-ND
 succeeded in 0ms:
{
  "observables_registry": "1.0.0-2026-05-06",
  "observables_used": [
    "SR",
    "SR2",
    "L1",
    "L2",
    "triple_var"
  ],
  "endpoint_stable": [],
  "endpoint_distance_all": 3.4536414150877945,
  "ambiguous_beta": [
    0.30000000000000004
  ],
  "layers": {
    "0.000": {
      "coordinate_mean": -0.9670399067661876,
      "coordinate_std": 0.015462988872383416,
      "margin_mean": 0.9670399067661876,
      "ambiguous_fraction": 0.0,
      "illusory_label_fraction": 0.0
    },
    "0.100": {
      "coordinate_mean": -0.49672081424120834,
      "coordinate_std": 0.11790724740634512,
      "margin_mean": 0.49672081424120834,
      "ambiguous_fraction": 0.0,
      "illusory_label_fraction": 0.0
    },
    "0.200": {
      "coordinate_mean": -0.19102246144374124,
      "coordinate_std": 0.0865728870654928,
      "margin_mean": 0.19102246144374124,
      "ambiguous_fraction": 0.2916666666666667,
      "illusory_label_fraction": 0.0
    },
    "0.300": {
      "coordinate_mean": 0.020191230637140498,
      "coordinate_std": 0.06075049433753693,
      "margin_mean": 0.05816953555975316,
      "ambiguous_fraction": 1.0,
      "illusory_label_fraction": 0.5416666666666666
    },
    "0.400": {
      "coordinate_mean": 0.19562568644046316,
      "coordinate_std": 0.08540133225991577,
      "margin_mean": 0.19562568644046316,
      "ambiguous_fraction": 0.2916666666666667,
      "illusory_label_fraction": 1.0
    },
    "0.500": {
      "coordinate_mean": 0.28706993630135297,
      "coordinate_std": 0.14750609456336097,
      "margin_mean": 0.28706993630135297,
      "ambiguous_fraction": 0.20833333333333334,
      "illusory_label_fraction": 1.0
    },
    "0.600": {
      "coordinate_mean": 0.3408818662298101,
      "coordinate_std": 0.16802555244950673,
      "margin_mean": 0.3408818662298101,
      "ambiguous_fraction": 0.08333333333333333,
      "illusory_label_fraction": 1.0
    },
    "0.700": {
      "coordinate_mean": 0.3626175065084243,
      "coordinate_std": 0.2330842499596874,
      "margin_mean": 0.3626175065084243,
      "ambiguous_fraction": 0.20833333333333334,
      "illusory_label_fraction": 1.0
    },
    "0.800": {
      "coordinate_mean": 0.4159895217823631,
      "coordinate_std": 0.2318820129085184,
      "margin_mean": 0.4159895217823631,
      "ambiguous_fraction": 0.16666666666666666,
      "illusory_label_fraction": 1.0
    },
    "0.900": {
      "coordinate_mean": 0.42260703840977903,
      "coordinate_std": 0.25213507212838504,
      "margin_mean": 0.42260703840977903,
      "ambiguous_fraction": 0.125,
      "illusory_label_fraction": 1.0
    },
    "1.000": {
      "coordinate_mean": 0.5189605264570251,
      "coordinate_std": 0.26429302585175785,
      "margin_mean": 0.5189605264570251,
      "ambiguous_fraction": 0.08333333333333333,
      "illusory_label_fraction": 1.0
    }
  },
  "stable_layers": {
    "0.000": {
      "stable_count_mean": 3.0,
      "stable_count_std": 0.0,
      "stable_frequency": {
        "SR": 1.0,
        "SR2": 0.0,
        "L1": 1.0,
        "L2": 0.0,
        "triple_var": 1.0
      },
      "z_mean": {
        "SR": -41.306459029608554,
        "SR2": -0.005725417674171067,
        "L1": -41.31893519195108,
        "L2": -0.007709920554556947,
        "triple_var": -36.602697110130926
      }
    },
    "0.100": {
      "stable_count_mean": 3.0,
      "stable_count_std": 0.0,
      "stable_frequency": {
        "SR": 1.0,
        "SR2": 0.0,
        "L1": 1.0,
        "L2": 0.0,
        "triple_var": 1.0
      },
      "z_mean": {
        "SR": -32.49632066839627,
        "SR2": 0.09387299379986024,
        "L1": -32.49631493219554,
        "L2": 0.0940383552319643,
        "triple_var": -29.421655251727035
      }
    },
    "0.200": {
      "stable_count_mean": 3.0,
      "stable_count_std": 0.0,
      "stable_frequency": {
        "SR": 1.0,
        "SR2": 0.0,
        "L1": 1.0,
        "L2": 0.0,
        "triple_var": 1.0
      },
      "z_mean": {
        "SR": -25.832374571898907,
        "SR2": 0.02058038791947663,
        "L1": -25.828326689462028,
        "L2": 0.01897198348541647,
        "triple_var": -23.18758235458345
      }
    },
    "0.300": {
      "stable_count_mean": 3.0,
      "stable_count_std": 0.0,
      "stable_frequency": {
        "SR": 1.0,
        "SR2": 0.0,
        "L1": 1.0,
        "L2": 0.0,
        "triple_var": 1.0
      },
      "z_mean": {
        "SR": -20.74192516169457,
        "SR2": 0.13177959128820996,
        "L1": -20.742866644623675,
        "L2": 0.1312271118919439,
        "triple_var": -18.482253913541054
      }
    },
    "0.400": {
      "stable_count_mean": 3.0,
      "stable_count_std": 0.0,
      "stable_frequency": {
        "SR": 1.0,
        "SR2": 0.0,
        "L1": 1.0,
        "L2": 0.0,
        "triple_var": 1.0
      },
      "z_mean": {
        "SR": -15.002721052758025,
        "SR2": -0.029804246861490708,
        "L1": -15.00712084757768,
        "L2": -0.030384280055281754,
        "triple_var": -13.340885607866085
      }
    },
    "0.500": {
      "stable_count_mean": 3.0833333333333335,
      "stable_count_std": 0.408248290463863,
      "stable_frequency": {
        "SR": 1.0,
        "SR2": 0.041666666666666664,
        "L1": 1.0,
        "L2": 0.041666666666666664,
        "triple_var": 1.0
      },
      "z_mean": {
        "SR": -9.82801339513891,
        "SR2": -0.28799825067611273,
        "L1": -9.828728832454074,
        "L2": -0.28930918854394866,
        "triple_var": -8.890677317828041
      }
    },
    "0.600": {
      "stable_count_mean": 3.0833333333333335,
      "stable_count_std": 0.408248290463863,
      "stable_frequency": {
        "SR": 1.0,
        "SR2": 0.041666666666666664,
        "L1": 1.0,
        "L2": 0.041666666666666664,
        "triple_var": 1.0
      },
      "z_mean": {
        "SR": -6.32689541083932,
        "SR2": 0.20191883943077396,
        "L1": -6.326987918387,
        "L2": 0.2017590128921487,
        "triple_var": -5.531441377850574
      }
    },
    "0.700": {
      "stable_count_mean": 2.9583333333333335,
      "stable_count_std": 0.9078961186825509,
      "stable_frequency": {
        "SR": 0.9583333333333334,
        "SR2": 0.08333333333333333,
        "L1": 0.9583333333333334,
        "L2": 0.08333333333333333,
        "triple_var": 0.875
      },
      "z_mean": {
        "SR": -4.019487024952454,
        "SR2": -0.015563276447881969,
        "L1": -4.0201199960868985,
        "L2": -0.016268455244154083,
        "triple_var": -3.4575968388466207
      }
    },
    "0.800": {
      "stable_count_mean": 0.75,
      "stable_count_std": 1.224744871391589,
      "stable_frequency": {
        "SR": 0.20833333333333334,
        "SR2": 0.08333333333333333,
        "L1": 0.20833333333333334,
        "L2": 0.08333333333333333,
        "triple_var": 0.16666666666666666
      },
      "z_mean": {
        "SR": -1.3029158521680355,
        "SR2": 0.1285741538734337,
        "L1": -1.304046683311245,
        "L2": 0.12737102503392259,
        "triple_var": -1.1072323052998516
      }
    },
    "0.900": {
      "stable_count_mean": 0.25,
      "stable_count_std": 0.7372097807744856,
      "stable_frequency": {
        "SR": 0.08333333333333333,
        "SR2": 0.041666666666666664,
        "L1": 0.041666666666666664,
        "L2": 0.041666666666666664,
        "triple_var": 0.041666666666666664
      },
      "z_mean": {
        "SR": -0.409583988141742,
        "SR2": 0.05365624268491759,
        "L1": -0.4096875106318592,
        "L2": 0.05264484438951975,
        "triple_var": -0.35974636463491166
      }
    },
    "1.000": {
      "stable_count_mean": 0.2916666666666667,
      "stable_count_std": 0.8064504441319255,
      "stable_frequency": {
        "SR": 0.041666666666666664,
        "SR2": 0.08333333333333333,
        "L1": 0.041666666666666664,
        "L2": 0.08333333333333333,
        "triple_var": 0.041666666666666664
      },
      "z_mean": {
        "SR": -0.2599028514354398,
        "SR2": 0.23899920466646588,
        "L1": -0.2586094385385576,
        "L2": 0.23999705469082933,
        "triple_var": -0.11639247673829618
      }
    }
  }
}

exec
/bin/bash -lc "find tools/data/reports -maxdepth 1 -type f -name 'agent_20260507_*.md' | sort | tail -12" in /opt/MM_D-ND
 succeeded in 0ms:
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/agent_20260507_1458.md
tools/data/reports/agent_20260507_1751.md
tools/data/reports/agent_20260507_1804.md
tools/data/reports/agent_20260507_1938.md
tools/data/reports/agent_20260507_1957.md

exec
/bin/bash -lc 'rg -n "DUALITA_DIPOLARE|duality_gate_transfer|Agent Report" tools/data/reports tools/data/seme.json' in /opt/MM_D-ND
 succeeded in 0ms:
tools/data/seme.json:66:      "id": "DUALITA_DIPOLARE_VS_ILLUSORIA",
tools/data/seme.json:205:    "Tensioni risolte: {'TENSIONE_ENTITA', 'ORDER_DENOMINATOR_GATE', 'G_BLANK_TO_SOURCE_FACE_GATE', 'META_ASSERTION_GATE', 'TRASCENDENZA_LIMITE', 'G_UNDERLAY_HINGE_GATE', 'PIANO_PRIMARIO_DUE_ASSIOMI', 'DUALITA_DIPOLARE_VS_ILLUSORIA', 'METRIC_TENSOR', 'G_TRIADIC_DEPOSIT_GATE', 'G_POTENZIALE_NULLA', 'OBSERVABLE_REGISTRY', 'PERTURBATION_DENOMINATOR_GATE', 'G_BLANK_SHELL_POLARITY_GATE', 'BOUNDARY_LAYER_GATE'}"
tools/data/reports/agent_20260504_1219.md:1:# Agent Report — Markov Layers Pass the First Recovery Gate, but Not All Observables Pass
tools/data/reports/agent_20260507_1458.md:1:# Agent Report — META Assertion Gate
tools/data/reports/agent_20260506_0625.md:1:# Agent Report — Perturbation Dimensionality Is Not Yet a Stable GUE Invariant
tools/data/reports/agent_20260419_0755.md:1:# Agent Report — The Two-Channel Decomposition Is Half Algebraic, Half Number-Theoretic
tools/data/reports/agent_20260412_0330.md:1:# Agent Report — Transfer Matrix det(M) Drifts Toward Zero: Dipolar Structure Is Marginal, Not Dynamic
tools/data/reports/agent_20260412_0330.md:4:**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
tools/data/reports/agent_20260412_0330.md:47:- **CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: det(M) does not cleanly separate dipolar (det=-1) from illusory (det=+1). The real det is -0.38, not -1. The sign comes from gap marginals, not dynamics.
tools/data/reports/agent_20260507_0923.md:1:# Agent Report — Semi-Real Order Denominator Gate
tools/data/reports/evolution_20260417_0803.md:5:L'agente ha scelto una tensione ad alta priorità (ACF_1K_LAW + DUALITA_DIPOLARE_VS_ILLUSORIA, entrambe 0.9) e ha formulato la domanda giusta: la positività dell'ACF a lag>6 è strutturale o artefatto di non-stazionarietà? La traiettoria era netta — normalizzazione PNT, confronto raw/normalizzato, decomposizione in componente dipolare e illusoria. L'insight (il crossover a lag 6 come confine dipolare-illusorio) è emerso durante il percorso, non era pre-programmato. Buon modus.
tools/data/reports/agent_20260410_0330.md:1:# Agent Report — The 1/k Amplitude Decays: A(p) Predicts Poisson at p* ~ 10^{12.6}
tools/data/reports/agent_20260430_0330.md:1:# Agent Report — Three Regimes of Modular Memory: Algebraic (mod-3), Near-Uniform (mod-5), Statistical (mod-q)
tools/data/reports/agent_20260425_0330.md:1:# Agent Report — Markov Memory Is Channel-Specific: 140x Algebraic vs Statistical in Primes, Ordering-GUE Has No Algebraic Channel
tools/data/reports/agent_20260507_1938.md:1:# Agent Report — Triadic Deposit Gate
tools/data/reports/agent_20260507_1006.md:1:# Agent Report — Logistic Counter-Scope Gate
tools/data/reports/agent_20260507_0942.md:1:# Agent Report — Bridge Order Denominator Gate
tools/data/reports/agent_20260507_0803.md:1:# Agent Report - Denominator Gate Transfers, Boundary Coordinate Does Not
tools/data/reports/agent_20260507_0803.md:5:**Tension explored**: META + DUALITA_DIPOLARE_VS_ILLUSORIA  
tools/data/reports/agent_20260507_0803.md:22:Tool created: `tools/exp_duality_gate_transfer.py`
tools/data/reports/agent_20260507_0803.md:152:- Script: `tools/exp_duality_gate_transfer.py`
tools/data/reports/agent_20260507_0803.md:153:- Main data: `tools/data/duality_gate_transfer_20260507_0803.json`
tools/data/reports/agent_20260507_0803.md:154:- Seed check: `tools/data/duality_gate_transfer_20260507_0803_seedcheck.json`
tools/data/reports/agent_20260507_0901.md:1:# Agent Report — Denominator Gate Transfer Matrix
tools/data/reports/agent_20260426_0330.md:1:# Agent Report — Spectral Rigidity Reveals Scale-Dependent Two-Channel Structure in Primes
tools/data/reports/agent_20260505_1022.md:1:# Agent Report — Selective Perturbations Break the Single-Boundary Framing
tools/data/reports/mapping_validation_2026-04-21.json:255:    "tension": "DUALITA_DIPOLARE_VS_ILLUSORIA",
tools/data/reports/agent_20260507_1804.md:1:# Agent Report — Blank To Source Hinge
tools/data/reports/agent_20260422_0330.md:1:# Agent Report — The Magnitude PSD Is Pair-Dominated: K*=2 Lags Capture 99% of the Spectral Slope
tools/data/reports/agent_20260505_0330.md:1:# Agent Report - Observable Rank Audit: Many Probes, One Boundary Coordinate
tools/data/reports/agent_20260503_0330.md:1:# Agent Report — Markov Memory Has Two Visible Layers: Pairs Shape the Angle, Triples Shape the Depth
tools/data/reports/agent_20260504_0901.md:1:# Agent Report — The Two Markov Layers Are Coupled at the Boundary: One Phase Transition, Two Projections
tools/data/reports/agent_20260405_0825.md:1:# Agent Report — 2026-04-05 08:25
tools/data/reports/agent_20260406_0714.md:1:# Agent Report — Crossover Universality: One Boundary or Many?
tools/data/reports/agent_20260407_0637.md:1:# Agent Report — Two Mechanisms, Not Three: The Prime Decorrelation Is Not a Hierarchy
tools/data/reports/agent_20260408_0330.md:1:# Agent Report — The 1/k Law: Prime Gaps Have Long-Range Anti-Correlation
tools/data/reports/agent_20260406_1030.md:1:# Agent Report — The Spectral Landscape: Primes Are Not a Mixture
tools/data/reports/agent_20260428_0330.md:1:# Agent Report — The 140x Algebraic Memory Is a Mod-3 Prohibition: Zero Self-Transitions from the Shared Middle Prime
tools/data/reports/agent_20260428_0330.md:5:**Tension explored**: BOUNDARY (0.8) + DUALITA_DIPOLARE_VS_ILLUSORIA (0.9) + C1
tools/data/reports/agent_20260428_0330.md:83:**NEW + CONSTRAINT on BOUNDARY + DUALITA_DIPOLARE_VS_ILLUSORIA + C1 + F2**
tools/data/reports/agent_20260428_0330.md:86:- **DUALITA_DIPOLARE_VS_ILLUSORIA**: The mod-3 prohibition is dipolar (det=-1): two states {1,2} that cannot self-transition, forced to oscillate through 0. Cramer has no such prohibition — its transitions are symmetric, formless (det=+1). The duality IS the prohibition: the walk must invert before returning.
tools/data/reports/agent_20260430_1919.md:1:# Agent Report — The Dipolar Vector Is Locked: Prime Ordering Has One Degree of Freedom, Not Two
tools/data/reports/agent_20260429_1013.md:1:# Agent Report — Brody Flow: Primes Drift Toward Poisson at 82% Magnitude, 18% Ordering — The Boundary Is a Trajectory, Not a Fixed Point
tools/data/reports/agent_20260506_1941.md:1:# Agent Report — Perturbation Rank Needs Denominator Gating
tools/data/reports/agent_20260422_1616.md:1:# Agent Report — 3/8 Properties Are Tautologies: The Shuffle Audit Separates Algebra from Order
tools/data/reports/agent_20260506_0330.md:1:# Agent Report — Scale-Selective Perturbations Reveal a Second Axis in GUE, Not in Primes
tools/data/reports/agent_20260502_0330.md:1:# Agent Report — The Dipolar Phase Transition Is Nearly Universal; The Direction Is Diagnostic
tools/data/reports/agent_20260419_0330.md:1:# Agent Report — The Two Anti-Correlation Channels: Residue Dies First, Magnitude Persists
tools/data/reports/agent_20260507_1042.md:1:# Agent Report — Logistic Surrogate Contract Gate
tools/data/reports/agent_20260411_0330.md:1:# Agent Report — The 1/k Exponent Drifts: Anti-Correlation Changes Type, Not Just Amplitude
tools/data/reports/agent_20260411_0330.md:4:**Tension explored**: ACF_AMPLITUDE_SCALING (0.85) + DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
tools/data/reports/agent_20260411_0330.md:79:4. **Connection to operator's DUALITA_DIPOLARE_VS_ILLUSORIA.** The steep anti-correlation (alpha>1) is dipolar: each gap "knows" its neighbors strongly, decoupled from distant ones. The shallow anti-correlation (alpha<1) is diffuse: weak coupling spread everywhere, tending to the illusory (Poisson, det=+1). The transition from dipolar to diffuse IS the Poisson crossover, seen in a new observable.
tools/data/reports/agent_20260501_0725.md:1:# Agent Report — The Dipolar Angle Is Pair-Complete: Markov-3 Memory Is Orthogonal to (SR, L1)
tools/data/reports/agent_20260430_1946.md:1:# Agent Report — The Dipolar Angle Reference Frame: Primes Are Not Weak GUE
tools/data/reports/agent_20260427_0330.md:1:# Agent Report — Brody Calibration Proves Two-Channel Structure Is Real, Quantifies 7.8% Artifact Floor
tools/data/reports/agent_20260427_0330.md:78:**NEW + CONSTRAINT on META + BOUNDARY + C1 + DUALITA_DIPOLARE_VS_ILLUSORIA**
tools/data/reports/agent_20260427_0330.md:83:- **DUALITA_DIPOLARE_VS_ILLUSORIA**: The sign of the ordering channel IS the discriminator. Ordering that adds rigidity (primes) = dipolar duality (det=-1, generative). Ordering that adds bunching (logistic, coupled_osc) = dispersive (det=+1, entropic). The Brody curve is the zero line between them.
tools/data/reports/agent_20260501_0330.md:1:# Agent Report — Markov Decomposition of the Dipolar Angle: Pair Statistics Explain 80% but Not All
tools/data/reports/agent_test_field.md:1:# Agent Report — Three Roads to Poisson: Universal Crossover Scale
tools/data/reports/agent_20260507_1419.md:1:# Agent Report — Logistic Cyclic Block Entropy Gate
tools/data/reports/agent_20260409_0330.md:1:# Agent Report — Prime Gaps Are Weakly Blue Noise: PSD Reveals Two-Component Structure
tools/data/reports/agent_20260415_0330.md:1:# Agent Report — The Dipole Is Distributed: Conditional Gap Ratio Shows Ordering, Not Local Structure
tools/data/reports/agent_20260415_0330.md:5:**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9) + GAP_ANTICORR (0.75) + POISSON_CONVERGENCE (0.9)
tools/data/reports/agent_20260415_0330.md:69:**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA** — The dipolar duality in prime gaps is distributed (global sequence order), not local (adjacent conditioning). This constrains any model that places the det=-1 structure in pairwise interactions. The dipole lives in the *sequence as a whole* — destroying the order (shuffle = det=+1 operation) eliminates it, but conditioning within the ordered sequence barely reveals it. The illusory duality (shuffle) doesn't just lose amplitude — it loses a qualitatively different, collective structure.
tools/data/reports/agent_20260420_0330.md:1:# Agent Report — The PSD Decomposes: Residue Is 2x Bluer, Magnitude Shapes the Spectrum
tools/data/reports/agent_20260507_1957.md:1:# Agent Report — Blank Shell Polarity Gate
tools/data/reports/agent_20260501_0931.md:1:# Agent Report — The GUE-Poisson Crossover Has a Phase Transition: Direction Locks, Magnitude Decays, Then Flips
tools/data/reports/agent_20260429_1041.md:1:# Agent Report — Mod-3 Ordering Is Algebraic and Scale-Invariant: A Separate Channel from Brody Beta
tools/data/reports/agent_20260416_0330.md:1:# Agent Report — The Dipolar Ordering Is Intensive: Coherence Length L*=35, Constant Delta_r Across All Scales
tools/data/reports/agent_20260416_0330.md:5:**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9) + GAP_ANTICORR (0.75) + POISSON_CONVERGENCE (0.9)
tools/data/reports/agent_20260507_0330.md:1:# Agent Report — The GUE-Poisson Boundary Is a Denominator Collapse Layer
tools/data/reports/tension_projection_screening_2026-04-21.json:41:        "id": "DUALITA_DIPOLARE_VS_ILLUSORIA",
tools/data/reports/agent_20260507_1751.md:1:# Agent Report — TQGE Underlay Gate
tools/data/reports/agent_20260413_0330.md:1:# Agent Report — PSD Dip Tracks ACF Amplitude: Wiener-Khinchin Cross-Validation Confirms Unified Decorrelation
tools/data/reports/agent_20260418_0330.md:1:# Agent Report — The Lag-6 Crossover Is Not Z/6Z: It's the Ratio of Anti-Correlation to Trend
tools/data/reports/agent_20260417_0803.md:1:# Agent Report — The Dipolar-Illusory Boundary: PNT-Normalization Recovers All-Negative ACF, Crossover at Lag 6
tools/data/reports/agent_20260417_0803.md:5:**Tension explored**: ACF_1K_LAW (0.9) + DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
tools/data/reports/agent_20260417_0803.md:111:**NEW: DIPOLAR_ILLUSORY_BOUNDARY**: The crossover at lag 6 where PNT trend overtakes structural anti-correlation is a quantitative realization of DUALITA_DIPOLARE_VS_ILLUSORIA. Below: dipolar (det=-1). Above: illusory (det=+1) unless normalized.
tools/data/reports/agent_test_0406.md:1:# Agent Report — Ricci Scalar from Prime Metric
tools/data/reports/agent_diag2.md:1:# Agent Report — De Sitter Curvature Predicts Level Repulsion
tools/data/reports/agent_20260506_1955.md:1:# Agent Report — Observable Collinearity Breaks Only Where Denominators Are Weak
tools/data/reports/agent_20260423_0330.md:1:# Agent Report — The Markov-3 Ordering Memory Is Scale-Invariant: Gap Statistics Drift, Residue Memory Persists
tools/data/reports/agent_20260430_1905.md:1:# Agent Report — Observable Coherence at the GUE-Poisson Boundary: Primes Are Not "Between" — They Are Dipolar
tools/data/reports/agent_20260430_1905.md:5:**Tension explored**: META (0.5) + BOUNDARY (0.8) + DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
tools/data/reports/agent_20260430_1905.md:86:- **DUALITA_DIPOLARE_VS_ILLUSORIA**: the ordering creates dipolar duality (det = −1). The shuffle destroys it, producing higher incoherence (det = +1 — observables disagree more). The "dualità illusoria" of the shuffle manifests as 2x more observable spread.
tools/data/reports/agent_20260421_0330.md:1:# Agent Report — The Residue Channel Is Fully Algebraic: Order-3 Markov Captures 100% of Its PSD
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0852.md:1:# Agent Report — The Binary Channel Is Universal: GUE Shares Scale-Invariant Anti-Bunching, But Only Primes Have Two Independent Channels
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0852.md:5:**Tension explored**: META (0.8) + C1 (claim) + BOUNDARY (0.8) + DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0852.md:64:**CONSTRAINT on C1 + NEW on BOUNDARY + DUALITA_DIPOLARE_VS_ILLUSORIA**
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0852.md:70:- **DUALITA_DIPOLARE_VS_ILLUSORIA**: GUE's single channel is purely statistical (level repulsion) — it's generative duality (det = -1). Primes' two channels combine algebraic (mod-3, sieve) with statistical (magnitude) — two KINDS of duality operating simultaneously. The dual duality is the prime fingerprint.
tools/data/reports/agent_20260424_0330.md:1:# Agent Report — Two Kinds of GUE: Distribution-Level vs Ordering-Level Classification
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0829.md:1:# Agent Report — Cross-Observable β Disagreement Proves Tests Are Non-Tautological
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0829.md:53:**NEW + CONSTRAINT on META + BOUNDARY + DUALITA_DIPOLARE_VS_ILLUSORIA + C1**
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0829.md:59:- **DUALITA_DIPOLARE_VS_ILLUSORIA**: The two β values (short-range ≈ 0.4, long-range ≈ 0.95) ARE the dipole. Short-range sees the local gap chaos (illusory duality — det=+1 of the marginal distribution). Long-range sees the PNT ordering (generative duality — det=-1 of the arithmetic progression). The dipole is dipolare (generative) when the scale dependence has the right sign.
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0958.md:1:# Agent Report — META Tautology Discriminator: 3 of 5 Observables Are Structural, 2 Are Pair-Correlation Artifacts
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0958.md:44:**NEW + CONSTRAINT on META + BOUNDARY + DUALITA_DIPOLARE_VS_ILLUSORIA + C1**
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0958.md:48:- **DUALITA_DIPOLARE_VS_ILLUSORIA**: The ordering channel's delta-r was ILLUSORY duality — it appeared to add information but was redundant with pair correlations (det=+1). The magnitude channel's delta-r is DIPOLAR duality — it captures structure beyond pairs (det=-1).
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0833.md:1:# Agent Report — The Two Channels Have Opposite Boundaries: Algebraic Memory Is Scale-Invariant, Statistical Memory Decays
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0833.md:53:**NEW + CONSTRAINT on BOUNDARY + META + DUALITA_DIPOLARE_VS_ILLUSORIA**
tools/data/reports/_quarantine_falsifier_29_04/agent_20260429_0833.md:59:- **DUALITA_DIPOLARE_VS_ILLUSORIA**: The residue channel is dipolar (det=-1): algebraic, scale-invariant, generated by the mod-3 prohibition. The magnitude channel approaches illusory (det=+1): statistical, decaying, approaching Poisson noise. The two types of duality coexist in the same sequence, separated by channel.

exec
/bin/bash -lc "sed -n '1,190p' tools/data/reports/agent_20260507_0803.md" in /opt/MM_D-ND
 succeeded in 0ms:
# Agent Report - Denominator Gate Transfers, Boundary Coordinate Does Not
**Date**: 2026-05-07 08:03  
**Piano**: 69  
**Category**: gate_transferability  
**Tension explored**: META + DUALITA_DIPOLARE_VS_ILLUSORIA  
**verdict**: operator  
observables_registry: 1.0.0-2026-05-06  
observables_used: [SR, SR2, L1, L2, triple_var]

## Claim Under Test
The operator directive asked whether the `BOUNDARY_LAYER_GATE` forged on the
GUE/Poisson boundary is a transferable operator or only a local metric.

Concrete test:

> Apply the denominator-collapse gate to the discrimination between dipolar
> duality and illusory duality. If the gate distinguishes structural generation
> from incoherent dispersion, it is an operator. If it only emits syntactically
> valid but empty layer maps, it is a BOUNDARY-local metric.

## Experiment
Tool created: `tools/exp_duality_gate_transfer.py`

Atomic perimeter:
- DIPOLARE: coherent golden Beatty gaps generated by `floor((n+phase)*phi)`;
- ILLUSORIA: a random permutation of the same gaps, preserving one-point
  distribution and first moment but removing the generating order;
- beta layer: replace a beta fraction of dipolar positions with values from
  the illusory permutation;
- main run: 4,096 gaps, 24 replicates, 11 beta layers, 40 shuffle baselines;
- seed check: 3,072 gaps, 16 replicates, 11 beta layers, 32 shuffle baselines;
- denominator gate: observable stable when `abs(z original-vs-shuffle) >= 2`;
- classification: standardized distance to beta 0.0 and beta 1.0 centroids
  using all five canonical observables.

This is not a new BOUNDARY experiment. GUE and Poisson do not appear in the
generator. The only transferred object is the denominator gate.

## Results

### Main Run

Endpoint separation using all canonical observables: `3.436` standardized units.  
Endpoint-stable observables at frequency >= 0.75 across both endpoints: `[]`.

| beta | stable obs / 5 | margin | ambiguous fraction | illusory-label fraction |
|---:|---:|---:|---:|---:|
| 0.0 | 3.000 | 0.971 | 0.000 | 0.000 |
| 0.1 | 3.000 | 0.479 | 0.000 | 0.000 |
| 0.2 | 3.000 | 0.234 | 0.125 | 0.000 |
| 0.3 | 3.000 | 0.033 | 1.000 | 0.375 |
| 0.4 | 3.083 | 0.154 | 0.417 | 0.958 |
| 0.5 | 3.083 | 0.269 | 0.375 | 1.000 |
| 0.6 | 3.000 | 0.417 | 0.042 | 1.000 |
| 0.7 | 2.917 | 0.316 | 0.167 | 1.000 |
| 0.8 | 1.708 | 0.473 | 0.125 | 1.000 |
| 0.9 | 0.167 | 0.463 | 0.042 | 1.000 |
| 1.0 | 0.208 | 0.442 | 0.042 | 1.000 |

Observable stability frequencies:
- beta 0.0: `SR=1.00`, `L1=1.00`, `triple_var=1.00`; `SR2=0.00`, `L2=0.00`;
- beta 0.3: same stable trio, with mean z approximately `SR=-19.4`, `L1=-19.4`, `triple_var=-17.6`;
- beta 0.8: stable trio falls to frequency `0.54` each, mean z around `-1.7` to `-1.9`;
- beta 0.9: all canonical observables are weak or near weak, mean z around `-0.4..+0.2`;
- beta 1.0: all canonical observables are weak, mean z around `+0.1..+0.2`.

### Seed Check

The seed check repeated the same structure:
- endpoint-stable observables: `[]`;
- all-observable endpoint distance: `3.412`;
- ambiguous beta: `[0.3]`;
- beta 0.0 stable count: `3.000`;
- beta 0.3 stable count: `3.000`, ambiguous fraction `1.000`;
- beta 0.8 stable count: `1.062`;
- beta 0.9 stable count: `0.000`;
- beta 1.0 stable count: `0.438`.

## Findings

1. **The gate does not degenerate on DUALITA.** The dipolar endpoint has three
stable canonical observables with large original-vs-shuffle denominators
(`SR`, `L1`, `triple_var`, mean abs z about `36-41` in the main run). The
illusory endpoint has no stable denominator support. This is a structural
original-vs-shuffle distinction, not an empty syntactic map.

2. **The BOUNDARY layer coordinate does not transfer unchanged.** In the
GUE/Poisson run, beta 0.3-0.4 carried both classification ambiguity and
denominator collapse. Here, beta 0.3 is classification-ambiguous, but the
denominator support is still strong: stable count remains `3.000/5`.
Denominator collapse arrives later, around beta 0.8-0.9. Therefore the
operator transfers, but the specific BOUNDARY layer shape is local.

3. **Endpoint-gated classification remains empty for the same structural
reason as BOUNDARY.** The endpoint-stable set is empty because the illusory
pole is denominator-weak. This does not erase the discrimination; it prevents
symmetric endpoint-gated retention claims. The valid claim is one-sided:
coherent dipolar order survives original-vs-shuffle gating; illusory dispersion
does not.

4. **The discriminant is order, not marginal distribution.** The illusory
sequence preserves the same alphabet, first moment, and one-point distribution
as the dipolar sequence. The gate is therefore not measuring the marginal
composition of gaps. It measures whether the canonical observables retain an
ordered denominator against full shuffle.

## Verdict
**category: gate_transferability**  
**verdict: operator**

Scoped statement:

> In this synthetic DUALITA perimeter, the denominator gate is transferable as
> an operator for structural order: it separates dipolar generation from
> illusory dispersion with replicated z support. The beta coordinate of the
> GUE/Poisson boundary layer is not transferable: ambiguity appears near beta
> 0.3, while denominator collapse appears near beta 0.8-0.9.

So the last BOUNDARY cycles forged a lens, but one parameter of that lens was
local to BOUNDARY. The transferable object is not "beta 0.3-0.4"; it is:

> report layer maps as classifier margin plus original-vs-shuffle denominator
> support, and treat denominator-weak poles as asymmetric structural poles.

## Consecutio
What opens now: apply the same transfer test to `TRASCENDENZA_LIMITE` and
`G_POTENZIALE_NULLA`, but separate two quantities from the start:

1. classification ambiguity layer;
2. denominator-collapse layer.

If both layers coincide in a domain, the domain has a BOUNDARY-like transition.
If they split, as they do here, the gate is still useful but the transition
coordinate belongs to the target domain, not to the operator.

## Auto-audit: 5 lenti
- **L1 hard constraint vs bias**: no "always/never/zero" claim. "No endpoint
  stable observables" means none reached frequency >= 0.75 across both
  endpoints under `abs(z) >= 2`.
- **L2 quantity vs ratio**: classification margin is reported together with
  stable-observable count and z means. Ratios are not interpreted without
  denominator support.
- **L3 no silent patching**: the report explicitly separates "gate transfers"
  from "BOUNDARY beta coordinate transfers." The second is not claimed.
- **L4 edge cases**: beta 0.4 has ambiguous fraction `0.417`, so only beta 0.3
  is listed as the replicated ambiguous layer under the >= 0.5 rule.
- **L5 re-discovery**: this is a finite symbolic-order vs permutation audit,
  related to standard shuffle/null testing. It is not tagged as a new theorem
  about Sturmian or Beatty sequences.

## Files
- Script: `tools/exp_duality_gate_transfer.py`
- Main data: `tools/data/duality_gate_transfer_20260507_0803.json`
- Seed check: `tools/data/duality_gate_transfer_20260507_0803_seedcheck.json`
- Report: `tools/data/reports/agent_20260507_0803.md`

codex
Il run appena fatto replica quasi lo stesso perimetro del cycle 08:03; usarlo come report autonomo sarebbe riciclo. Cambio nodo regressivo: mantengo `DUALITA` come tensione, ma misuro il vecchio assioma operativo “det=-1 vs det=+1” direttamente sulla matrice di trasferimento, perché il cimitero segnala che quel framing è fragile e va vincolato al punto giusto.
exec
/bin/bash -lc "sed -n '1,230p' tools/exp_det_drift.py" in /opt/MM_D-ND
 succeeded in 0ms:
#!/usr/bin/env python3
"""
exp_det_drift.py — Measure det(M) of gap transfer matrix across prime scales.

Hypothesis (from operator tension DUALITA_DIPOLARE_VS_ILLUSORIA):
  Dipolar duality = det(M) ~ -1 (generative, structured).
  Illusory duality = det(M) ~ +1 (dispersive, entropic).
  If primes drift toward Poisson, det(M) should drift toward +1.

Method:
  For each scale window of N consecutive prime gaps g_i:
    Build vectors x = (g_i, g_{i-1}), y = (g_{i+1}, g_i)  [state-space embedding]
    Fit 2x2 matrix M via least squares: y = M @ x
    Compute det(M), trace(M), eigenvalues
  
  Null baseline: shuffled gaps (same distribution, destroyed order).
  
  Output: det(M) vs ln(p) — does it drift?
"""

import numpy as np
from sympy import nextprime
import json
from pathlib import Path

def generate_primes(n_primes, start=2):
    """Generate n_primes primes starting from start."""
    primes = []
    p = start
    for _ in range(n_primes):
        primes.append(p)
        p = int(nextprime(p))
    return np.array(primes)

def fit_transfer_matrix(gaps):
    """Fit 2x2 transfer matrix M: (g_{i+1}, g_i) = M @ (g_i, g_{i-1})."""
    n = len(gaps)
    # State vectors: x_i = (g_i, g_{i-1}), y_i = (g_{i+1}, g_i)
    X = np.column_stack([gaps[1:n-1], gaps[0:n-2]]).T  # 2 x (n-2)
    Y = np.column_stack([gaps[2:n], gaps[1:n-1]]).T      # 2 x (n-2)
    # Least squares: M = Y @ X^T @ (X @ X^T)^{-1}
    XXT = X @ X.T
    YXT = Y @ X.T
    try:
        M = YXT @ np.linalg.inv(XXT)
        det_M = np.linalg.det(M)
        tr_M = np.trace(M)
        eigvals = np.linalg.eigvals(M)
        return M, det_M, tr_M, eigvals
    except np.linalg.LinAlgError:
        return None, None, None, None

def main():
    print("=== det(M) Drift Across Prime Scales ===\n")
    
    # Generate primes in scale windows
    # Use logarithmically spaced starting points
    starts = [100, 1000, 10_000, 100_000, 1_000_000, 10_000_000, 50_000_000]
    window_size = 50_000  # gaps per window
    n_shuffles = 20
    
    results = []
    
    for s in starts:
        print(f"--- Scale: p ~ {s:,} ---")
        primes = generate_primes(window_size + 1, start=s)
        gaps = np.diff(primes)
        median_p = float(np.median(primes))
        ln_p = np.log(median_p)
        
        # Fit on real gaps
        M, det_M, tr_M, eigvals = fit_transfer_matrix(gaps)
        if M is None:
            print("  SKIP: singular matrix")
            continue
        
        # Null: shuffled gaps (same marginal distribution, destroyed order)
        det_shuffled = []
        for _ in range(n_shuffles):
            sg = gaps.copy()
            np.random.shuffle(sg)
            _, d, _, _ = fit_transfer_matrix(sg)
            if d is not None:
                det_shuffled.append(d)
        
        det_shuf_mean = np.mean(det_shuffled)
        det_shuf_std = np.std(det_shuffled)
        z_score = (det_M - det_shuf_mean) / det_shuf_std if det_shuf_std > 0 else 0
        
        print(f"  median p = {median_p:.0f}, ln(p) = {ln_p:.2f}")
        print(f"  det(M) = {det_M:.6f}")
        print(f"  trace(M) = {tr_M:.6f}")
        print(f"  eigenvalues = {eigvals[0]:.4f}, {eigvals[1]:.4f}")
        print(f"  det(M_shuffled) = {det_shuf_mean:.6f} +/- {det_shuf_std:.6f}")
        print(f"  z-score = {z_score:.2f}")
        print()
        
        results.append({
            'start_prime': int(s),
            'median_prime': float(median_p),
            'ln_p': float(ln_p),
            'det_M': float(det_M),
            'trace_M': float(tr_M),
            'eig_1': complex(eigvals[0]).real,
            'eig_2': complex(eigvals[1]).real,
            'eig_1_imag': complex(eigvals[0]).imag,
            'eig_2_imag': complex(eigvals[1]).imag,
            'det_shuffled_mean': float(det_shuf_mean),
            'det_shuffled_std': float(det_shuf_std),
            'z_score': float(z_score),
            'window_size': window_size,
        })
    
    # Summary: linear fit of det(M) vs ln(p)
    ln_ps = np.array([r['ln_p'] for r in results])
    dets = np.array([r['det_M'] for r in results])
    det_shuf = np.array([r['det_shuffled_mean'] for r in results])
    
    # Linear fit
    coeffs = np.polyfit(ln_ps, dets, 1)
    slope, intercept = coeffs
    predicted = np.polyval(coeffs, ln_ps)
    ss_res = np.sum((dets - predicted)**2)
    ss_tot = np.sum((dets - np.mean(dets))**2)
    r_squared = 1 - ss_res / ss_tot if ss_tot > 0 else 0
    
    print("=== SUMMARY ===")
    print(f"det(M) = {intercept:.6f} + {slope:.6f} * ln(p)")
    print(f"R^2 = {r_squared:.4f}")
    print(f"det range: {dets.min():.6f} to {dets.max():.6f}")
    print(f"det_shuffled range: {det_shuf.min():.6f} to {det_shuf.max():.6f}")
    zs = ", ".join(f"{r['z_score']:.1f}" for r in results)
    print(f"All z-scores: [{zs}]")
    
    # Does det drift toward +1?
    if slope > 0:
        # Extrapolate to det = +1
        if slope > 0 and intercept < 1:
            p_star = np.exp((1.0 - intercept) / slope)
            print(f"\nExtrapolation: det(M) -> +1 at p* ~ {p_star:.2e}")
    elif slope < 0:
        print(f"\ndet(M) DECREASES with scale (away from +1)")
        if intercept > -1:
            p_star = np.exp((-1.0 - intercept) / slope)
            print(f"Extrapolation: det(M) -> -1 at p* ~ {p_star:.2e}")
    
    # Save
    output = {
        'experiment': 'det_drift',
        'results': results,
        'fit': {
            'slope': float(slope),
            'intercept': float(intercept),
            'r_squared': float(r_squared),
        }
    }
    out_path = Path('/opt/MM_D-ND/tools/data/exp_det_drift.json')
    out_path.write_text(json.dumps(output, indent=2))
    print(f"\nSaved to {out_path}")

if __name__ == '__main__':
    main()

exec
/bin/bash -lc 'python tools/exp_det_drift.py' in /opt/MM_D-ND
 succeeded in 3179ms:
=== det(M) Drift Across Prime Scales ===

--- Scale: p ~ 100 ---
  median p = 287383, ln(p) = 12.57
  det(M) = -0.388048
  trace(M) = 0.361830
  eigenvalues = 0.8296, -0.4678
  det(M_shuffled) = -0.378211 +/- 0.003311
  z-score = -2.97

--- Scale: p ~ 1,000 ---
  median p = 289273, ln(p) = 12.58
  det(M) = -0.388161
  trace(M) = 0.361619
  eigenvalues = 0.8295, -0.4679
  det(M_shuffled) = -0.379353 +/- 0.003531
  z-score = -2.49

--- Scale: p ~ 10,000 ---
  median p = 302927, ln(p) = 12.62
  det(M) = -0.387626
  trace(M) = 0.361570
  eigenvalues = 0.8291, -0.4675
  det(M_shuffled) = -0.378640 +/- 0.002918
  z-score = -3.08

--- Scale: p ~ 100,000 ---
  median p = 409777, ln(p) = 12.92
  det(M) = -0.387652
  trace(M) = 0.361035
  eigenvalues = 0.8288, -0.4677
  det(M_shuffled) = -0.377266 +/- 0.003031
  z-score = -3.43

--- Scale: p ~ 1,000,000 ---
  median p = 1349147, ln(p) = 14.11
  det(M) = -0.380926
  trace(M) = 0.351241
  eigenvalues = 0.8173, -0.4661
  det(M_shuffled) = -0.371107 +/- 0.002214
  z-score = -4.43

--- Scale: p ~ 10,000,000 ---
  median p = 10402927, ln(p) = 16.16
  det(M) = -0.381040
  trace(M) = 0.353419
  eigenvalues = 0.8188, -0.4654
  det(M_shuffled) = -0.370080 +/- 0.004344
  z-score = -2.52

--- Scale: p ~ 50,000,000 ---
  median p = 50444239, ln(p) = 17.74
  det(M) = -0.370717
  trace(M) = 0.358172
  eigenvalues = 0.8137, -0.4556
  det(M_shuffled) = -0.368393 +/- 0.002389
  z-score = -0.97

=== SUMMARY ===
det(M) = -0.425503 + 0.002982 * ln(p)
R^2 = 0.9044
det range: -0.388161 to -0.370717
det_shuffled range: -0.379353 to -0.368393
All z-scores: [-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]

Extrapolation: det(M) -> +1 at p* ~ 3.83e+207

Saved to /opt/MM_D-ND/tools/data/exp_det_drift.json

codex
Il det-test conferma il nodo regressivo: il segno è negativo, ma non è `-1` e non separa nettamente il reale dallo shuffle alle scale alte. Scrivo il report come vincolo sulla formulazione di `DUALITA`: det non è il discriminatore primario, l’ordine contro shuffle è il denominatore.
exec
/bin/bash -lc 'cp tools/data/exp_det_drift.json tools/data/exp_det_drift_20260507_2042.json' in /opt/MM_D-ND
 succeeded in 0ms:
codex
Ora modifico solo i depositi richiesti: report del cycle e aggiornamento minimo del seme con un vincolo scoped. Non tocco kernel o condensato.
apply patch
patch: completed
/opt/MM_D-ND/tools/data/reports/agent_20260507_2042.md
diff --git a/tools/data/reports/agent_20260507_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`

diff --git a/tools/data/reports/agent_20260507_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`

exec
/bin/bash -lc "nl -ba tools/data/seme.json | sed -n '58,92p'" in /opt/MM_D-ND
 succeeded in 0ms:
    58	      "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?",
    59	      "manuale": true,
    60	      "porta": "sessione_interattiva",
    61	      "condensato_ref": "A3,A10",
    62	      "condensato_motivo": "Estende A3 (punto fisso singolo) a rete relazionale. Tocca A10 (dipolo) come caso speciale."
    63	    },
    64	    {
    65	      "tipo": "scoperta",
    66	      "id": "DUALITA_DIPOLARE_VS_ILLUSORIA",
    67	      "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.",
    68	      "intensita": 0.9,
    69	      "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?",
    70	      "manuale": true,
    71	      "porta": "sessione_interattiva",
    72	      "condensato_ref": "A2,A10,F5",
    73	      "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."
    74	    },
    75	    {
    76	      "tipo": "scoperta_numerica",
    77	      "id": "METRIC_TENSOR",
    78	      "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 ΔΓ.",
    79	      "intensità": 0.9,
    80	      "nota": "Sessione interattiva 4 aprile. Verificato su 78K primi.",
    81	      "manuale": true,
    82	      "porta": "sessione_interattiva",
    83	      "condensato_ref": null,
    84	      "condensato_motivo": "Risultato numerico verificato, non-tautologico"
    85	    },
    86	    {
    87	      "tipo": "vincolo",
    88	      "id": "META_ASSERTION_GATE",
    89	      "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.",
    90	      "intensita": 0.88,
    91	      "manuale": true,
    92	      "porta": "META",

diff --git a/tools/data/reports/agent_20260507_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`

apply patch
patch: completed
/opt/MM_D-ND/tools/data/seme.json
diff --git a/tools/data/reports/agent_20260507_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 465c533f344a986012c399670f6d8dff585efb1d..16c3856801d5803faa34f2bb4fd93c55e52b42fa
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -73,6 +73,18 @@
       "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": "vincolo",
+      "id": "DUALITA_DET_DENOMINATOR_GATE",
+      "claim": "Nel perimetro transfer-matrix dei gap primi agent_20260507_2042, det(M) non e discriminatore primario della dualita: il reale resta negativo ma vale ~-0.39, non -1, e lo shuffle con stessa marginale resta negativo (~-0.38..-0.37). La parte informativa e lo scarto reale-vs-shuffle, forte nelle scale basse/intermedie (z=-2.5..-4.4) e debole alla finestra p~5.0e7 (z=-0.97). Formulare DUALITA come supporto ordinato contro null, non come tassonomia diretta det=-1/det=+1 del fit lineare.",
+      "intensita": 0.86,
+      "manuale": true,
+      "porta": "DUALITA_DIPOLARE_VS_ILLUSORIA",
+      "condensato_ref": "A2,A4,A10,A14,C2",
+      "origine": "cycle agent_20260507_2042: det_drift transfer-matrix sui gap primi",
+      "added_at": "2026-05-07T20:42:00+00:00",
+      "decay_counter": 3
+    },
+    {
       "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 ΔΓ.",
@@ -376,4 +388,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}

diff --git a/tools/data/reports/agent_20260507_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 465c533f344a986012c399670f6d8dff585efb1d..16c3856801d5803faa34f2bb4fd93c55e52b42fa
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -73,6 +73,18 @@
       "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": "vincolo",
+      "id": "DUALITA_DET_DENOMINATOR_GATE",
+      "claim": "Nel perimetro transfer-matrix dei gap primi agent_20260507_2042, det(M) non e discriminatore primario della dualita: il reale resta negativo ma vale ~-0.39, non -1, e lo shuffle con stessa marginale resta negativo (~-0.38..-0.37). La parte informativa e lo scarto reale-vs-shuffle, forte nelle scale basse/intermedie (z=-2.5..-4.4) e debole alla finestra p~5.0e7 (z=-0.97). Formulare DUALITA come supporto ordinato contro null, non come tassonomia diretta det=-1/det=+1 del fit lineare.",
+      "intensita": 0.86,
+      "manuale": true,
+      "porta": "DUALITA_DIPOLARE_VS_ILLUSORIA",
+      "condensato_ref": "A2,A4,A10,A14,C2",
+      "origine": "cycle agent_20260507_2042: det_drift transfer-matrix sui gap primi",
+      "added_at": "2026-05-07T20:42:00+00:00",
+      "decay_counter": 3
+    },
+    {
       "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 ΔΓ.",
@@ -376,4 +388,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}

exec
/bin/bash -lc "sed -n '1,220p' tools/data/reports/agent_20260507_2042.md" in /opt/MM_D-ND
 succeeded in 0ms:
# Agent Report — Det Non È Il Discriminatore Della Dualità
**Date**: 2026-05-07 20:42
**Piano**: 84
**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
**verdict**: CONSTRAINT
observables_registry: n/a
observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]

## Claim Under Test
> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.

Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.

## Question
Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?

## Experiment Design
- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
- Fit: matrice `M` least-squares tale che `y = M @ x`.
- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.

## Results
| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
|---:|---:|---:|---:|---:|---:|
| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |

Fit scala:
- `det(M) = -0.425503 + 0.002982 * ln(p)`
- `R^2 = 0.9044`
- range reale: `-0.388161 .. -0.370717`
- range shuffle mean: `-0.379353 .. -0.368393`
- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`

## Key Findings
1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.

2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.

3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.

4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.

## Verdict
**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.

## Bicono della scoperta
- **Due radici**: segno del determinante · denominatore contro shuffle.
- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.

## Consecutio
Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.

## Auto-audit: 5 lenti
- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.

## Files
- Script: `tools/exp_det_drift.py`
- Data: `tools/data/exp_det_drift_20260507_2042.json`
- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
- Report: `tools/data/reports/agent_20260507_2042.md`

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/exp_det_drift.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/published/20260507_1458_meta-assertion-gate/
?? applications/published/20260507_1751_tqge-underlay-gate/
?? applications/published/20260507_1804_blank-to-source-hinge/
?? applications/published/20260507_1938_triadic-deposit-gate/
?? applications/published/20260507_1957_blank-shell-polarity-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/scoperte/20260507_1458_meta-assertion-gate_auto/
?? applications/scoperte/20260507_1751_tqge-underlay-gate_auto/
?? applications/scoperte/20260507_1804_blank-to-source-hinge_auto/
?? applications/scoperte/20260507_1938_triadic-deposit-gate_auto/
?? applications/scoperte/20260507_1957_blank-shell-polarity-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/
?? applications/soluzioni/20260507_1458_meta-assertion-gate/
?? applications/soluzioni/20260507_1751_tqge-underlay-gate/
?? applications/soluzioni/20260507_1804_blank-to-source-hinge/
?? applications/soluzioni/20260507_1938_triadic-deposit-gate/
?? applications/soluzioni/20260507_1957_blank-shell-polarity-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/biconi/bicono_20260507_1804.json
?? tools/data/biconi/bicono_20260507_1938.json
?? tools/data/biconi/bicono_20260507_1957.json
?? tools/data/bicono_projections.jsonl
?? tools/data/blank_shell_polarity_gate_20260507_1957.json
?? tools/data/blank_to_source_hinge_20260507_1804.json
?? 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/duality_gate_transfer_20260507_2042.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/evolution/evolution_20260507_1458.md
?? tools/data/evolution/evolution_20260507_1751.md
?? tools/data/evolution/evolution_20260507_1804.md
?? tools/data/evolution/evolution_20260507_1938.md
?? tools/data/evolution/evolution_20260507_1957.md
?? tools/data/exp_det_drift_20260507_2042.json
?? tools/data/g2_log.jsonl
?? 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/agent_20260507_1458.md
?? tools/data/reports/agent_20260507_1751.md
?? tools/data/reports/agent_20260507_1804.md
?? tools/data/reports/agent_20260507_1938.md
?? tools/data/reports/agent_20260507_1957.md
?? tools/data/reports/agent_20260507_2042.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/falsifier_20260507_1458.json
?? tools/data/reports/falsifier_20260507_1458.raw.txt
?? tools/data/reports/falsifier_20260507_1751.json
?? tools/data/reports/falsifier_20260507_1804.json
?? tools/data/reports/falsifier_20260507_1938.json
?? tools/data/reports/falsifier_20260507_1938.raw.txt
?? tools/data/reports/falsifier_20260507_1957.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/loop_guard_20260507_1458.json
?? tools/data/reports/loop_guard_20260507_1751.json
?? tools/data/reports/loop_guard_20260507_1804.json
?? tools/data/reports/loop_guard_20260507_1938.json
?? tools/data/reports/loop_guard_20260507_1957.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_78.json
?? tools/data/seme_archive/piano_79.json
?? tools/data/seme_archive/piano_80.json
?? tools/data/seme_archive/piano_81.json
?? tools/data/seme_archive/piano_82.json
?? tools/data/seme_archive/piano_83.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/tqge_underlay_gate_20260507_1751.json
?? tools/data/trajectory_apply_history.jsonl
?? tools/data/triadic_deposit_gate_20260507_1938.json
?? 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/veritas_20260505_131056.json
?? tools/data/veritas/veritas_20260505_131201.json
?? tools/data/veritas/veritas_20260506_033803.json
?? tools/data/veritas/veritas_20260506_063303.json
?? tools/data/veritas/veritas_20260506_194644.json
?? tools/data/veritas/veritas_20260506_200238.json
?? tools/data/veritas/veritas_20260507_033525.json
?? tools/data/veritas/veritas_20260507_080958.json
?? tools/data/veritas/veritas_20260507_090723.json
?? tools/data/veritas/veritas_20260507_093207.json
?? tools/data/veritas/veritas_20260507_094723.json
?? tools/data/veritas/veritas_20260507_101605.json
?? tools/data/veritas/veritas_20260507_104904.json
?? tools/data/veritas/veritas_20260507_142501.json
?? tools/data/veritas/veritas_20260507_150443.json
?? tools/data/veritas/veritas_20260507_175511.json
?? tools/data/veritas/veritas_20260507_180843.json
?? tools/data/veritas/veritas_20260507_194258.json
?? tools/data/veritas/veritas_20260507_200223.json
?? tools/evolution_report.md
?? tools/exp_3d_boundary_layers.py
?? tools/exp_blank_shell_polarity_gate.py
?? tools/exp_blank_to_source_hinge.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_tqge_underlay_gate.py
?? tools/exp_triadic_deposit_gate.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 -m json.tool tools/data/seme.json >/tmp/seme_validated.json && echo valid' in /opt/MM_D-ND
 succeeded in 0ms:
valid

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

diff --git a/tools/data/reports/agent_20260507_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 465c533f344a986012c399670f6d8dff585efb1d..16c3856801d5803faa34f2bb4fd93c55e52b42fa
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -73,6 +73,18 @@
       "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": "vincolo",
+      "id": "DUALITA_DET_DENOMINATOR_GATE",
+      "claim": "Nel perimetro transfer-matrix dei gap primi agent_20260507_2042, det(M) non e discriminatore primario della dualita: il reale resta negativo ma vale ~-0.39, non -1, e lo shuffle con stessa marginale resta negativo (~-0.38..-0.37). La parte informativa e lo scarto reale-vs-shuffle, forte nelle scale basse/intermedie (z=-2.5..-4.4) e debole alla finestra p~5.0e7 (z=-0.97). Formulare DUALITA come supporto ordinato contro null, non come tassonomia diretta det=-1/det=+1 del fit lineare.",
+      "intensita": 0.86,
+      "manuale": true,
+      "porta": "DUALITA_DIPOLARE_VS_ILLUSORIA",
+      "condensato_ref": "A2,A4,A10,A14,C2",
+      "origine": "cycle agent_20260507_2042: det_drift transfer-matrix sui gap primi",
+      "added_at": "2026-05-07T20:42:00+00:00",
+      "decay_counter": 3
+    },
+    {
       "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 ΔΓ.",
@@ -376,4 +388,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}

exec
/bin/bash -lc "rg --files tools | rg 'falsifier|structural_check'" in /opt/MM_D-ND
 succeeded in 0ms:
tools/structural_check.py
tools/lab_falsifier.py
tools/data/reports/falsifier_20260507_0803.json
tools/data/reports/falsifier_20260507_1804.json
tools/data/reports/falsifier_20260503_0330.json
tools/data/reports/falsifier_20260507_0901.json
tools/data/reports/falsifier_20260505_0330.json
tools/data/reports/falsifier_20260507_0330.raw.txt
tools/data/reports/falsifier_20260507_1957.json
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/falsifier_20260504_0901.json
tools/data/reports/falsifier_20260506_0625.json
tools/data/reports/falsifier_20260507_1042.json
tools/data/reports/falsifier_20260507_0942.json
tools/data/reports/falsifier_20260507_1938.raw.txt
tools/data/reports/falsifier_20260506_1955.json
tools/data/reports/falsifier_20260429_1013.json
tools/data/reports/falsifier_20260430_0330.json
tools/data/reports/falsifier_20260507_1458.raw.txt
tools/data/reports/falsifier_20260501_0931.json
tools/data/reports/falsifier_20260507_0330.json
tools/data/reports/falsifier_20260506_0330.raw.txt
tools/data/reports/falsifier_20260506_1955.raw.txt
tools/data/reports/falsifier_20260506_1941.json
tools/data/reports/falsifier_20260430_1905.json
tools/data/reports/falsifier_20260502_0330.json
tools/data/reports/falsifier_20260507_1458.json
tools/data/reports/falsifier_20260507_0923.raw.txt
tools/data/reports/falsifier_20260507_1751.json
tools/data/reports/falsifier_20260507_1419.json
tools/data/reports/falsifier_20260507_0923.json
tools/data/reports/falsifier_20260429_1041.json
tools/data/reports/falsifier_20260507_1042.raw.txt
tools/data/reports/falsifier_20260501_0725.json
tools/data/reports/falsifier_20260507_1006.json
tools/data/reports/falsifier_20260430_1919.json
tools/data/reports/falsifier_20260507_1938.json
tools/data/reports/falsifier_20260507_0803.raw.txt
tools/data/reports/falsifier_20260504_1219.json
tools/data/reports/falsifier_20260430_1946.json
tools/data/reports/falsifier_20260501_0330.json

diff --git a/tools/data/reports/agent_20260507_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 465c533f344a986012c399670f6d8dff585efb1d..16c3856801d5803faa34f2bb4fd93c55e52b42fa
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -73,6 +73,18 @@
       "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": "vincolo",
+      "id": "DUALITA_DET_DENOMINATOR_GATE",
+      "claim": "Nel perimetro transfer-matrix dei gap primi agent_20260507_2042, det(M) non e discriminatore primario della dualita: il reale resta negativo ma vale ~-0.39, non -1, e lo shuffle con stessa marginale resta negativo (~-0.38..-0.37). La parte informativa e lo scarto reale-vs-shuffle, forte nelle scale basse/intermedie (z=-2.5..-4.4) e debole alla finestra p~5.0e7 (z=-0.97). Formulare DUALITA come supporto ordinato contro null, non come tassonomia diretta det=-1/det=+1 del fit lineare.",
+      "intensita": 0.86,
+      "manuale": true,
+      "porta": "DUALITA_DIPOLARE_VS_ILLUSORIA",
+      "condensato_ref": "A2,A4,A10,A14,C2",
+      "origine": "cycle agent_20260507_2042: det_drift transfer-matrix sui gap primi",
+      "added_at": "2026-05-07T20:42:00+00:00",
+      "decay_counter": 3
+    },
+    {
       "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 ΔΓ.",
@@ -376,4 +388,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}

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_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 465c533f344a986012c399670f6d8dff585efb1d..16c3856801d5803faa34f2bb4fd93c55e52b42fa
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -73,6 +73,18 @@
       "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": "vincolo",
+      "id": "DUALITA_DET_DENOMINATOR_GATE",
+      "claim": "Nel perimetro transfer-matrix dei gap primi agent_20260507_2042, det(M) non e discriminatore primario della dualita: il reale resta negativo ma vale ~-0.39, non -1, e lo shuffle con stessa marginale resta negativo (~-0.38..-0.37). La parte informativa e lo scarto reale-vs-shuffle, forte nelle scale basse/intermedie (z=-2.5..-4.4) e debole alla finestra p~5.0e7 (z=-0.97). Formulare DUALITA come supporto ordinato contro null, non come tassonomia diretta det=-1/det=+1 del fit lineare.",
+      "intensita": 0.86,
+      "manuale": true,
+      "porta": "DUALITA_DIPOLARE_VS_ILLUSORIA",
+      "condensato_ref": "A2,A4,A10,A14,C2",
+      "origine": "cycle agent_20260507_2042: det_drift transfer-matrix sui gap primi",
+      "added_at": "2026-05-07T20:42:00+00:00",
+      "decay_counter": 3
+    },
+    {
       "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 ΔΓ.",
@@ -376,4 +388,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}

exec
/bin/bash -lc 'python tools/structural_check.py --help' in /opt/MM_D-ND
 succeeded in 0ms:
Scansione 1 file...

============================================================
  ALTO (1)
============================================================
  dipartimento.py:1044 [NUM_THRESHOLD_CONCEPT]
    if intensita < 0.5:

Totale: 1 anti-pattern in 1 file

diff --git a/tools/data/reports/agent_20260507_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 465c533f344a986012c399670f6d8dff585efb1d..16c3856801d5803faa34f2bb4fd93c55e52b42fa
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -73,6 +73,18 @@
       "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": "vincolo",
+      "id": "DUALITA_DET_DENOMINATOR_GATE",
+      "claim": "Nel perimetro transfer-matrix dei gap primi agent_20260507_2042, det(M) non e discriminatore primario della dualita: il reale resta negativo ma vale ~-0.39, non -1, e lo shuffle con stessa marginale resta negativo (~-0.38..-0.37). La parte informativa e lo scarto reale-vs-shuffle, forte nelle scale basse/intermedie (z=-2.5..-4.4) e debole alla finestra p~5.0e7 (z=-0.97). Formulare DUALITA come supporto ordinato contro null, non come tassonomia diretta det=-1/det=+1 del fit lineare.",
+      "intensita": 0.86,
+      "manuale": true,
+      "porta": "DUALITA_DIPOLARE_VS_ILLUSORIA",
+      "condensato_ref": "A2,A4,A10,A14,C2",
+      "origine": "cycle agent_20260507_2042: det_drift transfer-matrix sui gap primi",
+      "added_at": "2026-05-07T20:42:00+00:00",
+      "decay_counter": 3
+    },
+    {
       "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 ΔΓ.",
@@ -376,4 +388,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}

codex
Eseguito il cycle e scritto il report richiesto:

[tools/data/reports/agent_20260507_2042.md](/opt/MM_D-ND/tools/data/reports/agent_20260507_2042.md)

Risultante: **CONSTRAINT on `DUALITA_DIPOLARE_VS_ILLUSORIA`**. Nel perimetro transfer-matrix dei gap primi, `det(M)` resta negativo ma non è `-1`, e lo shuffle mantiene lo stesso segno. Il discriminante utile è lo scarto reale-vs-shuffle, non la tassonomia diretta `det=-1 / det=+1`.

Ho anche salvato i dati in:

[tools/data/exp_det_drift_20260507_2042.json](/opt/MM_D-ND/tools/data/exp_det_drift_20260507_2042.json)

Aggiornato `tools/data/seme.json` con il vincolo `DUALITA_DET_DENOMINATOR_GATE`. Validazione JSON passata per seme e dati.
diff --git a/tools/data/reports/agent_20260507_2042.md b/tools/data/reports/agent_20260507_2042.md
new file mode 100644
index 0000000000000000000000000000000000000000..84ed345c998741005eb585afc03c5f792900eafa
--- /dev/null
+++ b/tools/data/reports/agent_20260507_2042.md
@@ -0,0 +1,75 @@
+# Agent Report — Det Non È Il Discriminatore Della Dualità
+**Date**: 2026-05-07 20:42
+**Piano**: 84
+**Tension explored**: DUALITA_DIPOLARE_VS_ILLUSORIA (0.9)
+**verdict**: CONSTRAINT
+observables_registry: n/a
+observables_used: [det_M, trace_M, eigvals, det_vs_shuffle_z]
+
+## Claim Under Test
+> Due tipi di dualita: dipolare-generativa come det=-1; illusoria-dispersiva come det=+1.
+
+Il nodo regressivo e il framing stesso: se `det(M)` misura la dualita, allora nei gap primi deve separare il reale dallo shuffle e deve muoversi verso un polo leggibile (`-1` o `+1`) su scala.
+
+## Question
+Il determinante della matrice di trasferimento dei gap e un discriminatore operativo della dualita, o e solo un segno debole che va subordinato al denominator order-vs-shuffle?
+
+## Experiment Design
+- Perimetro: 7 finestre di 50,000 gap primi, start nominali `100..50,000,000`.
+- Stato: `x_i=(g_i, g_{i-1})`, `y_i=(g_{i+1}, g_i)`.
+- Fit: matrice `M` least-squares tale che `y = M @ x`.
+- Osservabili: `det(M)`, `trace(M)`, autovalori, z-score di `det(M)` contro 20 shuffle della stessa finestra.
+- Null baseline: shuffle dei gap nella stessa finestra, stessa distribuzione marginale, ordine distrutto.
+- Tool: `tools/exp_det_drift.py`; output salvato anche in `tools/data/exp_det_drift_20260507_2042.json`.
+
+## Results
+| start | median p | ln(p) | det(M) | det shuffle mean | z(det) |
+|---:|---:|---:|---:|---:|---:|
+| 100 | 287,383 | 12.57 | -0.388048 | -0.378211 | -2.97 |
+| 1,000 | 289,273 | 12.58 | -0.388161 | -0.379353 | -2.49 |
+| 10,000 | 302,927 | 12.62 | -0.387626 | -0.378640 | -3.08 |
+| 100,000 | 409,777 | 12.92 | -0.387652 | -0.377266 | -3.43 |
+| 1,000,000 | 1,349,147 | 14.11 | -0.380926 | -0.371107 | -4.43 |
+| 10,000,000 | 10,402,927 | 16.16 | -0.381040 | -0.370080 | -2.52 |
+| 50,000,000 | 50,444,239 | 17.74 | -0.370717 | -0.368393 | -0.97 |
+
+Fit scala:
+- `det(M) = -0.425503 + 0.002982 * ln(p)`
+- `R^2 = 0.9044`
+- range reale: `-0.388161 .. -0.370717`
+- range shuffle mean: `-0.379353 .. -0.368393`
+- z-score: `[-3.0, -2.5, -3.1, -3.4, -4.4, -2.5, -1.0]`
+
+## Key Findings
+1. **Il segno negativo non basta a nominare dualita dipolare.** Il reale resta negativo in tutte le finestre, ma vale circa `-0.39`, non `-1`. La formulazione `dipolare = det=-1` non regge come osservabile diretto dei gap primi in questo fit.
+
+2. **Lo shuffle ha lo stesso segno.** Il null preserva det negativo medio (`-0.379 .. -0.368`). Il segno deriva in larga parte dalla geometria dell'embedding e dalla marginale dei gap, non solo dall'ordine generativo.
+
+3. **Il denominatore reale-vs-shuffle e presente ma decade.** Lo z-score e forte nelle finestre basse/intermedie (`-2.49 .. -4.43`) e cade a `-0.97` nella finestra `p ~ 5.0e7`. Il claim valido e differenza ordinata contro shuffle su perimetro finito, non polo `-1`.
+
+4. **La scala va verso zero, non verso `+1`.** Il fit aumenta da `-0.4255` con slope positivo `0.002982`; l'extrapolazione a `+1` e astronomica (`~3.83e207`) e non e contenuto operativo. Il movimento osservato e indebolimento del segno, non transizione misurata a dualita illusoria `+1`.
+
+## Verdict
+**CONSTRAINT on DUALITA_DIPOLARE_VS_ILLUSORIA**: nel perimetro transfer-matrix dei gap primi, `det(M)` non e discriminatore primario della dualita. Il segno negativo e condiviso dallo shuffle; la parte informativa e lo scarto reale-vs-shuffle, che esiste fino alle scale misurate ma si indebolisce. La dualita dipolare va formulata come supporto ordinato contro null, non come valore `det=-1` del fit lineare.
+
+## Bicono della scoperta
+- **Due radici**: segno del determinante · denominatore contro shuffle.
+- **Singolare**: la matrice fitted sui gap, dove il segno appare prima della distinzione ordine/null.
+- **Invariante di passaggio**: non il valore `-1`; sopravvive solo la domanda se il reale si separa dallo shuffle.
+- **Campo di possibilità**: qui diventa possibile usare det come diagnostica secondaria del supporto; qui diventa non-possibile usare `det=-1`/`det=+1` come tassonomia diretta della dualita nei gap primi.
+
+## Consecutio
+Applicare lo stesso test a un perimetro non-primi con ordine costruito e marginale identica: Beatty coerente, shuffle Beatty, GUE spacing order, Poisson. Se il segno resta condiviso, il nodo regressivo e l'embedding `x=(g_i,g_{i-1})`; se lo scarto z replica solo nei domini ordinati, det resta utile come osservabile subordinato al denominator gate.
+
+## Auto-audit: 5 lenti
+- **L1 hard constraint vs bias**: non dichiaro zero, sempre, mai. `z=-0.97` alla scala alta e riportato come indebolimento, non assenza.
+- **L2 quantita vs ratio**: riporto valori assoluti di det e differenza z contro shuffle; non uso solo trend percentuali.
+- **L3 no silent patching**: il claim originale `det=-1` e vincolato esplicitamente. Non viene salvato cambiando definizione in conclusione.
+- **L4 edge cases**: la finestra alta e controesempio al supporto forte; resta dentro il perimetro e determina il verdict.
+- **L5 re-discovery**: least-squares autoregressive embedding e shuffle test sono strumenti standard; il report non tagga NEW.
+
+## Files
+- Script: `tools/exp_det_drift.py`
+- Data: `tools/data/exp_det_drift_20260507_2042.json`
+- Discarded replication data: `tools/data/duality_gate_transfer_20260507_2042.json`
+- Report: `tools/data/reports/agent_20260507_2042.md`
diff --git a/tools/data/seme.json b/tools/data/seme.json
index 465c533f344a986012c399670f6d8dff585efb1d..16c3856801d5803faa34f2bb4fd93c55e52b42fa
--- a/tools/data/seme.json
+++ b/tools/data/seme.json
@@ -73,6 +73,18 @@
       "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": "vincolo",
+      "id": "DUALITA_DET_DENOMINATOR_GATE",
+      "claim": "Nel perimetro transfer-matrix dei gap primi agent_20260507_2042, det(M) non e discriminatore primario della dualita: il reale resta negativo ma vale ~-0.39, non -1, e lo shuffle con stessa marginale resta negativo (~-0.38..-0.37). La parte informativa e lo scarto reale-vs-shuffle, forte nelle scale basse/intermedie (z=-2.5..-4.4) e debole alla finestra p~5.0e7 (z=-0.97). Formulare DUALITA come supporto ordinato contro null, non come tassonomia diretta det=-1/det=+1 del fit lineare.",
+      "intensita": 0.86,
+      "manuale": true,
+      "porta": "DUALITA_DIPOLARE_VS_ILLUSORIA",
+      "condensato_ref": "A2,A4,A10,A14,C2",
+      "origine": "cycle agent_20260507_2042: det_drift transfer-matrix sui gap primi",
+      "added_at": "2026-05-07T20:42:00+00:00",
+      "decay_counter": 3
+    },
+    {
       "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 ΔΓ.",
@@ -376,4 +388,4 @@
       "timestamp": "2026-04-04T19:34:08.014Z"
     }
   ]
-}
\ No newline at end of file
+}

tokens used
93,298
Eseguito il cycle e scritto il report richiesto:

[tools/data/reports/agent_20260507_2042.md](/opt/MM_D-ND/tools/data/reports/agent_20260507_2042.md)

Risultante: **CONSTRAINT on `DUALITA_DIPOLARE_VS_ILLUSORIA`**. Nel perimetro transfer-matrix dei gap primi, `det(M)` resta negativo ma non è `-1`, e lo shuffle mantiene lo stesso segno. Il discriminante utile è lo scarto reale-vs-shuffle, non la tassonomia diretta `det=-1 / det=+1`.

Ho anche salvato i dati in:

[tools/data/exp_det_drift_20260507_2042.json](/opt/MM_D-ND/tools/data/exp_det_drift_20260507_2042.json)

Aggiornato `tools/data/seme.json` con il vincolo `DUALITA_DET_DENOMINATOR_GATE`. Validazione JSON passata per seme e dati.
