# Analisi implementativa — hardening degli hook Sophia e governance della memoria Codex/MCP

Repository: `sophiadeveloper/mcp-servers`  
Branch: `master`  
Baseline: `407677463f1944ffc4d6c1051c0975bb0c4b12be`  
Data analisi: 2026-07-31  
Stato quality gate: `PASS_CON_RISCHI`

## Sintesi esecutiva

Il falso positivo osservato non deriva da un conflitto di storage tra `memory-node` e la memoria nativa Codex. Deriva dal modo in cui l’hook `UserPromptSubmit` classifica il testo e formula il risultato:

1. il router analizza un testo aggregato ricavato da più campi del payload;
2. la funzione `matchIntent()` cerca parole come `ricorda`, `annota` e `memorizza` senza distinguere istruzioni effettive da codice, citazioni, documenti o prompt incollati;
3. in caso di match, l’hook dichiara come fatto che l’utente abbia chiesto di ricordare qualcosa;
4. lo stesso messaggio ordina di chiamare `memory_add_entry`.

La formulazione attuale:

```text
You are asked to remember something. Use memory_add_entry in memory-mcp to store this context persistently.
```

contraddice i principi dichiarati nello stesso hook — suggerimenti non vincolanti, precisione prima del recall e comportamento conservativo — e trasforma un’evidenza lessicale debole in una direttiva operativa.

La correzione consigliata è incrementale e su più livelli:

- introdurre un segmentatore puro che separi testo istruttivo e regioni dati, mascherando almeno fenced code, inline code e blockquote durante l’intent detection;
- sostituire il matching diretto con una policy deterministica strutturata, applicata esclusivamente al messaggio utente corrente;
- rendere l’output un hint condizionale, non una dichiarazione o un comando;
- mantenere l’enforcement reale sulle operazioni mutative tramite approvazione per-tool nel `config.toml`;
- integrare la configurazione tramite il percorso installer già transazionale;
- estendere `memory-node` con cancellazione fisica soltanto per record già invalidati;
- aggiungere una suite di regressione comune per prompt lunghi, testo citato, fence non chiuse, negazioni, compatibilità cross-runtime e merge TOML.

Non è consigliato sostituire subito tutti gli entry point con un dispatcher unico. Il repository dispone già di entry point distinti e adapter condivisi per Codex, Cursor e Antigravity. La strategia a minor rischio è introdurre moduli puri comuni e mantenere inizialmente invariati gli script di ingresso.

## Problema e obiettivo

### Problema osservato

Un prompt tecnico lungo, fornito come specifica implementativa, ha attivato erroneamente l’hook di memoria. Il prompt conteneva requisiti come “conservare gli stati diagnostici” e numerosi esempi, ma non chiedeva di salvare informazioni in memoria persistente.

L’hook ha prodotto:

```text
You are asked to remember something. Use memory_add_entry in memory-mcp to store this context persistently.
```

Il risultato è un falso positivo ad alto impatto: il rilevatore non si limita a suggerire una skill, ma attribuisce all’utente un’intenzione non espressa e propone direttamente un tool mutativo.

### Obiettivo

Realizzare un motore deterministico comune e verificabile che:

- distingua istruzioni, citazioni e dati incollati;
- applichi policy diverse in base all’evento hook;
- emetta normalmente output vuoto;
- produca soltanto hint condizionali quando esiste evidenza forte;
- non trasformi mai autonomamente un match lessicale in una scrittura persistente;
- protegga le operazioni mutative anche se il modello interpreta male il prompt;
- gestisca in modo esplicito la coesistenza fra memoria nativa Codex e `memory-node`;
- consenta la cancellazione controllata di record MCP già invalidati.

## Comportamento attuale e comportamento atteso

| Area | Comportamento attuale | Comportamento atteso |
| --- | --- | --- |
| Input `UserPromptSubmit` | Il routing usa testo aggregato da più campi del payload | Le policy di intento usano soltanto il messaggio utente corrente |
| Segmentazione | Nessuna distinzione generale fra istruzioni e regioni dati | Fenced code, inline code e blockquote non partecipano all’intent detection |
| Intento memoria | Regex su termini generici | Evidenza strutturata: imperativo esplicito, persistenza, assenza di negazione e contesto metalinguistico |
| Output hook | Dichiarazione fattuale più comando al tool | Hint prudente, condizionale e non imperativo |
| Scrittura memoria | Skill e `PreToolUse` forniscono hygiene, ma non una conferma semantica obbligatoria | Approvazione Codex per ogni tool mutativo, più anteprima operazione nelle regole agente |
| Memoria nativa Codex | Nessuna policy installer dedicata osservata | Profilo prudente iniettato idempotentemente nel TOML |
| Priorità delle fonti | Regole già presenti, ma non traducibili in precedenza tecnica della memoria nativa | Gerarchia formalizzata; nei contesti auditabili si disabilita l’uso della memoria nativa |
| Lifecycle record | Invalidazione soft disponibile | Delete fisico solo dopo invalidazione, conferma esplicita e audit tombstone |
| Test | Esiste un test che attende la vecchia direttiva | Fixture di regressione sul falso positivo e matrice instruction/data |

