CtrlK
BlogDocsLog inGet started
Tessl Logo

spec-driven-development/spec-as-source

Spec-driven development on OpenSpec, with mechanical spec-as-source enforcement: a custom 'spec-as-source' OpenSpec schema adds file-ownership (targets) and test-verification ([@test]) metadata to every capability spec, three scripts (link check, ownership check, manifest build) keep code and specs from drifting apart, plus requirement-gathering, spec-writer, work-review, and a session-handoff skill with a proactive context-warning hook and a packaged handoff memory: the skill ships the exporter, importer, graph model, facts pipeline, Neo4j Compose runtime and operating guide to load handoffs into a local, authenticated Neo4j graph and query them.

68

Quality

85%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

SKILL.mdskills/handoff/

name:
handoff
description:
Gestisce il sistema di passaggio di consegne tra sessioni AI per qualsiasi progetto. Crea, aggiorna e legge file HANDOFF-N.md nella cartella .handoff/ del progetto, mantenendo una knowledge base persistente con documentazione (CLAUDE.md, PROMPTS.md, CLIENTS.md, WORKFLOW.md). Usa questa skill ogni volta che l'utente vuole: - Salvare lo stato ("crea handoff", "salva lo stato", "facciamo il punto", "chiudiamo la sessione", "riprendiamo domani", "passaggio di consegne", "freeze the context", "save state") - Riprendere da una sessione precedente ("riprendi da dove eravamo", "carica handoff", "resume", "continua da HANDOFF", "cosa avevamo fatto") - Inizializzare la knowledge base di un nuovo progetto ("/handoff init") - Aggiornare la documentazione persistente (CLAUDE.md, PROMPTS.md, CLIENTS.md, WORKFLOW.md) Suggerisci proattivamente la creazione di un handoff dopo sessioni lunghe con modifiche importanti, debugging complessi, o decisioni architetturali significative.

Handoff — Sistema di Knowledge Base Persistente

Questo sistema mantiene tutta la memoria del progetto nella cartella .handoff/, strutturata per permettere a qualsiasi agente AI (o operatore umano) di riprendere il lavoro senza perdere contesto tra sessioni.


Struttura della cartella .handoff/

.handoff/
├── HANDOFF-001.md       ← prima sessione
├── HANDOFF-002.md       ← seconda sessione (legge il precedente)
├── HANDOFF-NNN.md       ← sessione corrente (sempre il numero più alto)
├── HISTORY.md           ← diario continuo append-only (vedi rule history-log)
├── CLAUDE.md            ← istruzioni persistenti per Claude Code
├── PROMPTS.md           ← libreria prompt riutilizzabili
├── CLIENTS.md           ← schede clienti attivi
└── WORKFLOW.md          ← metodologia TheNewA(i)telier

Regola fondamentale: gli HANDOFF-NNN.md sono append-only — non si modificano mai le sessioni passate. Si aggiorna solo creando un nuovo file numerato.


Comandi riconosciuti

Frase utenteAzione
/handoff initInizializza .handoff/ nel progetto corrente
/handoff save o "crea handoff"Crea nuovo HANDOFF-NNN.md
/handoff load o "riprendi"Legge l'ultimo handoff + context docs
/handoff update [doc]Aggiorna CLAUDE.md / PROMPTS.md / CLIENTS.md / WORKFLOW.md
/handoff statusMostra lista handoff esistenti con date
/handoff install-hookInstalla l'hook PreCompact (Workflow E, Claude Code)

Workflow A — INIT (primo avvio su un progetto)

Eseguire quando .handoff/ non esiste ancora.

Step 1 — Crea la struttura

mkdir -p .handoff

Step 2 — Crea i documenti persistenti con scaffolding

Leggere references/init-templates.md per i template di partenza di ciascun file (CLAUDE.md, PROMPTS.md, CLIENTS.md, WORKFLOW.md). Creare tutti e 4 nella cartella .handoff/ con il contenuto scaffold appropriato al progetto rilevato dal contesto della conversazione.

Step 2b — Crea il diario continuo HISTORY.md

Creare .handoff/HISTORY.md vuoto (nessuno scaffold necessario — è un log append-only, vedi la rule history-log per il formato delle righe che vi verranno scritte da qui in avanti).

Step 3 — Crea il primo HANDOFF-001.md

Seguire il Workflow B (SAVE) per creare HANDOFF-001.md con le informazioni disponibili al momento dell'init.

Step 4 — Aggiungi .handoff/ al progetto

