pi-jev-guard
Jev validation guard for pi: on-demand tool + automatic provider gate. Dual backend: TypeSafe direct + OpenRouter.
Package details
Install pi-jev-guard from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-jev-guard- Package
pi-jev-guard- Version
0.7.2- Published
- Sep 23, 2026
- Downloads
- 1,869/mo · 1,869/wk
- Author
- alucard_24
- License
- unknown
- Types
- extension, skill
- Size
- 273.9 KB
- Dependencies
- 4 dependencies · 3 peers
Pi manifest JSON
{
"skills": [
"./skills"
],
"extensions": [
"./extensions/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-jev-guard
Verifica le risposte con TypeSafe Jev dentro pi: un solo motore di validazione, due interfacce.
- A richiesta (default): tool
jev_validate, comando/jev check, skilljev-review. Zero verifiche implicite, zero costi se non lo usi. - Domande tipate: tool
jev_askper giudizi calibrati definiti dal modello (noul/choice/score) invece di prosa. - Automatica: in
automaticil gate copre il modello selezionato e ogni cambio modello, senza alias o registrazioni extra: trattiene la risposta, la verifica con Jev e pubblica solo l'output approvato (con rigenerazione privata sublock). Stessa auth del provider: nessun login extra, funziona anche con Codex/OAuth. - Giudice output (solo
automatic, fail-open): dopo ognibashcerca secret nel testo e classifica i fallimenti, allegando un consiglio al risultato. - Verifica progetto (opt-in): footer deterministico da
edit/writeosservati e check autorizzati da override locale, manifest globale utente o profilo comune integrato; il modello può eseguire soltanto quegli id, mai shell arbitraria.
Installazione
cd pi-jev-guard
npm install
mkdir -p ~/.pi/agent
cp config/jev-config.example.json ~/.pi/agent/jev-config.json
pi install "$PWD"
Chiavi (a seconda del backend Jev scelto):
export OPENROUTER_API_KEY="sk-or-v1-..." # backend openrouter (default)
export TYPESAFE_API_KEY="..." # backend typesafe diretto
Uso normale (invariato)
Le nuove sessioni partono in on-demand: i modelli normali restano selezionabili e nessuna verifica parte da sola.
/jev mode automatic|on-demand salva la scelta nella sessione, non nella config globale.
La scelta sopravvive a /reload, riavvio e /resume; fork e /tree seguono lo stato del ramo.
Credenziali e policy restano condivise.
Migrazione: il vecchio mode in jev-config.json non controlla più l'estensione
(resta compatibile con i consumer standalone). Nelle sessioni senza uno stato salvato,
riattiva automatic una volta se desiderato. JEV_MODE=automatic può impostare il valore
iniziale in headless; una scelta già salvata nella sessione ha precedenza.
/jev check ./src/example.ts # verifica singola di un file
/jev status # stato completo
/jev help # tutti i sottocomandi
In chat, l'LLM può chiamare jev_validate per controlli mirati.
Uso protetto
/model # scegli qualunque modello (o più modelli in sessioni diverse)
/jev mode automatic # ogni risposta passa dal gate Jev
/jev off # gate disattivato, provider ripristinati
Nessun alias __jev, nessuna registrazione: il gate lavora sullo stesso
oggetto provider e riusa la credenziale già configurata (env, stored,
OAuth/SSO come Codex business plan). I vecchi alias delle versioni ≤ 0.6.x
vengono normalizzati automaticamente ai modelli originali.
Backend e chiavi
Due backend, stessa policy e stesse regole:
| Backend | Endpoint | Variabile | Modello | Timeout |
|---|---|---|---|---|
openrouter (default) |
OpenRouter | OPENROUTER_API_KEY |
typesafe/jev-1.13 |
4000 ms |
typesafe |
SDK ufficiale @typesafe-ai/sdk → api.typesafe.ai |
TYPESAFE_API_KEY |
jev-1.13.0 |
1500 ms |
auto |
sceglie il backend che ha una chiave (entrambe → OpenRouter) | — | — | — |
/jev backend # stato: backend, modello, chiavi rilevate
/jev backend typesafe # cambia backend (salvato in jev-config.json)
/jev save-key typesafe # salva la chiave del backend (file 600)
/jev save-key openrouter # l'altra chiave resta dov'è
/jev key-file # dove viene cercata la chiave
Le chiavi stanno in file separati (jev-api-key.<backend>.txt accanto alla
config), quindi i due backend possono coesistere. Precedenza: variabile
d'ambiente → file del backend → file generico jev.apiKeyFile → percorso
canonico. Vedi config/jev-config.example.json.
Qualunque modello: in automatic il gate segue la selezione — cambi
modello con /model e ogni risposta resta coperta, senza passaggi di setup.
Il catalogo resta quello di pi: nessun alias, nessun modulo extra nel picker.
Torna normale con /jev mode on-demand (o /jev off, che ripristina anche i
metodi originali dei provider). Entrambe le scelte vivono nella sessione e
sopravvivono a /reload e /resume.
L'installazione punta alla cartella: dopo un aggiornamento del codice basta /reload.
Headless/CI: JEV_MODE=automatic parte già col gate attivo sul modello usato.
Un hold [JEV — OUTPUT NON PUBBLICATO] interrompe intenzionalmente il turno:
controlla /jev last. Non viene aggirato con un proseguimento automatico.
Verdetto incerto (review): il gate tenta prima una riparazione privata
(automatic.repairOnReview, default true), poi applica la policy configurata:
policy.onUncertain e policy.onUnavailable ("hold" default, oppure "pass").
Con "pass" il testo viene pubblicato con una nota di trasparenza sul verdetto.
Se un'altra estensione gestisce lo stesso provider (caso reale: pi-accounts
con overlay auth su openai-codex), il gate NON ri-registra nulla: applica
una patch in-place sull'oggetto provider live (stessa identità, stessa config
del proprietario). Così i controlli di ownership altrui non vedono mai una
"configuration changed" e non armano abort dei turni (This operation was aborted istantaneo). Quando il proprietario sostituisce l'oggetto, il nuovo
viene patchato ex-novo agli hook (input, before_agent_start, turn_start,
model_select, message_end); /jev off ripristina i metodi originali senza
unregister (jev-overlay-reassert solo quando un oggetto nuovo viene patchato).
Rete di sicurezza legacy: se un id __jev delle vecchie versioni sfugge nel
payload, viene normalizzato al modello originale registrando jev-gate-bypass,
perché quel turno non è passato dalla verifica.
Le conferme per comandi di rete sospetti attendono invece una decisione esplicita;
la normale sequenza tool → risposta successiva continua senza un nuovo prompt.
Come decide
Jev risponde a domande noul (probabilità 0–1 di "sì, c'è la falla"):
| Regola | Gate automatic | On-demand |
|---|---|---|
sql_injection |
✓ | ✓ |
unsafe_destructive_action |
✓ | ✓ |
requirement_conflict |
— (requisiti chat troppo vaghi) | ✓ (requisiti espliciti) |
Soglie preliminari calibrate live (docs/calibration-2026-09-19.md):
p ≤ 0.20 pass · p ≥ 0.90 block · in mezzo review (trattenuto) ·
errori/timeout → unavailable (trattenuto). Mai approvazione su input troncato:
un pass parziale diventa review dichiarata. I candidati lunghi sono verificati
a chunk (copertura completa); i requisiti oltre 16k trattengono con nota.
In automatic è attiva anche una tool policy deterministica (costo zero):
blocca comandi distruttivi (rm -rf /, fork bomb, mkfs, dd su device…)
e scritture su path sensibili (.env, .ssh/, *.pem, node_modules/).
In on-demand non blocca nulla. Sempre in automatic, i comandi con tool
di rete (curl, scp, ssh…) passano un check semantico Jev
(destructive/exfiltration/beyond_scope/impact): su flag chiede conferma
in TUI, in headless solo avviso (fail-open).
Sempre in automatic, il giudice output esamina i risultati bash
(1 chiamata Jev per output nuovo, con cache 120s): se trova un secret
avvisa e dice di riferirsi al valore per nome; se è un errore, allega il
consiglio per la classe (transient → riprova, code_bug → fixa il codice…).
Non blocca mai; /jev output mostra l'ultimo verdetto.
Sempre in automatic, il grounding (opt-in, default spento) confronta le
affermazioni sulla sessione — "ho letto il file", "i test passano", "ho
eseguito X", "il guard riporta X" — con un registro evidenza costruito dai
tool_result e dai fatti generati dal guard (footer di verifica, run
jev_verify)
(comandi, test, letture, modifiche; redatto, max 30 voci, solo sessione
corrente). Due domande Jev strette: contraddizione con l'evidenza e
affermazione non supportata. Senza evidenza non si giudica: "senza
evidenza" non significa "falso". Una modifica riuscita invalida i test
precedenti (stale). Tre modalità (/jev grounding off|warn|repair|hold):
warn pubblica con nota, repair rigenera una volta, hold trattiene solo
le contraddizioni ad alta confidenza. Fail-open: se il verificatore non
risponde, il testo passa senza nota. /jev last mostra anche l'esito
grounding (warned/repaired/held).
Verifica progetto deterministica (opt-in)
Il grounding è probabilistico; per compilazione, lint e test serve una
prova deterministica. La verifica progetto conserva, solo nella sessione,
edit/write riusciti e gli esiti osservati dei check. Il footer viene
generato dall'estensione, non dal modello: un test non eseguito non può
diventare “test passati”. Un report di “verifica” scritto dal modello non ha
valore: il footer autorevole è solo quello del guard (marcato generata dal guard, non dal modello) e una guideline ai tool scoraggia le imitazioni.
Nuovi progetti: zero manifest locale
Una volta, in una sessione pi, abilita la modalità scelta:
/jev verification repair
Da quel momento ogni progetto usa questa precedenza:
.pi/jev-verification.jsonlocale, se presente;verification.globalManifestPath, se l'hai configurato nella config utente;- profilo integrato
common(default).
Il profilo common non legge comandi dal repository: abilita esclusivamente
comandi fissi dell'estensione quando trova segnali convenzionali:
| Rilevamento | Check disponibili |
|---|---|
package.json con script |
npm run typecheck, npm run lint, uno tra npm run test:unit, npm run test:ci, npm test |
Cargo.toml |
cargo check, cargo test |
go.mod |
go test ./... |
*.sln / *.csproj (root o 2 livelli) |
dotnet build, dotnet test |
| configurazione pytest | python -m pytest |
| repository Git | git diff --check |
Il profilo sceglie un solo ecosistema (Node → Rust → Go → .NET → Python) e aggiunge
il check Git quando applicabile. I comandi sono bounded da
verification.maxCommands (default 4) e timeout. Se nessun segnale è
rilevato, non esegue nulla e il footer dichiara la limitazione.
Dopo un edit il modello può scegliere solo id già acquisiti:
/jev verify recommended # check pertinenti non ancora freschi
/jev verify all # tutti, fino a verification.maxCommands
/jev verify node-typecheck # un id esplicito della policy corrente
Il tool LLM jev_verify ha lo stesso vincolo, richiede un progetto trusted e
non accetta shell arbitraria. Footer/repair/hold operano in automatic;
/jev verify è utilizzabile manualmente anche senza footer.
Override per progetti speciali
Per una pipeline specifica, aggiungi un manifest al progetto: prevale sempre sul profilo globale.
mkdir -p .pi
cp config/jev-verification.example.json .pi/jev-verification.json
Controllalo tu, poi acquisiscilo (e ripeti dopo ogni modifica manuale):
/jev verification reload
In alternativa puoi definire una policy comune per tutti i tuoi progetti nella config utente, purché esista davvero e sia sotto il tuo controllo:
{
"verification": {
"globalManifestPath": "~/.pi/agent/jev-verification.global.json",
"defaultProfile": "common"
}
}
Un globalManifestPath configurato ma assente o malformato non degrada
silenziosamente al profilo integrato: la verifica segnala l'errore. Per
disattivare il fallback integrato imposta "defaultProfile": "off".
/jev verification e /jev status mostrano l'origine effettiva della policy.
Manifest e profilo sono acquisiti a inizio sessione, all'attivazione esplicita
o con /jev verification reload. Se un manifest, un package.json o un file
di configurazione che abilita il profilo cambia dopo l'acquisizione, nessun
check parte fino al reload utente. In automatic, con tool policy e verifica
attive, write/edit del modello su tali file sono bloccati; una modifica via shell
viene comunque rilevata dal fingerprint. Questo evita che il modello trasformi
uno script o un manifest in un nuovo comando autorizzato.
Modalità: warn aggiunge il footer; repair rigenera una volta con feedback
che chiede jev_verify; hold trattiene dopo una failure concreta, o dopo il
tentativo bounded se restano check mancanti. Nessun check pertinente non è un
fallimento del codice e non produce hold. Le modifiche rilevate restano solo
quelle di edit/write: una modifica shell non viene attribuita al modello.
Configurazione
~/.pi/agent/jev-config.json (o $JEV_CONFIG). Env: JEV_MODE, JEV_BACKEND
(openrouter|typesafe|auto), JEV_MODEL.
Vedi config/jev-config.example.json per tutti i campi.
Chiave Jev (ordine: env vince sul file): OPENROUTER_API_KEY o
TYPESAFE_API_KEY, altrimenti jev.apiKeyFile (es.
"~/.pi/agent/jev-api-key.txt", ~/ espanso, solo prima riga, permessi
600 consigliati). /jev status mostra la sorgente (env:VAR,
file:<path>, o il motivo se assente) — mai il valore.
Per salvare la chiave stando dentro pi (senza passarla come argomento, che resterebbe in history e transcript):
/jev save-key # chiede la chiave via dialogo, la scrive a 600, ricarica
Nota: il dialogo TUI potrebbe fare echo nel terminale; per massima
paranoia usa la shell: umask 077 && cat > ~/.pi/agent/jev-api-key.txt.
I verdetti identici sono riusati per 120s (reviewCache, mai gli
unavailable): retry e batch paralleli costano una sola chiamata.
Gli input oltre i limiti sono marcati …[N chars elided] nel testo inviato
a Jev, mai troncati in silenzio.
Retry solo su transienti (jev.retryTransients, default 1 retry): 429/5xx
ed errori di connessione ritentano con backoff, timeout e auth mai — un
rate-limit non diventa più subito hold. /jev last mostra l'ultimo
verdetto del gate (esito, tentativi, controllo con p, backend, tempo).
Sviluppo
npm run typecheck
npm run test:unit # mock, nessun costo
npm run test:integration
RUN_JEV_LIVE=1 npm run bench:jev # corpus live (costa poco)
echo '{"requirements":"...","candidate":"..."}' | npm run jev-check
Limiti onesti
pass= "supera i controlli configurati", non "corretto". Compilazione e test restano necessari.- Il gate copre i turni che passano dal provider patchato in
automatic; se un provider non è patchato (raro: sostituzione concorrente) il turno passa con una notajev-guarded/diagnostica dichiarata. - Soglie calibrate su 20 casi (
docs/calibration-2026-09-19.md): buone per iniziare, da rivalutare con corpus più ampio. - Jev è un giudice probabilistico, non un verificatore formale.
- Il grounding controlla solo affermazioni verificabili sulla sessione (comandi, file, test, modifiche): niente fact-check di fatti esterni, e con contesti lunghi l'evidenza oltre budget viene elisa.
- La verifica progetto dimostra solo i check dichiarati ed eseguiti dopo gli
edit/writeosservati; non è una prova formale di correttezza, non vede modifiche effettuate via shell e non sostituisce review umana.