> ## Documentation Index
> Fetch the complete documentation index at: https://exosphere-auto-translate-docs-20260624-1149.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Policy Personalizzate

> Scrivi le tue policy in JavaScript - applica convenzioni, previeni deviazioni, rileva errori, integrati con sistemi esterni

Le policy personalizzate ti permettono di scrivere regole per qualsiasi comportamento dell'agente: applicare convenzioni di progetto, prevenire deviazioni, bloccare operazioni distruttive, rilevare agenti bloccati, o integrarti con Slack, workflow di approvazione e altro ancora. Utilizzano lo stesso sistema di hook event e le stesse decisioni `allow`, `deny`, `instruct` delle policy integrate.

***

## Esempio rapido

```js theme={null}
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";

customPolicies.add({
  name: "no-production-writes",
  description: "Block writes to paths containing 'production'",
  match: { events: ["PreToolUse"] },
  fn: async (ctx) => {
    if (ctx.toolName !== "Write" && ctx.toolName !== "Edit") return allow();
    const path = ctx.toolInput?.file_path ?? "";
    if (path.includes("production")) {
      return deny("Writes to production paths are blocked");
    }
    return allow();
  },
});
```

Installalo:

```bash theme={null}
failproofai policies --install --custom ./my-policies.js
```

***

## Due modi per caricare policy personalizzate

### Opzione 1: Basata su convenzione (consigliato)

Inserisci file `*policies.{js,mjs,ts}` in `.failproofai/policies/` e verranno caricati automaticamente — nessun flag o cambio di configurazione necessario. Funziona come i git hooks: inserisci un file e basta.

```
# Livello di progetto — committato su git, condiviso con il team
.failproofai/policies/security-policies.mjs
.failproofai/policies/workflow-policies.mjs

# Livello utente — personale, si applica a tutti i progetti
~/.failproofai/policies/my-policies.mjs
```

**Come funziona:**

* Entrambe le directory di progetto e utente vengono scansionate (unione — non first-scope-wins)
* I file vengono caricati alfabeticamente all'interno di ogni directory. Utilizza il prefisso `01-`, `02-` per controllare l'ordine
* Vengono caricati solo i file che corrispondono a `*policies.{js,mjs,ts}`; gli altri file vengono ignorati
* Ogni file viene caricato in modo indipendente (fail-open per file)
* Funziona insieme alle policy `--custom` esplicite e alle policy integrate

<Tip>
  Le policy di convenzione sono il modo più semplice per costruire uno standard di qualità per la tua organizzazione. Committi `.failproofai/policies/` su git e ogni membro del team otterrà automaticamente le stesse regole — nessuna configurazione per sviluppatore necessaria. Mentre il tuo team scopre nuovi modi di fallimento, aggiungi una policy e fai il push. Nel tempo questi diventano uno standard di qualità dinamico che continua a migliorare con ogni contributo.
</Tip>

### Opzione 2: Percorso file esplicito

```bash theme={null}
# Installa con un file di policy personalizzate
failproofai policies --install --custom ./my-policies.js

# Sostituisci il percorso del file di policy
failproofai policies --install --custom ./new-policies.js

# Rimuovi il percorso delle policy personalizzate dalla configurazione
failproofai policies --uninstall --custom
```

Il percorso assoluto risolto viene memorizzato in `policies-config.json` come `customPoliciesPath`. Il file viene caricato fresh su ogni hook event - non c'è caching tra gli eventi.

### Utilizzare entrambi insieme

Le policy di convenzione e il file `--custom` esplicito possono coesistere. Ordine di caricamento:

1. File `customPoliciesPath` esplicito (se configurato)
2. File di convenzione di progetto (`{cwd}/.failproofai/policies/`, alfabetico)
3. File di convenzione utente (`~/.failproofai/policies/`, alfabetico)

***

## API

### Import

```js theme={null}
import { customPolicies, allow, deny, instruct } from "failproofai";
```

### `customPolicies.add(hook)`

Registra una policy. Chiama questa funzione tutte le volte necessarie per più policy nello stesso file.

```ts theme={null}
customPolicies.add({
  name: string;                         // required - unique identifier
  description?: string;                 // shown in `failproofai policies` output
  match?: { events?: HookEventType[] }; // filter by event type; omit to match all
  fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
});
```

### Helper per decisioni

| Funzione            | Effetto                               | Usare quando                                               |
| ------------------- | ------------------------------------- | ---------------------------------------------------------- |
| `allow()`           | Permetti l'operazione silenziosamente | L'azione è sicura, nessun messaggio necessario             |
| `deny(message)`     | Blocca l'operazione                   | L'agente non dovrebbe eseguire questa azione               |
| `instruct(message)` | Aggiungi contesto senza bloccare      | Dai all'agente contesto aggiuntivo per rimanere in traccia |

`deny(message)` - il messaggio appare a Claude con prefisso `"Blocked by failproofai:"`. Un singolo `deny` cortocircuita tutta la valutazione successiva.

`instruct(message)` - il messaggio viene aggiunto al contesto di Claude per la chiamata dello strumento corrente. Tutti i messaggi `instruct` vengono accumulati e consegnati insieme.

