> ## Documentation Index
> Fetch the complete documentation index at: https://docs.befailproof.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Politiche personalizzate

> Scrivi le tue regole in JavaScript - applica convenzioni, previeni derive, rileva fallimenti, integrati con sistemi esterni

Le politiche personalizzate ti permettono di scrivere regole per qualsiasi comportamento di agenti: applicare convenzioni di progetto, prevenire derive, bloccare operazioni distruttive, rilevare agenti bloccati, o integrarsi con Slack, flussi di approvazione e altro ancora. Utilizzano lo stesso sistema di eventi hook e le decisioni `allow`, `deny`, `instruct` delle politiche incorporate.

***

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

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

Rilascia file `*policies.{js,mjs,ts}` in `.failproofai/policies/` e vengono caricati automaticamente — non sono necessari flag o modifiche di configurazione. Funziona come git hooks: rilascia un file e funziona.

```
# Livello di progetto — committato a 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. Usa il prefisso `01-`, `02-` per controllare l'ordine
* Solo i file corrispondenti a `*policies.{js,mjs,ts}` vengono caricati; gli altri file vengono ignorati
* Ogni file viene caricato indipendentemente (fail-open per file)
* Funziona insieme a `--custom` espliciti e politiche incorporate

<Tip>
  Le politiche di convenzione sono il modo più semplice per costruire uno standard di qualità per la tua organizzazione. Committa `.failproofai/policies/` a git e ogni membro del team ottiene automaticamente le stesse regole — nessuna configurazione per sviluppatore necessaria. Man mano che il tuo team scopre nuove modalità di fallimento, aggiungi una politica e fai il push. Nel tempo questi diventano uno standard di qualità vivo che continua a migliorare con ogni contributo.
</Tip>

### Opzione 2: Percorso file esplicito

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

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

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

Il percorso assoluto risolto viene archiviato in `policies-config.json` come `customPoliciesPath`. Il file viene caricato nuovamente ad ogni evento hook — non c'è caching tra gli eventi.

### Usare entrambi insieme

Le politiche 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/`, alfabetici)
3. File di convenzione utente (`~/.failproofai/policies/`, alfabetici)

***

## API

### Importazione

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

### `customPolicies.add(hook)`

Registra una politica. Chiamala tutte le volte che è necessario per più politiche 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                               | Usa quando                                                       |
| ------------------- | ------------------------------------- | ---------------------------------------------------------------- |
| `allow()`           | Consenti l'operazione silenziosamente | L'azione è sicura, nessun messaggio necessario                   |
| `deny(message)`     | Blocca l'operazione                   | L'agente non dovrebbe intraprendere questa azione                |
| `instruct(message)` | Aggiungi contesto senza bloccare      | Dai all'agente contesto aggiuntivo per stare sulla giusta strada |

`deny(message)` - il messaggio appare a Claude con il prefisso `"Blocked by failproofai:"`. Un singolo `deny` fa cortocircuito su 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 una guida aggiuntiva a qualsiasi messaggio `deny` o `instruct` aggiungendo un campo `hint` in `policyParams` — nessuna modifica del codice necessaria. Questo funziona anche per le politiche 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)` consente l'operazione **e** invia un messaggio informativo 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 avviso.

| Funzione         | Effetto                            | Usa quando                                                                        |
| ---------------- | ---------------------------------- | --------------------------------------------------------------------------------- |
| `allow(message)` | Consenti 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.")` — comunica a Claude che tutto è verde
* **Spiegazioni fail-open:** `allow("GitHub CLI not installed, skipping CI check.")` — comunica a Claude perché un controllo è stato saltato in modo che abbia il contesto completo
* **Più messaggi si accumulano:** se più politiche restituiscono `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 chiamato (ad es. `"Bash"`, `"Write"`, `"Read"`) |
| `toolInput` | `Record<string, unknown> \| undefined` | I parametri di input dello strumento                         |
| `payload`   | `Record<string, unknown>`              | Payload di evento completo grezzo da Claude Code             |
| `session`   | `SessionMetadata \| undefined`         | Contesto di sessione (vedi sotto)                            |

### Campi `SessionMetadata`

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

### Tipi di evento

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

***

## Ordine di valutazione

Le politiche vengono valutate in questo ordine:

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

<Note>
  Il primo `deny` fa cortocircuito su tutte le politiche successive. Tutti i messaggi `instruct` vengono accumulati e consegnati insieme.
</Note>

***

## Importazioni transitive

I file di politiche personalizzate possono importare moduli locali usando 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");
  },
});
```

Tutte le importazioni relative raggiungibili dal file di entry vengono risolte. Questo viene implementato riscrivendo le importazioni `from "failproofai"` al percorso dist effettivo e creando file `.mjs` temporanei per garantire compatibilità ESM.

***

## Filtraggio dei tipi di evento

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

```js theme={null}
customPolicies.add({
  name: "require-summary-on-stop",
  match: { events: ["Stop"] },
  fn: async (ctx) => {
    // Only fires when the session ends
    // ctx.session.transcriptPath contains the full session log
    return allow();
  },
});
```

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

***

## Gestione degli errori e modalità di fallimento

Le politiche personalizzate sono **fail-open**: gli errori non bloccano mai le politiche incorporate o fanno bloccare il gestore hook.

| Fallimento                                    | Comportamento                                                                                                             |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `customPoliciesPath` non impostato            | Nessuna politica personalizzata esplicita viene eseguita; le politiche di convenzione e i built-in continuano normalmente |
| File non trovato                              | Avviso registrato in `~/.failproofai/hook.log`; i built-in continuano                                                     |
| Errore di sintassi/importazione (esplicito)   | Errore registrato in `~/.failproofai/hook.log`; le politiche personalizzate esplicite vengono saltate                     |
| Errore di sintassi/importazione (convenzione) | Errore registrato; quel file saltato, gli altri file di convenzione continuano a caricarsi                                |
| `fn` genera un errore a runtime               | Errore registrato; questo hook trattato come `allow`; gli altri hook continuano                                           |
| `fn` richiede più di 10s                      | Timeout registrato; trattato come `allow`                                                                                 |
| Directory di convenzione mancante             | Nessuna politica di convenzione viene eseguita; nessun errore                                                             |

<Tip>
  Per eseguire il debug degli errori delle politiche personalizzate, osserva il file di registro:

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

***

## Esempio completo: più politiche

```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 politiche pronti all'uso:

| File                                                 | Contenuti                                                                                                       |
| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `examples/policies-basic.js`                         | Cinque politiche di avvio che coprono modalità di fallimento comuni degli agenti                                |
| `examples/policies-advanced/index.js`                | Modelli avanzati: importazioni transitive, chiamate asincrone, scrubbing dell'output, e hook di fine sessione   |
| `examples/convention-policies/security-policies.mjs` | Politiche di sicurezza basate su convenzione (blocca scritture .env, previeni riscrittura della cronologia git) |
| `examples/convention-policies/workflow-policies.mjs` | Politiche di flusso di lavoro basate su convenzione (promemoria dei test, file di audit writes)                 |

### Utilizzo di esempi di file espliciti

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

### Utilizzo di esempi basati su convenzione

```bash theme={null}
# Copy to project level
mkdir -p .failproofai/policies
cp examples/convention-policies/*.mjs .failproofai/policies/

# Or copy to user level
mkdir -p ~/.failproofai/policies
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
```

Nessun comando di installazione necessario — i file vengono prelevati automaticamente al prossimo evento hook.