Se esiste un .gitignore, suggerire all'utente se vuole committare .handoff/ o escluderlo. Raccomandazione: committarlo — è documentazione di progetto.


Workflow B — SAVE (crea nuovo handoff)

Step 1 — Determina il numero progressivo

ls .handoff/HANDOFF-*.md 2>/dev/null | sort | tail -1

Se non esiste nessun file → creare HANDOFF-001.md. Se esiste l'ultimo → incrementare di 1 (es. HANDOFF-007.md → HANDOFF-008.md).

Step 2 — Leggi l'ultimo handoff (se esiste)

Prima di scrivere, leggere l'ultimo HANDOFF-NNN.md per capire cosa era in sospeso e non contraddire la storia. I Next Steps dell'handoff precedente diventano la base della sezione Current Progress del nuovo.

Step 3 — Scrivi il nuovo HANDOFF-NNN.md

Prima il frontmatter, validato. Il file apre con il frontmatter YAML descritto in references/handoff-template.md § Frontmatter strutturato: handoff, project_id, date (ISO con fuso), continues, agent_session, parent_session, operator: {person, provider, models}, client, work_context, track, plan_entry, change, deadline. Con openspec/PLAN.md presente, plan_entry e change si leggono dal piano ora. Scrivi prima la bozza in un file temporaneo nella stessa cartella e validala:

python3 <skill>/scripts/graph_export.py --check-only --as HANDOFF-NNN.md .handoff/.HANDOFF-NNN.draft.md

Se esce diverso da 0 (manca project_id, data non ISO o senza fuso, continues verso un file inesistente, a sé stesso o al futuro, campi mancanti o di tipo sbagliato) correggi la bozza e non pubblicare lo snapshot: il salvataggio non è riuscito. Solo con esito 0 rinomina la bozza in .handoff/HANDOFF-NNN.md.

Usare la struttura esatta in references/handoff-template.md. Le 6 sezioni obbligatorie — 7 se il progetto ha openspec/PLAN.md (era: 5 sezioni, 6 con un piano) — sono:

  1. 📍 Posizione nel piano — solo con un piano presente, subito dopo il Goal. Voce corrente (id, titolo, stato), cosa si sta facendo per avvicinare il done-when del piano, e quali voci restano aperte. Si compila leggendo openspec/PLAN.md adesso, non ricordandolo: apri il file e riporta gli stati che ci trovi. Una posizione scritta a memoria è sbagliata esattamente come un timestamp indovinato, e molto più difficile da notare. Vale la stessa disciplina anti-invenzione della rule history-log.
  2. 🎯 Goal — Obiettivo finale del progetto (stabile tra sessioni).
  3. 🔄 Stato volatile — I comandi che producono conteggi, stati, numeri di commit, task aperti, esiti di test e del gate. Mai il valore congelato. Un numero scritto qui invecchia fra il salvataggio e la lettura, e spesso è già sbagliato quando lo scrivi: "16 commit locali" lo era, perché non contava il commit dell'handoff stesso. Chi legge deve poterli rigenerare, non ereditare. Regola operativa: ogni conteggio citato altrove nel documento ha qui il comando che lo rigenera.
  4. ✅ Current Progress — Checklist di fatto/non fatto con nomi file specifici.
  5. 💡 What Worked — Approcci vincenti con dettaglio tecnico esatto (prompt, parametri, comandi). Il perché conta quanto il cosa.
  6. ❌ What Didn't Work — Errori e vicoli ciechi. Mai lasciare vuota: salva tempo al prossimo agente. Se davvero nulla è fallito: "Nessun vicolo cieco rilevante."
  7. 🚀 Next Steps — Lista numerata, concreta, azionabile. Item #1 eseguibile subito senza domande.