<Tip>
  Puoi aggiungere guidance extra a qualsiasi messaggio `deny` o `instruct` aggiungendo un campo `hint` in `policyParams` — nessun cambio di codice necessario. Questo funziona anche per le policy personalizzate (`custom/`), di convenzione di progetto (`.failproofai-project/`), e di convenzione utente (`.failproofai-user/`). Vedi [Configuration → hint](/it/configuration#hint-cross-cutting) per i dettagli.
</Tip>

### Messaggi allow informativi

`allow(message)` permette l'operazione **e** invia un messaggio informativo indietro a Claude. Il messaggio viene consegnato come `additionalContext` nella risposta stdout del gestore hook — lo stesso meccanismo utilizzato da `instruct`, ma semanticamente diverso: è un aggiornamento di stato, non un avvertimento.

| Funzione         | Effetto                            | Usare quando                                                                      |
| ---------------- | ---------------------------------- | --------------------------------------------------------------------------------- |
| `allow(message)` | Permetti e invia contesto a Claude | Conferma che un controllo è passato, o spiega perché un controllo è stato saltato |

Casi d'uso:

* **Conferme di stato:** `allow("All CI checks passed.")` — dice a Claude che tutto è verde
* **Spiegazioni fail-open:** `allow("GitHub CLI not installed, skipping CI check.")` — dice a Claude perché un controllo è stato saltato così ha il contesto completo
* **Più messaggi si accumulano:** se più policy restituiscono ciascuna `allow(message)`, tutti i messaggi vengono uniti con newline e consegnati insieme

```js theme={null}
customPolicies.add({
  name: "confirm-branch-status",
  match: { events: ["Stop"] },
  fn: async (ctx) => {
    const cwd = ctx.session?.cwd;
    if (!cwd) return allow("No working directory, skipping branch check.");

    // ... check branch status ...
    if (allPushed) {
      return allow("Branch is up to date with remote.");
    }
    return deny("Unpushed changes detected.");
  },
});
```

### Campi `PolicyContext`

| Campo       | Tipo                                   | Descrizione                                                          |
| ----------- | -------------------------------------- | -------------------------------------------------------------------- |
| `eventType` | `string`                               | `"PreToolUse"`, `"PostToolUse"`, `"Notification"`, `"Stop"`          |
| `toolName`  | `string \| undefined`                  | Lo strumento in fase di chiamata (es. `"Bash"`, `"Write"`, `"Read"`) |
| `toolInput` | `Record<string, unknown> \| undefined` | I parametri di input dello strumento                                 |
| `payload`   | `Record<string, unknown>`              | Payload evento grezzo completo da Claude Code                        |
| `session`   | `SessionMetadata \| undefined`         | Contesto sessione (vedi sotto)                                       |

### Campi `SessionMetadata`

| Campo            | Tipo     | Descrizione                                       |
| ---------------- | -------- | ------------------------------------------------- |
| `sessionId`      | `string` | Identificatore sessione Claude Code               |
| `cwd`            | `string` | Directory di lavoro della sessione Claude Code    |
| `transcriptPath` | `string` | Percorso del file transcript JSONL della sessione |

### Tipi di evento

| Evento         | Quando si attiva                      | Contenuti `toolInput`                                                                                                                                        |
| -------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `PreToolUse`   | Prima che Claude esegua uno strumento | L'input dello strumento (es. `{ command: "..." }` per Bash)                                                                                                  |
| `PostToolUse`  | Dopo che uno strumento si completa    | L'input dello strumento + `tool_result` (l'output)                                                                                                           |
| `Notification` | Quando Claude invia una notifica      | `{ message: "...", notification_type: "idle" \| "permission_prompt" \| ... }` - i hook devono sempre restituire `allow()`, non possono bloccare le notifiche |
| `Stop`         | Quando la sessione Claude termina     | Vuoto                                                                                                                                                        |

***

## Ordine di valutazione

Le policy vengono valutate in questo ordine:

1. Policy integrate (in ordine di definizione)
2. Policy personalizzate esplicite da `customPoliciesPath` (in ordine `.add()`)
3. Policy di convenzione da `.failproofai/policies/` di progetto (file alfabetici, ordine `.add()` all'interno)
4. Policy di convenzione da `~/.failproofai/policies/` utente (file alfabetici, ordine `.add()` all'interno)

<Note>
  Il primo `deny` cortocircuita tutte le policy successive. Tutti i messaggi `instruct` vengono accumulati e consegnati insieme.
</Note>

***

## Import transitivi

I file di policy personalizzate possono importare moduli locali utilizzando percorsi relativi:

```js theme={null}
// my-policies.js
import { isBlockedPath } from "./utils.js";
import { checkApproval } from "./approval-client.js";

customPolicies.add({
  name: "approval-gate",
  fn: async (ctx) => {
    if (ctx.toolName !== "Bash") return allow();
    const approved = await checkApproval(ctx.toolInput?.command, ctx.session?.sessionId);
    return approved ? allow() : deny("Approval required for this command");
  },
});
```

Tutti gli import relativi raggiungibili dal file di ingresso vengono risolti. Questo viene implementato riscrivendo gli import `from "failproofai"` al percorso dist effettivo e creando file `.mjs` temporanei per garantire la compatibilità ESM.

***

## Filtraggio per tipo di evento

Usa `match.events` per limitare quando una policy si attiva:

```js theme={null}
customPolicies.add({
  name: "require-summary-on-stop",
  match: { events: ["Stop"] },
  fn: async (ctx) => {
    // Si attiva solo quando la sessione termina
    // ctx.session.transcriptPath contiene il log di sessione completo
    return allow();
  },
});
```

Ometti `match` completamente per attivarsi su ogni tipo di evento.

***

## Gestione degli errori e modalità di fallimento

Le policy personalizzate sono **fail-open**: gli errori non bloccano mai le policy integrate o fanno crashare il gestore hook.

| Errore                                  | Comportamento                                                                                                                 |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `customPoliciesPath` non impostato      | Nessuna policy personalizzata esplicita viene eseguita; le policy di convenzione e le policy integrate continuano normalmente |
| File non trovato                        | Avvertimento registrato in `~/.failproofai/hook.log`; le policy integrate continuano                                          |
| Errore di sintassi/import (esplicito)   | Errore registrato in `~/.failproofai/hook.log`; le policy personalizzate esplicite vengono saltate                            |
| Errore di sintassi/import (convenzione) | Errore registrato; quel file viene saltato, gli altri file di convenzione continuano comunque a caricarsi                     |
| `fn` lancia un'eccezione a runtime      | Errore registrato; questo hook viene trattato come `allow`; gli altri hook continuano                                         |
| `fn` impiega più di 10s                 | Timeout registrato; trattato come `allow`                                                                                     |
| Directory di convenzione mancante       | Nessuna policy di convenzione viene eseguita; nessun errore                                                                   |

<Tip>
  Per eseguire il debug degli errori di policy personalizzate, osserva il file di log:

  ```bash theme={null}
  tail -f ~/.failproofai/hook.log
  ```
</Tip>

***

## Esempio completo: multiple policy

```js theme={null}
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";

// Prevent agent from writing to secrets/ directory
customPolicies.add({
  name: "block-secrets-dir",
  description: "Prevent agent from writing to secrets/ directory",
  match: { events: ["PreToolUse"] },
  fn: async (ctx) => {
    if (!["Write", "Edit"].includes(ctx.toolName ?? "")) return allow();
    const path = ctx.toolInput?.file_path ?? "";
    if (path.includes("secrets/")) return deny("Writing to secrets/ is not permitted");
    return allow();
  },
});

// Keep the agent on track: verify tests before committing
customPolicies.add({
  name: "remind-test-before-commit",
  description: "Keep the agent on track: verify tests pass before committing",
  match: { events: ["PreToolUse"] },
  fn: async (ctx) => {
    if (ctx.toolName !== "Bash") return allow();
    const cmd = ctx.toolInput?.command ?? "";
    if (/git\s+commit/.test(cmd)) {
      return instruct("Verify all tests pass before committing. Run `bun test` if you haven't already.");
    }
    return allow();
  },
});

// Prevent unplanned dependency changes during freeze
customPolicies.add({
  name: "dependency-freeze",
  description: "Prevent unplanned dependency changes during freeze period",
  match: { events: ["PreToolUse"] },
  fn: async (ctx) => {
    if (ctx.toolName !== "Bash") return allow();
    const cmd = ctx.toolInput?.command ?? "";
    const isInstall = /^(npm install|yarn add|bun add|pnpm add)\s+\S/.test(cmd);
    if (isInstall && process.env.DEPENDENCY_FREEZE === "1") {
      return deny("Package installs are frozen. Unset DEPENDENCY_FREEZE to allow.");
    }
    return allow();
  },
});

export { customPolicies };
```

***

## Esempi

La directory `examples/` contiene file di policy pronti per l'uso:

| File                                                 | Contenuti                                                                                               |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `examples/policies-basic.js`                         | Cinque policy iniziali che coprono i comuni modi di fallimento dell'agente                              |
| `examples/policies-advanced/index.js`                | Pattern avanzati: import transitivi, chiamate asincrone, scrubbing dell'output, e hook di fine sessione |
| `examples/convention-policies/security-policies.mjs` | Policy di convenzione sulla sicurezza (blocca scritture .env, previeni riscrittura della storia git)    |
| `examples/convention-policies/workflow-policies.mjs` | Policy di convenzione sul workflow (reminder di test, audit delle scritture di file)                    |

### Utilizzare esempi di file espliciti

```bash theme={null}
failproofai policies --install --custom ./examples/policies-basic.js
```

### Utilizzare esempi basati su convenzione

```bash theme={null}
# Copia a livello di progetto
mkdir -p .failproofai/policies
cp examples/convention-policies/*.mjs .failproofai/policies/

# O copia a livello di utente
mkdir -p ~/.failproofai/policies
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
```

Nessun comando di installazione necessario — i file vengono racccolti automaticamente al prossimo hook event.