## Scope

### In scope

- hardening di `UserPromptSubmit`;
- segmentazione deterministica del prompt;
- policy di intento memoria riusabile;
- contratto comune per decisioni hook;
- revisione del memory `PreToolUse`;
- regole della skill e regole agente sulla conferma;
- iniezione delle policy Codex nel `config.toml`;
- gestione prudente della memoria nativa Codex;
- cancellazione fisica di record MCP invalidati;
- test unitari, smoke, runtime e memory-node;
- compatibilità Codex, Cursor e Antigravity per i moduli condivisi.

### Fuori scope

- sostituzione della memoria nativa Codex;
- sincronizzazione fra storage Codex e SQLite di `memory-node`;
- definizione di una precedenza tecnica non supportata dal client Codex;
- migrazione automatica dei record già presenti nella memoria nativa;
- classificatore LLM per decidere se scrivere memoria;
- salvataggio automatico di conversazioni;
- riscrittura completa del routing engine;
- introduzione di nuove dipendenze npm;
- modifica automatica di hook di terze parti o non gestiti dall’installer Sophia;
- eliminazione fisica di record attivi;
- modifica del repository nell’ambito di questa analisi.

## Fonti consultate

### Fonte funzionale

- Allegato fornito dall’utente: prompt tecnico che ha generato l’inserimento errato in memoria.
- Discussione corrente: requisiti su hint condizionali, esclusione dei fenced block, generalizzazione del motore, gestione TOML e cancellazione dei record invalidati.

### Repository alla baseline indicata