Regole di scrittura:

  • Lingua del contenuto = lingua della conversazione (italiano se l'utente parla italiano)
  • Titoli sezioni in inglese (portabilità cross-tool)
  • Contenuto estratto dalla conversazione reale, mai generici
  • Quando c'è una decisione stabile o un fatto riutilizzabile, scrivilo nella sezione esistente più adatta con il prefisso Decision: o Fact:; non inventare voci mancanti. L'export Neo4j legge solo queste righe esplicite e le voci numerate di Next Steps.
  • Zero segreti (API key, password, token): referenziarli come "→ vedi .env"
  • Fatti stabili (decisioni, motivazioni, What Worked, What Didn't Work) in prosa, come sempre: non invecchiano, e sono la parte che si trasferisce intatta.
  • Fatti volatili mai come valore congelato: vanno nella sezione 🔄 Stato volatile sotto forma di comando. Unica eccezione, se nessun comando li può rigenerare, il valore datato — (al YYYY-MM-DD HH:MM — riverificare).
  • Puntatori: ogni affermazione sul contenuto di un file si cita come file § sezione, mai come riassunto senza fonte. Il numero di riga può accompagnare il titolo della sezione, non sostituirlo. Un riassunto senza fonte costringe chi legge a ricostruire, e una ricostruzione inventa: da "contraddice ROUTER.md" è nata la citazione di una sezione inesistente.

Step 3b — Consolida HISTORY.md

Subito dopo aver scritto HANDOFF-NNN.md, appendere a .handoff/HISTORY.md (se esiste — crearlo prima se .handoff/ esiste ma HISTORY.md no, come da rule history-log) una riga marker in fondo al file, usando il numero dello snapshot appena scritto:

--- consolidated up to HANDOFF-NNN ---

Questa riga non cancella né riscrive nulla sopra di sé — HISTORY.md resta append-only esattamente come gli HANDOFF-NNN.md. Segna solo il confine da cui il prossimo Workflow C (LOAD) riparte a leggere.

Step 3c — Esporta il sidecar Neo4j

Dopo aver scritto HANDOFF-NNN.md, invocare lo script scripts/graph_export.py bundled con questa skill in profilo nuovo, passando il path dell'handoff: python3 <skill>/scripts/graph_export.py --new .handoff/HANDOFF-NNN.md. Lo script crea e valida .handoff/HANDOFF-NNN.graph.json in schema v2: metadati del frontmatter, provenienza della cartella sorgente e i record. Esporta solo righe esplicite Decision: e Fact:, gli item numerati in Next Steps e, come failure, le voci significative di What Didn't Work (non la frase "nessun vicolo cieco" né gli esempi in blocchi di codice), con provenienza alla sezione Markdown. La sintassi resta leggibile nel documento normale; non trascrivere dialoghi o credenziali nel sidecar.

Se l'export o la validazione fallisce, non dichiarare il salvataggio completo e non cancellare il Markdown. Comunica il nome dell'handoff e l'errore generico restituito dallo script; dopo aver risolto la causa, riesegui lo stesso exporter sullo stesso .md per rigenerare il sidecar mantenendo gli stessi ID.

Step 4 — Quality check

Prima di finalizzare:

  • Tutte 6 le sezioni compilate con contenuto reale (7 con un piano presente)
  • Header metadata con data, sessione, operatore
  • Frontmatter strutturato presente e validato con --check-only prima dello snapshot
  • Sidecar .graph.json presente e validato accanto al Markdown (schema v2)
  • Nessun fatto volatile scritto come valore congelato: ogni conteggio citato nel documento ha il suo comando in 🔄 Stato volatile
  • Ogni affermazione sul contenuto di un file cita file § sezione, non un riassunto senza fonte
  • Next Steps numerati e il primo è eseguibile senza domande
  • Con un piano presente: nessuna voce legata a un change già sotto openspec/changes/archive/ è rimasta diversa da done. È la stessa staleness che riporta scripts/check-plan-gate.sh. Segnalala, non bloccare il salvataggio: perdere lo stato di una sessione per far rispettare l'igiene del piano scambia la cosa più preziosa con la meno preziosa. Il giudizio bloccante resta al gate.
  • Nessuna credenziale nel testo

Step 4b — Import automatico nella memoria

Dopo export e quality check, eseguire sul Markdown appena salvato:

PY=~/.venvs/handoff-memory/bin/python
[ -x "$PY" ] || PY=python3
"$PY" <skill>/scripts/import_handoff_graph.py import-saved .handoff/HANDOFF-NNN.md

Il venv è quello di references/local-handoff-memory.md, con le dipendenze runtime/requirements.txt. Il fallback python3 senza driver conserva comunque una coda locale durevole. Il comando legge prima NEO4J_PASSWORD, altrimenti ~/.config/handoff-memory/neo4j-password, senza stampare credenziali.

Exit 0: comunicare imported oppure da importare, insieme al conteggio pending; anche un database spento o una password assente permettono il save. Exit 1 (input/export non valido) o 3 (coda non salvabile): segnalare il fallimento della finalizzazione, mantenendo Markdown e sidecar. Non dichiarare il salvataggio completato. Un commit riuscito con acknowledgement fallito viene segnalato come tale: la voce resta disponibile per retry idempotente.

La coda è privata, mai versionata; il comando per recuperarla senza conoscere i path è "$PY" <skill>/scripts/import_handoff_graph.py import-pending.

Step 5 — Notifica

Comunicare il path esatto del file creato e come riprendere:

✅ Salvato: .handoff/HANDOFF-003.md
Memoria: imported; pending 0
# oppure: Memoria: da importare; pending <conteggio>

Per riprendere in una nuova sessione Claude Code:
→ claude (apri una nuova sessione)
→ "Leggi .handoff/HANDOFF-003.md e riprendi da dove eravamo"

Workflow C — LOAD (ripresa da sessione precedente)

Step 1 — Trova l'ultimo handoff

ls .handoff/HANDOFF-*.md | sort | tail -1

Step 2 — Leggi in ordine

  1. Leggi l'ultimo HANDOFF-NNN.md completamente.
  2. Leggi .handoff/CLAUDE.md — contiene istruzioni operative persistenti.
  3. Se openspec/PLAN.md esiste, leggilo: è la sorgente della sequenza del lavoro, e l'handoff ne è solo la fotografia al momento dello snapshot. Da qui prendi il goal:, il done-when: e gli stati reali delle voci — se la sezione "📍 Posizione nel piano" dell'handoff dice altro, il piano vince: è stato scritto dopo. Se il file non esiste non è un errore: è un progetto che non usa plan-mode, procedi con gli altri documenti.
  4. Se .handoff/HISTORY.md esiste, leggi solo le righe dopo l'ultimo marker --- consolidated up to HANDOFF-NNN --- — non l'intero file dall'inizio. Se il file non contiene nessun marker (mai consolidato), trattalo per intero come non consolidato: non è un errore, è solo un progetto la cui prima consolidazione non è ancora avvenuta.
  5. Se qualcosa è ambiguo, leggi il penultimo handoff. Non leggere tutta la chain di default.

Step 2b — Riverifica i fatti volatili (prima di riportarli)

Prima di dire qualsiasi cosa all'utente, esegui il blocco della sezione 🔄 Stato volatile dell'handoff appena letto e prendi i valori da lì, non dal testo del documento. Se la sezione non c'è (handoff scritti prima di questa convenzione), usa il blocco minimo:

git log --oneline origin/main..HEAD | wc -l        # commit non pushati
bash scripts/verify.sh | tail -2                   # test verdi/rossi
bash scripts/check-plan-gate.sh                    # stato del gate
grep -c '^- \[ \]' openspec/changes/*/tasks.md     # task aperti per change

Due regole, entrambe non negoziabili:

  • Quando un valore riletto contraddice l'handoff, il disco vince. Stessa ragione per cui il piano vince sulla sua copia nell'handoff: è stato scritto dopo. Un handoff che dice "16 commit" e un git log che ne conta 17 non sono un'ambiguità da segnalare, sono un numero vecchio e uno vero.
  • Un comando che fallisce o non si applica a questo progetto non è un errore. Non tutti i progetti hanno verify.sh, un remote o un piano. Salta e prosegui, non trattarlo come una condizione di stop.

Step 3 — Conferma comprensione

Rispondi in 3-4 righe: obiettivo, punto di avanzamento, prossima azione. Non recitare il documento — dimostrare di aver capito.

Ogni numero che compare in questa risposta deve venire dallo Step 2b, mai dal testo dell'handoff. Ripetere un conteggio letto nel documento senza averlo riverificato è il modo esatto in cui un dato sbagliato sopravvive a un passaggio di consegne: è già successo, con "16 commit locali" riportati intatti da un agente che aveva il repository davanti.

Con un piano presente, "punto di avanzamento" significa la voce corrente: id, titolo e stato, e cosa la fa avanzare. Un riassunto che racconta l'ultima sessione senza dire a quale voce del piano appartiene non ha dimostrato di aver capito dove siamo — ha dimostrato di aver letto l'handoff.

Step 4 — Parti dal Next Step #1

Esegui subito il primo passo. Non re-interrogare l'utente su cose già documentate nell'handoff. Tratta What Didn't Work come vincoli rigidi: non riprovare approcci già falliti salvo istruzione esplicita dell'utente.


Workflow D — UPDATE DOCS

Quando l'utente vuole aggiornare uno dei documenti persistenti:

  • CLAUDE.md — nuove istruzioni operative, preferenze di stile, regole del progetto
  • PROMPTS.md — aggiungere prompt validati dalla sessione corrente
  • CLIENTS.md — aggiornare scheda cliente, aggiungere nuovo cliente
  • WORKFLOW.md — aggiornare la metodologia

Leggere prima il file esistente, fare un update chirurgico (non riscrivere da zero), e confermare le righe modificate/aggiunte all'utente.


Workflow E — Install proactive context-warning hook (Claude Code, opzionale)

Esegui una sola volta per progetto, su richiesta dell'utente o durante spec-as-source-setup. Installa un hook reale PreCompact che avvisa automaticamente prima che Claude Code compatti il contesto (cioè quando il contesto si avvicina davvero al limite) — il trigger deterministico più vicino a "contesto vicino a 300k" disponibile oggi in Claude Code. Per ambienti/agenti diversi da Claude Code, vale solo la rule soft handoff-suggestion (non richiede installazione).

Step 1 — Leggi l'eventuale .claude/settings.json esistente

test -f .claude/settings.json && cat .claude/settings.json || echo "(non esiste ancora)"

Step 2 — Fondi l'hook, non sovrascrivere

Leggi templates/claude-settings-hooks.json in questa skill. Se .claude/settings.json non esiste, crealo con esattamente quel contenuto. Se esiste già:

  • se non ha la chiave hooks.PreCompact, aggiungi l'intero blocco PreCompact da templates/claude-settings-hooks.json;
  • se ha già hooks.PreCompact, appendi l'oggetto hook del template all'array esistente — non sostituire gli hook già presenti.

Non scrivere mai un .claude/settings.json che cancelli configurazione preesistente (altri hook, permessi, ecc.).

Step 3 — Conferma

cat .claude/settings.json

Riporta all'utente: "Hook PreCompact installato — riceverai un avviso prima di ogni compattazione automatica del contesto."


Workflow F — Memoria handoff (Neo4j locale, opzionale)

Gli handoff restano la fonte canonica e si leggono senza nulla di installato. La memoria handoff è un indice derivato e ricostruibile: carica i sidecar .graph.json (o i facts .facts.json) in un Neo4j Community locale e autenticato, per navigare decisioni, fatti, prossimi passi e fallimenti per progetto, sessione, handoff, cliente o contesto di lavoro. Tutto ciò che serve sta in questa skill: scripts/ (exporter, importer, motore del modello, pipeline dei facts), runtime/ (Compose e requisito del driver) e references/ (modello del grafo, schemi, guida).

Usala quando l'utente chiede di interrogare lo storico degli handoff ("cosa avevamo deciso su…", "quali fallimenti in questo contesto", "catena di continuazione"), di importare gli handoff in Neo4j o di ricostruire il grafo. Workflow B tenta automaticamente l’import dopo un save valido; il database può essere spento: il handoff resta in coda e il Markdown permette la ripresa.

Prerequisiti: Docker con Compose, Python 3.10+, un venv fuori dal repository con runtime/requirements.txt (unica dipendenza: neo4j==6.3.0). <skill> qui sotto è la cartella di questa skill: la stessa che la guida chiama HANDOFF_SKILL. I comandi si lanciano dalla cartella del progetto (quella con .handoff/).

# avvio richiede la password in ambiente; solo import-saved/import-pending usano il file locale
read -rs -p 'Neo4j password: ' NEO4J_PASSWORD; echo; export NEO4J_PASSWORD
docker compose -f <skill>/runtime/compose.yaml up -d
# import (validate è offline e non richiede il driver)
python3 <skill>/scripts/import_handoff_graph.py validate .handoff
~/.venvs/handoff-memory/bin/python <skill>/scripts/import_handoff_graph.py import .handoff
# query: Neo4j Browser su http://127.0.0.1:7474 con le query documentate

La procedura completa — venv, readiness, query per progetto/sessione/handoff/ cliente/contesto, facts e relazioni derivate da IA, rebuild, stop/start e ripristino — è in references/local-handoff-memory.md. Non usare mai down -v sul progetto handoff-memory senza volerne cancellare il volume.


Note per Claude Code

  • In Claude Code, usa bash per creare/leggere file .handoff/ direttamente nel filesystem del progetto.
  • Il file .handoff/CLAUDE.md può essere aggiunto al contesto di Claude Code come file sempre caricato (con @.handoff/CLAUDE.md all'inizio della sessione).
  • Questa skill è bundled in questo plugin (skills/handoff/); se installata anche globalmente in ~/.claude/skills/handoff/, le due copie sono indipendenti — aggiornarle separatamente.
  • Se .handoff/ non esiste e l'utente chiede di salvare, offrire di fare init prima.
  • Il contesto si avvicina al limite (compattazione imminente)? Suggerire subito /handoff save, anche senza che l'utente lo chieda — vedi la rule handoff-suggestion per il trigger automatico.

README.md

tile.json