- [`scripts/hooks/sophia-user-prompt-submit.mjs`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/scripts/hooks/sophia-user-prompt-submit.mjs)
- [`scripts/hooks/routing-engine.mjs`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/scripts/hooks/routing-engine.mjs)
- [`scripts/hooks/sophia-pretool-memory.mjs`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/scripts/hooks/sophia-pretool-memory.mjs)
- [`scripts/hooks-generator-lib.js`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/scripts/hooks-generator-lib.js)
- [`scripts/generate-codex-hooks.js`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/scripts/generate-codex-hooks.js)
- [`scripts/inject-user-mcp-settings.js`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/scripts/inject-user-mcp-settings.js)
- [`scripts/install-user-runtime.js`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/scripts/install-user-runtime.js)
- [`genera_mcp_json.sh`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/genera_mcp_json.sh)
- [`shared-agent-rules/GLOBAL.md`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/shared-agent-rules/GLOBAL.md)
- [`skills/mcp-memory-operator/SKILL.md`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/skills/mcp-memory-operator/SKILL.md)
- [`memory-node/README.md`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/memory-node/README.md)
- [`docs/memory-node/memory-node-technical-analysis.md`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/docs/memory-node/memory-node-technical-analysis.md)
- [`tests/routing-hooks.test.mjs`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/tests/routing-hooks.test.mjs)
- [`scripts/smoke-codex-hooks.js`](https://github.com/sophiadeveloper/mcp-servers/blob/407677463f1944ffc4d6c1051c0975bb0c4b12be/scripts/smoke-codex-hooks.js)

### Documentazione pubblica ufficiale

Consultata il 2026-07-31:

- [Codex hooks](https://developers.openai.com/codex/hooks)
- [Codex config reference](https://developers.openai.com/codex/config-reference)
- [Codex memories](https://developers.openai.com/codex/memories)

Limite dell’evidenza esterna: la documentazione descrive il contratto del client Codex, non dimostra il comportamento runtime della build installata su una macchina specifica.

## Evidenze osservate

### E-01 — La direttiva errata è nel codice del router

`matchIntent()` contiene un ramo “Remembering Intent” che cerca:

```text
ricorda | annota | memorizza | tieni a mente | salva in memoria
```

e restituisce direttamente la frase che ordina di usare `memory_add_entry`.

### E-02 — Il routing principale usa testo aggregato

Nel `main()` dell’hook:

```js
const aggregateText = collectStrings(payload).join('\n').trim();
```

`collectStrings()` attraversa più campi testuali e anche `messages`. Il progetto dispone già di `extractCurrentUserSubmissionText()`, ma il suo risultato è usato principalmente per dichiarazioni esplicite di skill, non come input esclusivo di tutte le policy di intento.

### E-03 — Il motore deterministico esistente è una buona base, ma non segmenta regioni

`routing-engine.mjs` è puro, non effettua I/O e dispone già di:

- normalizzazione;
- tokenizzazione;
- suddivisione in clausole;
- gestione di `non` e `senza`;
- segnali affermativi;
- anti-pattern;
- ranking deterministico e diagnostica.

Non dispone di una mappa instruction/data né di esclusione strutturale di code fence, inline code o blockquote.

### E-04 — Il memory `PreToolUse` è advisory

`sophia-pretool-memory.mjs` riconosce add/invalidate e produce un `systemMessage` con regole di hygiene. Non blocca la chiamata, non collega l’operazione a una conferma esplicita del turno e analizza ricorsivamente i valori del payload.

### E-05 — Il repository ha già un percorso installer sicuro per il TOML

`inject-user-mcp-settings.js` gestisce:

- target `~/.codex/config.toml`;
- dry run;
- backup;
- scrittura temporanea;
- sostituzione atomica;
- rollback;
- validazione;
- merge selettivo dei blocchi MCP.

Il merge corrente è specializzato per `[mcp_servers.<name>]` e relativi `.env`; non gestisce ancora in modo generale chiavi root, `[features]`, `[memories]` e tabelle `.tools.<tool>`.

### E-06 — L’identificativo generato del server è stabile nel generatore

`genera_mcp_json.sh` definisce:

```text
memory-mcp-server
```

e genera il blocco Codex:

```toml
[mcp_servers.memory-mcp-server]
```

Questo identificativo può essere usato per le policy per-tool, ma l’installer deve comunque derivarlo dalla configurazione generata o da una costante condivisa per evitare duplicazioni.

### E-07 — `memory-node` supporta invalidazione, non delete

La superficie M2 documentata contiene otto tool, incluso `memory_invalidate_entry`. L’invalidazione è soft, idempotente ed esclude il record dalle ricerche `active`.

`memory_delete_entry` compare soltanto nella roadmap tecnica e non nel contratto corrente della skill.

### E-08 — La gerarchia delle fonti è già parzialmente codificata

`shared-agent-rules/GLOBAL.md` stabilisce che la memoria è contesto operativo, che le fonti primarie prevalgono e che i conflitti vanno segnalati. Manca una regola esplicita che vieti ogni write mutativo senza anteprima e conferma.

### E-09 — I test consolidano il comportamento pericoloso

Lo smoke test attuale verifica che il prompt:

```text
Ricorda cosa dice la documentazione sul commit abc1234.
```

produca la stringa:

```text
You are asked to remember something
```

Il test deve essere aggiornato per preservare la rilevazione come possibile intento, ma rifiutare la direttiva automatica al tool.

### E-10 — Il contesto dell’hook ha autorità elevata

La documentazione ufficiale Codex indica che l’output di `UserPromptSubmit` può essere aggiunto come contesto developer. Per questo un falso positivo formulato come fatto o comando è più rischioso di un normale suggerimento testuale.

## Inferenze tecniche

### I-01 — Il falso positivo è riproducibile con citazioni e snippet

In assenza di segmentazione, una stringa come:

````text
Verifica che questo esempio non attivi l’hook:

```text
Ricorda questa informazione.
```
````

può soddisfare il ramo di `matchIntent()` anche se l’utente sta descrivendo un test negativo.

### I-02 — Il filtro deve essere applicato per policy, non globalmente

Mascherare fenced block è corretto per l’intent detection su `UserPromptSubmit`. Non è corretto applicare lo stesso preprocessing agli argomenti strutturati di `PreToolUse`, dove `tool_name` e `tool_input` sono il dato autorevole da esaminare.

### I-03 — L’approvazione TOML è il controllo più affidabile disponibile

Un hint prudente riduce i falsi positivi, ma resta testo interpretato dal modello. L’approvazione per-tool intercetta invece la chiamata mutativa effettiva. Non dimostra che il contenuto sia corretto, ma impedisce una scrittura completamente silenziosa.

### I-04 — La priorità fra le due memorie non è configurabile come ordinamento

Le opzioni Codex consentono di usare o generare memoria nativa e di disabilitarne la generazione con contesto esterno. Non è emersa una chiave che assegni formalmente priorità a `memory-node`. La precedenza deve quindi essere ottenuta con:

- regole agente;
- verifica su fonti primarie;
- disattivazione di `use_memories` nei profili auditabili.

## Decisioni architetturali proposte

### D-01 — Evoluzione incrementale, non big-bang dispatcher

Mantenere gli entry point esistenti:

```text
sophia-user-prompt-submit.mjs
sophia-pretool-memory.mjs
sophia-pretool-sql.mjs
...
```

e introdurre moduli puri condivisi. Un dispatcher unico potrà essere valutato dopo una fase di parity test cross-runtime.

### D-02 — Separazione fra testo originale e testo di detection

Ogni policy testuale riceve:

```ts
{
  originalText,
  detectionText,
  regions
}
```

- `originalText` non viene modificato;
- `detectionText` conserva newline e offset, ma maschera le regioni non eleggibili;
- `regions` descrive tipo, intervallo ed eleggibilità.

### D-03 — Output strutturato delle policy

Una policy non restituisce direttamente testo libero:

```ts
type PolicyDecision = 'noop' | 'hint' | 'allow' | 'rewrite' | 'block' | 'audit';

interface PolicyResult {
  policyId: string;
  decision: PolicyDecision;
  reasonCode: string;
  evidence: Array<{
    ruleId: string;
    start?: number;
    end?: number;
  }>;
  hintId?: string;
}
```

Il renderer dell’evento converte il risultato nel formato host.

### D-04 — Nessuna scrittura direttamente richiesta dall’hook

`UserPromptSubmit` può al massimo indicare un possibile intento. Non deve mai:

- dichiarare che l’intento sia certo;
- ordinare la chiamata a un tool;
- includere automaticamente il contenuto da persistere;
- considerare l’utilità futura come consenso.

### D-05 — Invalidation-first, delete controllato

Il lifecycle resta:

```text
active → invalidated → deleted
```

La cancellazione fisica è ammessa soltanto da `invalidated`.

## Architettura del piano

```mermaid
flowchart LR
    P["Prompt utente corrente"] --> S["Segmentazione instruction/data"]
    S --> D["Policy deterministiche"]
    D -->|nessuna evidenza| N["Nessun output"]
    D -->|possibile intento| H["Hint condizionale"]

    H --> A["Agente propone operazione esatta"]
    A --> T["Tool mutativo memory-node"]
    T --> G["PreToolUse strutturato"]
    G --> C["Approval mode nel config.toml"]
    C --> M["memory-node"]

    I["Installer Sophia"] --> C
    M --> V["Invalidazione"]
    V --> X["Delete controllato"]
```

## Componenti coinvolti

| Componente | Intervento |
| --- | --- |
| `scripts/hooks/sophia-user-prompt-submit.mjs` | usare testo corrente per intent policy; rimuovere il comando diretto a `memory_add_entry` |
| `scripts/hooks/routing-engine.mjs` | riusare primitive deterministiche; evitare di sovraccaricarlo con parsing host-specific |
| nuovo modulo puro di segmentazione | mappa instruction/data e masking offset-preserving |
| nuovo modulo puro di memory intent | risultato strutturato, reason code, evidenza |
| `scripts/hooks/sophia-pretool-memory.mjs` | analisi strutturata di tool e argomenti; copertura completa dei tool mutativi |
| `scripts/hooks-generator-lib.js` | aggiornare matcher dei tool mutativi, senza allargarli a tutti i read tool |
| `scripts/inject-user-mcp-settings.js` | merge delle policy Codex oltre ai blocchi server |
| `scripts/install-user-runtime.js` | selezione profilo e report conflitti |
| `shared-agent-rules/GLOBAL.md` | conferma obbligatoria e gerarchia fonti |
| `skills/mcp-memory-operator/*` | workflow propose/confirm/execute; delete invalidated-only |
| `memory-node/src/*` | nuovo tool delete e audit |
| test routing/runtime/memory | regressioni e compatibilità |

I nomi dei nuovi moduli sono indicativi. Devono essere scelti seguendo le convenzioni locali prima dell’implementazione.

## Milestone 1 — Segmentazione deterministica del prompt

### Obiettivo

Impedire che codice, citazioni o testo incollato siano interpretati come istruzioni dell’utente.

### Attività

1. Introdurre un modulo puro, ad esempio:

   ```text
   scripts/hooks/prompt-content-segmenter.mjs
   ```

2. Esporre:

   ```ts
   segmentPrompt(text)
   maskNonInstructionRegions(text)
   ```

3. Gestire inizialmente:

   - fenced block con tre o più backtick;
   - fenced block con tre o più tilde;
   - fence con info string;
   - chiusura con stesso carattere e lunghezza almeno pari all’apertura;
   - fence non chiusa: tutto il resto è data plane;
   - inline code;
   - blockquote Markdown.

4. Preservare newline e lunghezza:

   ```text
   carattere escluso → spazio
   newline → newline
   ```

5. Non usare una regex singola non stateful.

6. Mantenere il prompt originale separato.

### Regola sui payload

Un blocco escluso può diventare contenuto candidato soltanto quando un’istruzione esplicita, fuori dal blocco, lo referenzia:

````text
Ricorda questa configurazione:

```toml
[features]
memories = false
```
````

L’intento è nel piano istruttivo; il payload resta nel piano dati.

### Criteri di completamento

- nessun match proveniente esclusivamente da una fence;
- offset e numeri di riga stabili;
- nessuna eccezione su fence non chiuse;
- API senza I/O e testabile isolatamente.

## Milestone 2 — Policy di intento e hint non imperativo

### Obiettivo

Sostituire `matchIntent()` con una decisione esplicabile e prudente.

### Attività

1. Applicare la policy esclusivamente a:

   ```js
   extractCurrentUserSubmissionText(payload)
   ```

   Il testo aggregato può restare temporaneamente per il ranking legacy, ma non deve governare operazioni sensibili.

2. Introdurre condizioni necessarie:

   ```text
   imperativo esplicito
   + oggetto di persistenza
   + match fuori dalle regioni escluse
   + assenza di negazione locale
   + assenza di contesto metalinguistico
   ```

3. Non considerare trigger autonomi:

   ```text
   conserva
   mantieni
   preserva
   persisti
   salva
   store
   keep
   retain
   ```

4. Trattare come evidenza contraria:

   - “non ricordare”;
   - “verifica che ‘ricorda’ non attivi…”;
   - “questo hook dice…”;
   - “esempio”, “fixture”, “test”, “snippet”, “prompt” nella stessa clausola;
   - match in code, quote o blockquote.

5. Restituire reason code stabili, per esempio:

   ```text
   MEM_NO_EXPLICIT_INTENT
   MEM_MATCH_EXCLUDED_REGION
   MEM_NEGATED
   MEM_METALINGUISTIC
   MEM_POSSIBLE_EXPLICIT_INTENT
   ```

6. Formulare l’hint:

   ```text
   Possible explicit persistent-memory intent was detected in the current
   user message outside quoted and code regions.

   Independently verify that the user directly requested future persistence.
   If verified, show the exact content, project scope and operation and obtain
   explicit confirmation before using a mutating memory tool. Otherwise ignore
   this hint.
   ```

7. Non includere `Use memory_add_entry`.

8. Conservare il limite massimo di due hint e la deduplicazione esistente.

### Generalizzazione agli altri hook

Il contratto comune può essere riusato, ma le policy devono essere event-specific:

| Evento | Input autorevole | Strategia |
| --- | --- | --- |
| `UserPromptSubmit` | messaggio utente corrente | segmentazione e intent policy |
| `PreToolUse` | `tool_name`, `tool_input` | analisi strutturata dell’operazione |
| `PostToolUse` | risultato tool | classificazione di esiti, mai intent detection |
| `Stop` | stato di completamento | criteri oggettivi e protezione anti-loop |
| `SessionStart` | contesto di avvio | bootstrap minimo, nessun parsing di intenti |

### Criteri di completamento

- il prompt della regressione non produce hint memoria;
- un comando esplicito fuori da una fence produce soltanto l’hint condizionale;
- l’hint non dichiara un’intenzione certa;
- l’hint non ordina una tool call.

## Milestone 3 — Protezione delle operazioni mutative

### Obiettivo

Fare in modo che un errore del modello non diventi una scrittura silenziosa.

### Attività

1. Refactor di `sophia-pretool-memory.mjs`:

   - leggere il nome tool dal campo host previsto;
   - leggere gli argomenti strutturati;
   - evitare `collectValues()` su tutto il payload;
   - distinguere read e write.

2. Tool mutativi da coprire:

   ```text
   memory_add_entry
   memory_invalidate_entry
   memory_delete_entry
   eventuale memory_update_entry futuro
   ```

3. Aggiornare il matcher in `hooks-generator-lib.js` senza intercettare inutilmente search/read/list/status.

4. Rendere il messaggio coerente:

   ```text
   This is a mutating memory operation. Verify project scope, source,
   duplicate/conflict status, sensitive-data exclusion and explicit user
   confirmation before proceeding.
   ```

5. Aggiornare `GLOBAL.md` e `mcp-memory-operator`:

   - mostrare contenuto esatto;
   - mostrare scope/progetto;
   - mostrare operazione;
   - chiedere conferma;
   - non interpretare un hint come consenso;
   - fonti primarie sempre prevalenti.

### Livello di enforcement

Fase iniziale:

```text
TOML approval = enforcement obbligatorio
PreToolUse = guardrail contestuale
skill/rules = semantica della conferma
```

Una correlazione automatica fra consenso e tool call richiederebbe uno stato turn-scoped affidabile, con `session_id`, `turn_id`, scadenza e anti-replay. Non va simulata finché il contratto host e la persistenza di tale receipt non sono verificati.

## Milestone 4 — Policy Codex gestita dall’installer

### Obiettivo

Configurare memoria nativa e approvazioni MCP con lo stesso modello transazionale già usato per le impostazioni MCP.

### Profilo prudente consigliato

```toml
approvals_reviewer = "user"

[features]
memories = true

[memories]
use_memories = true
generate_memories = false
disable_on_external_context = true

[mcp_servers.memory-mcp-server.tools.memory_add_entry]
approval_mode = "prompt"

[mcp_servers.memory-mcp-server.tools.memory_invalidate_entry]
approval_mode = "prompt"

[mcp_servers.memory-mcp-server.tools.memory_delete_entry]
approval_mode = "prompt"
```

`disable_on_external_context = true` rimane utile come difesa nel caso in cui la generazione venga riabilitata successivamente.

### Profilo auditabile

```toml
[memories]
use_memories = false
generate_memories = false
disable_on_external_context = true
```

In questo profilo non esiste interferenza semantica della memoria nativa durante il lavoro sul progetto.

### Strategia di merge

Estendere `inject-user-mcp-settings.js` con helper puri dedicati, evitando di confondere policy globali e definizioni dei server.

Comportamento predefinito:

- aggiungere chiavi mancanti;
- preservare valori esplicitamente diversi;
- riportare il conflitto nel report;
- non duplicare tabelle;
- fallire su TOML ambiguo o duplicato;
- mantenere backup, temp write e rollback esistenti.

Con `--force` o una selezione esplicita:

- aggiornare soltanto le chiavi gestite da Sophia;
- non sostituire altre impostazioni dell’utente;
- registrare nel report precedente e nuovo valore.

### Possibile seam

```ts
mergeCodexPolicyToml(targetToml, {
  root: {
    approvals_reviewer: 'user'
  },
  tables: {
    features: { memories: true },
    memories: {
      use_memories: true,
      generate_memories: false,
      disable_on_external_context: true
    },
    'mcp_servers.memory-mcp-server.tools.memory_add_entry': {
      approval_mode: 'prompt'
    }
  }
}, {
  overwriteManagedKeys: false
})
```

### Gerarchia delle fonti

Da formalizzare nelle regole:

```text
codice / ticket / documentazione / commit
> MCP memory verificata e project-scoped
> memoria nativa Codex
> inferenze non verificate
```

Questa è una policy semantica, non una priorità tecnica configurabile nel TOML.

## Milestone 5 — Cancellazione dei record invalidati

### Obiettivo

Consentire la rimozione fisica controllata senza indebolire l’auditabilità.

### Contratto proposto

Tool:

```text
memory_delete_entry
```

Input minimo:

```json
{
  "project_path": "/path/to/project",
  "project_id": "optional",
  "entry_id": "entry-uuid",
  "confirm": true,
  "reason": "optional concise reason"
}
```

### Precondizioni

- progetto risolto e isolato;
- entry esistente nello stesso progetto;
- stato corrente esattamente `invalidated`;
- `confirm === true`;
- nessuna cancellazione cross-project implicita;
- operazione transazionale.

### Comportamento

1. leggere stato e metadati minimi;
2. rifiutare record `active`, `archived` o `superseded`;
3. scrivere un audit tombstone senza contenuto sensibile;
4. eliminare relazioni tag e record;
5. verificare l’allineamento dell’indice FTS secondo i trigger/schema esistenti;
6. restituire:

   ```json
   {
     "ok": true,
     "project_id": "...",
     "entry_id": "...",
     "previous_status": "invalidated",
     "deleted": true
   }
   ```

### Scelta consigliata

Non rendere il delete idempotente come successo silenzioso. Una seconda cancellazione dovrebbe restituire un esito controllato `NOT_FOUND`, perché l’assenza può indicare un ID errato o una doppia operazione.

### Aggiornamenti correlati

- tool list e schema MCP;
- tipi;
- audit operation;
- README;
- skill;
- hook matcher;
- configurazione approvazione per-tool;
- test unitari e smoke.

## Milestone 6 — Test, compatibilità e rollout

### Fixture di regressione obbligatoria

Aggiungere una fixture derivata dal prompt che ha causato il falso positivo. Il test deve verificare:

```text
memory hint assente
memory_add_entry assente
nessuna direttiva mutativa
```

Il contenuto può essere sanitizzato soltanto per dati sensibili; la struttura lunga e le parole che hanno causato il rumore devono essere preservate.

### Matrice segmentazione

| Caso | Esito |
| --- | --- |
| `Ricorda che usiamo pnpm` fuori da regioni escluse | hint condizionale |
| stessa frase dentro ``` | nessun hint |
| stessa frase dentro ```` | nessun hint |
| stessa frase dentro `~~~` | nessun hint |
| fence non chiusa | nessun trigger dal resto del testo |
| inline code | nessun hint dal solo inline code |
| blockquote | nessun hint dal solo blockquote |
| `Non ricordare...` | nessun hint |
| `Testa la frase "ricorda..."` | nessun hint |
| `Conserva lo stato diagnostico` | nessun hint |
| istruzione esplicita fuori fence che referenzia il blocco | hint, payload disponibile per proposta |
| match solo in un turno storico | nessun hint |

### Test `PreToolUse`

- add/invalidate/delete vengono riconosciuti;
- search/read/list/status non producono guardrail mutativo;
- tool MCP non correlato non produce output;
- il tool name viene letto strutturalmente;
- payload che cita `memory_add_entry` come dato non viene classificato come chiamata a quel tool.

### Test installer

- inserimento di chiavi mancanti;
- seconda esecuzione invariata;
- conflitto preservato e riportato;
- overwrite limitato alle chiavi gestite con `--force`;
- tabelle preesistenti non duplicate;
- TOML non valido: nessuna scrittura;
- backup e rollback;
- target symlink/hardlink trattati secondo i controlli esistenti;
- dry run senza modifiche;
- separazione fra profilo prudente e auditabile.

### Test delete

- delete di record invalidato;
- rifiuto record attivo;
- rifiuto senza `confirm`;
- isolamento cross-project;
- rimozione da search/list taxonomy;
- indice FTS coerente;
- audit tombstone presente e redatto;
- seconda cancellazione restituisce `NOT_FOUND`;
- smoke stdio con lifecycle add → invalidate → delete.

### Compatibilità

Gli script e i moduli comuni sono riusati dagli adapter Cursor e Antigravity. I test devono quindi dimostrare almeno:

- stesso esito del segmentatore indipendentemente dall’adapter;
- nessun cambiamento del formato host-specific non correlato;
- nessuna perdita dei limiti massimi di hint;
- nessuna regressione su Git, ProjectFS, SQL e ColdFusion routing.

## Criteri di accettazione

### Hook engine

1. Il prompt di regressione non genera alcun hint memoria.
2. Testo dentro code fence, inline code o blockquote non attiva policy di intento.
3. Una fence non chiusa viene trattata in modo fail-safe.
4. Le policy sensibili analizzano soltanto il messaggio utente corrente.
5. Ogni decisione espone `policyId`, `reasonCode` ed evidenza.
6. Il caso normale produce output vuoto.
7. Nessun hint contiene un comando diretto a un tool mutativo.

### Memoria

8. Ogni write MCP richiede approvazione `prompt`.
9. La skill richiede anteprima e conferma esplicita.
10. Fonti primarie prevalgono sempre sulla memoria.
11. `memory_delete_entry` accetta soltanto entry `invalidated`.
12. Il delete lascia un audit tombstone redatto.
13. Search e tassonomia non restituiscono entry cancellate.

### Installer

14. L’iniezione è idempotente.
15. I valori utente divergenti non vengono sovrascritti in modalità predefinita.
16. `--force` modifica soltanto chiavi gestite.
17. Il merge non duplica tabelle TOML.
18. Un errore provoca rollback senza lasciare un target parzialmente scritto.
19. Il report indica profilo applicato, conflitti e chiavi preservate.

### Compatibilità

20. Le suite routing correnti restano verdi dopo l’aggiornamento delle aspettative.
21. Codex, Cursor e Antigravity mantengono i rispettivi contratti di output.
22. Nessuna nuova dipendenza npm è introdotta.

## Validazioni consigliate

Eseguire nell’ordine:

```bash
npm run test:routing:unit
npm run test:routing:engine
npm run test:routing:smoke
npm run test:routing
npm run test:runtime
npm run test:memory
npm run test:affected:unit
```

Gate finale consigliato:

```bash
npm run test:affected -- --strict \
  --base 407677463f1944ffc4d6c1051c0975bb0c4b12be \
  --include test:routing \
  --include test:runtime \
  --include test:memory \
  --include test:affected:unit
```

La baseline del gate va adeguata al commit base effettivo della futura branch di implementazione; lo SHA sopra identifica la baseline di questa analisi, non necessariamente il corretto merge-base futuro.

Non sono stati eseguiti test, build o smoke nell’ambito di questa analisi read-only.

## Rischi e mitigazioni

| Rischio | Impatto | Mitigazione |
| --- | --- | --- |
| Over-filtering di istruzioni legittime dentro una fence | falso negativo | richiedere comando esplicito fuori dalla fence che referenzi il payload |
| Hint ancora interpretato come comando | write non desiderato | formulazione condizionale più approval per-tool |
| Duplicazione fra memoria Codex e MCP | dati divergenti | generazione nativa disabilitata; profilo auditabile con `use_memories=false` |
| Merge TOML line-based fragile | config corrotta | helper limitato, fail-closed, test su commenti/tabelle/duplicati, rollback |
| Hook duplicati da più scope | hint concorrenti | inventario e warning installer; non rimuovere hook estranei senza consenso |
| Delete riduce auditabilità | perdita storica | invalidated-only, conferma, tombstone, approval prompt |
| Cambio router rompe altre skill | regressione ampia | integrazione locale della policy, nessuna riscrittura del ranking |
| Stato di conferma non correlato al turno | falsa garanzia | non introdurre receipt finché il contratto host non è verificato |
| Memoria obsoleta usata come verità | decisione errata | gerarchia fonti e `verification_hint` obbligatorio |

## Punti aperti

1. Stabilire se il profilo prudente debba essere il default installer o una scelta esplicita.
2. Stabilire se `features.memories = true` debba essere aggiunto quando la memoria nativa non è già abilitata.
3. Definire la UX installer per il profilo auditabile.
4. Verificare il formato esatto dei payload `PreToolUse` per tutte le versioni host supportate prima di eliminare i fallback compatibili.
5. Decidere se il delete debba richiedere anche una `reason` obbligatoria.
6. Verificare lo schema SQLite e i trigger FTS correnti prima di definire l’ordine esatto delle DELETE.
7. Stabilire se l’inventario degli hook duplicati debba essere solo warning o bloccare l’installazione.
8. Valutare un dispatcher unico soltanto dopo parity test dei moduli condivisi.

## Handoff implementativo

Sequenza consigliata:

1. introdurre segmentatore e relativi test puri;
2. integrare la sola policy memoria nel `UserPromptSubmit`;
3. aggiornare fixture e smoke;
4. aggiornare regole agente e skill;
5. estendere il merge TOML con profilo prudente;
6. aggiungere approvazione per add/invalidate;
7. implementare `memory_delete_entry`;
8. aggiungere approval e hook matcher per delete;
9. eseguire suite routing, runtime, memory e affected;
10. validare su un profilo Codex temporaneo, mai sulla home reale durante i test.

Deliverable atteso dalla futura implementazione:

- elenco file modificati;
- comportamento precedente e nuovo;
- configurazione TOML applicata;
- casi di test aggiunti;
- comandi eseguiti con risultato reale;
- limiti residui;
- SHA del commit di implementazione.

## Confidenza

- **Alta** sulla causa del falso positivo e sul seam di correzione nel router.
- **Alta** sulla disponibilità del percorso installer transazionale.
- **Alta** sullo stato corrente di invalidazione e assenza del delete nel contratto M2.
- **Media** sulla strategia di enforcement semantico oltre all’approvazione TOML, perché richiede verifica del payload host e di un eventuale stato turn-scoped.
- **Media** sull’estensione line-based del TOML fino alla definizione dei casi ambigui e dei test di compatibilità.
