@marcomigozzi/trailhead 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.it.md +142 -29
- package/README.md +141 -28
- package/bin/base-preflight-docs.test.js +65 -0
- package/bin/execute-split-docs.test.js +146 -0
- package/bin/isolation-answer-docs.test.js +41 -0
- package/bin/isolation-copy-docs.test.js +28 -0
- package/bin/lib/codex-projection.js +17 -10
- package/bin/lib/codex-projection.test.js +80 -11
- package/bin/lib/install-verify.js +10 -5
- package/bin/lib/install-verify.test.js +51 -0
- package/bin/report-status-docs.test.js +195 -0
- package/bin/resolve-helpers-docs.test.js +36 -0
- package/bin/scope-confirm-skip-docs.test.js +70 -0
- package/bin/trailhead.js +40 -28
- package/bin/trailhead.test.js +503 -6
- package/bin/uat-setup-docs.test.js +65 -0
- package/package.json +4 -1
- package/plugins/trailhead/.claude-plugin/plugin.json +3 -2
- package/plugins/trailhead/agents/trailhead-code-review.md +15 -2
- package/plugins/trailhead/agents/trailhead-codebase-map.md +20 -1
- package/plugins/trailhead/agents/trailhead-debug.md +20 -1
- package/plugins/trailhead/agents/trailhead-executor.md +29 -2
- package/plugins/trailhead/agents/trailhead-fix.md +29 -2
- package/plugins/trailhead/agents/trailhead-plan.md +20 -1
- package/plugins/trailhead/agents/trailhead-research.md +22 -3
- package/plugins/trailhead/agents/trailhead-verify.md +15 -2
- package/plugins/trailhead/commands/panel.md +10 -0
- package/plugins/trailhead/hooks/hooks.json +3 -18
- package/plugins/trailhead/hooks/lib/base-preflight.test.js +513 -0
- package/plugins/trailhead/hooks/lib/body-sources.js +795 -0
- package/plugins/trailhead/hooks/lib/commit-message-check.js +1 -1
- package/plugins/trailhead/hooks/lib/commit-message-check.test.js +3 -2
- package/plugins/trailhead/hooks/lib/commit-msg-module-repo.test.js +116 -0
- package/plugins/trailhead/hooks/lib/commit-msg-sync.test.js +100 -9
- package/plugins/trailhead/hooks/lib/dashboard.test.js +409 -0
- package/plugins/trailhead/hooks/lib/fixtures/commit-msg-legacy-js +104 -0
- package/plugins/trailhead/hooks/lib/gh-subcommand.js +92 -10
- package/plugins/trailhead/hooks/lib/gh-subcommand.test.js +55 -0
- package/plugins/trailhead/hooks/lib/isolation-answer.test.js +258 -0
- package/plugins/trailhead/hooks/lib/isolation-copy.test.js +298 -0
- package/plugins/trailhead/hooks/lib/issue-body.test.js +470 -0
- package/plugins/trailhead/hooks/lib/mockup-link.js +21 -5
- package/plugins/trailhead/hooks/lib/report-status.test.js +366 -0
- package/plugins/trailhead/hooks/lib/shell-scan.js +532 -65
- package/plugins/trailhead/hooks/lib/shell-scan.test.js +434 -0
- package/plugins/trailhead/hooks/lib/uat-backfill.test.js +150 -0
- package/plugins/trailhead/hooks/lib/uat-setup.test.js +340 -0
- package/plugins/trailhead/hooks/lib/unmodelled.js +345 -0
- package/plugins/trailhead/hooks/lib/unmodelled.test.js +173 -0
- package/plugins/trailhead/hooks/lib/work-state.test.js +297 -0
- package/plugins/trailhead/hooks/mod/README.md +219 -0
- package/plugins/trailhead/hooks/mod/map-pane-view.ts +606 -0
- package/plugins/trailhead/hooks/mod/map-pane.tsx +832 -0
- package/plugins/trailhead/hooks/mod/register.tsx +293 -0
- package/plugins/trailhead/hooks/mod/work-state-prompt.ts +69 -0
- package/plugins/trailhead/hooks/mod/work-state-view.ts +110 -0
- package/plugins/trailhead/hooks/trailhead-bash-guards.js +140 -0
- package/plugins/trailhead/hooks/trailhead-bash-guards.test.js +233 -0
- package/plugins/trailhead/hooks/trailhead-body-guard.js +145 -61
- package/plugins/trailhead/hooks/trailhead-body-guard.test.js +224 -3
- package/plugins/trailhead/hooks/trailhead-commit-guard.js +41 -14
- package/plugins/trailhead/hooks/trailhead-commit-guard.test.js +2 -1
- package/plugins/trailhead/hooks/trailhead-install-guard.js +187 -42
- package/plugins/trailhead/hooks/trailhead-install-guard.test.js +182 -2
- package/plugins/trailhead/hooks/trailhead-mockup-link-guard.js +48 -11
- package/plugins/trailhead/hooks/trailhead-mockup-link-guard.test.js +75 -3
- package/plugins/trailhead/hooks/trailhead-search-guard.js +59 -13
- package/plugins/trailhead/hooks/trailhead-search-guard.test.js +68 -3
- package/plugins/trailhead/hooks/trailhead-secret-guard.js +541 -57
- package/plugins/trailhead/hooks/trailhead-secret-guard.test.js +1000 -4
- package/plugins/trailhead/hooks/trailhead-secret-read-guard.js +171 -6
- package/plugins/trailhead/hooks/trailhead-secret-read-guard.test.js +170 -0
- package/plugins/trailhead/skills/_shared/choices.md +7 -3
- package/plugins/trailhead/skills/_shared/configuration-reference.md +15 -3
- package/plugins/trailhead/skills/_shared/load-first.md +3 -3
- package/plugins/trailhead/skills/_shared/multi-map.md +3 -3
- package/plugins/trailhead/skills/_shared/session-handoff.md +1 -1
- package/plugins/trailhead/skills/_shared/substrate-commands.md +22 -11
- package/plugins/trailhead/skills/_shared/substrate.md +6 -4
- package/plugins/trailhead/skills/_shared/teamwork.md +17 -6
- package/plugins/trailhead/skills/_shared/techniques/acceptance-testing.md +17 -9
- package/plugins/trailhead/skills/_shared/techniques/code-review.md +1 -1
- package/plugins/trailhead/skills/_shared/techniques/codebase-map.md +1 -1
- package/plugins/trailhead/skills/_shared/techniques/debug.md +2 -0
- package/plugins/trailhead/skills/_shared/techniques/prototype.md +1 -1
- package/plugins/trailhead/skills/_shared/techniques/research.md +4 -2
- package/plugins/trailhead/skills/_shared/techniques/verify.md +1 -1
- package/plugins/trailhead/skills/_shared/techniques.md +12 -2
- package/plugins/trailhead/skills/trailhead/SKILL.md +3 -3
- package/plugins/trailhead/skills/trailhead-capture/SKILL.md +1 -1
- package/plugins/trailhead/skills/trailhead-capture/references/capture.md +2 -2
- package/plugins/trailhead/skills/trailhead-chart/SKILL.md +1 -1
- package/plugins/trailhead/skills/trailhead-chart/references/charting.md +1 -1
- package/plugins/trailhead/skills/trailhead-manage/SKILL.md +1 -1
- package/plugins/trailhead/skills/trailhead-manage/references/auditing.md +1 -1
- package/plugins/trailhead/skills/trailhead-view/SKILL.md +8 -6
- package/plugins/trailhead/skills/trailhead-work/SKILL.md +16 -13
- package/plugins/trailhead/skills/trailhead-work/references/auto.md +6 -4
- package/plugins/trailhead/skills/trailhead-work/references/executor-brief.md +29 -0
- package/plugins/trailhead/skills/trailhead-work/references/ticket-engines.md +28 -10
- package/plugins/trailhead/templates/trailhead-base-preflight.js +305 -0
- package/plugins/trailhead/templates/trailhead-commit-msg +38 -102
- package/plugins/trailhead/templates/trailhead-commit-msg-sync.js +58 -27
- package/plugins/trailhead/templates/trailhead-commit-msg.cjs +114 -0
- package/plugins/trailhead/templates/trailhead-dashboard.js +340 -0
- package/plugins/trailhead/templates/trailhead-isolation-answer.js +227 -0
- package/plugins/trailhead/templates/trailhead-isolation-copy.js +239 -0
- package/plugins/trailhead/templates/trailhead-issue-body.js +459 -0
- package/plugins/trailhead/templates/trailhead-report-status.js +274 -0
- package/plugins/trailhead/templates/trailhead-uat-backfill.js +114 -0
- package/plugins/trailhead/templates/trailhead-uat-setup.js +385 -0
- package/plugins/trailhead/templates/trailhead-work-state.js +217 -0
- package/plugins/trailhead/tests/map-pane-ui.test.ts +1921 -0
- package/plugins/trailhead/tests/map-pane-view.test.ts +853 -0
- package/plugins/trailhead/tests/mod.test.ts +14 -0
- package/plugins/trailhead/tests/work-state-prompt-hook.test.ts +207 -0
- package/plugins/trailhead/tests/work-state-prompt.test.ts +109 -0
- package/plugins/trailhead/tests/work-state-ui.test.ts +365 -0
- package/plugins/trailhead/tests/work-state-view.test.ts +110 -0
- package/plugins/trailhead/types/index.d.ts +103 -0
package/README.it.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
🇬🇧 [English](README.md) · 🇮🇹 **Italiano**
|
|
8
8
|
|
|
9
|
-
[](https://trailhead.marcomigozzi.it) [](https://github.com/ToRvaLDz/trailhead/actions/workflows/site-ci.yml) [](https://www.npmjs.com/package/@marcomigozzi/trailhead) [](LICENSE)  ](https://trailhead.marcomigozzi.it) [](https://github.com/ToRvaLDz/trailhead/actions/workflows/site-ci.yml) [](https://www.npmjs.com/package/@marcomigozzi/trailhead) [](LICENSE)   
|
|
10
10
|
|
|
11
11
|
</div>
|
|
12
12
|
|
|
@@ -24,9 +24,9 @@ Due approcci al lavoro di progetto guidato dagli agenti risolvono ciascuno una m
|
|
|
24
24
|
|
|
25
25
|
- **GSD** (il workflow system [open-gsd](https://github.com/open-gsd/gsd-core)) è brillante nel *fare*. Il suo ciclo `discuss → plan → execute → verify`, i commit atomici e la cattura senza attrito rendono la costruzione vera e propria affidabile e revisionabile. Ma il suo stato vive in un albero locale `.planning/`, separato da dove il team può vederlo.
|
|
26
26
|
|
|
27
|
-
Lavorando su entrambi, uno schema continuava a ripresentarsi: **usa una mappa e un onboarding in stile Wayfinder per decidere la forma del lavoro, poi un motore in stile GSD per costruire ogni pezzo, senza mai lasciare l'issue tracker.** `trailhead` è quello schema trasformato in un
|
|
27
|
+
Lavorando su entrambi, uno schema continuava a ripresentarsi: **usa una mappa e un onboarding in stile Wayfinder per decidere la forma del lavoro, poi un motore in stile GSD per costruire ogni pezzo, senza mai lasciare l'issue tracker.** `trailhead` è quello schema trasformato in un insieme di skill a cluster coesi su un core condiviso, una sua interpretazione autonoma di entrambe le idee anziché un wrapper attorno all'una o all'altra.
|
|
28
28
|
|
|
29
|
-
> **trailhead è self-contained** nel senso che ha **zero dipendenze da plugin esterni**: gli agent di trailhead e i built-in dell'host vanno bene, e nessun'altra skill o plugin è richiesta. Wayfinder e GSD sono *ispirazione*, non dipendenze. Ogni tecnica che quei sistemi impacchettano come skill separata (grilling, TDD, debugging sistematico, codebase mapping, code review) è **integrata qui come protocollo inline**. Il core di trailhead non invoca nessun'altra skill; ogni tecnica del motore dispatcha al **proprio agent `trailhead-*`** (`trailhead-executor`, `trailhead-plan`, `trailhead-research`, `trailhead-code-review`, `trailhead-debug`, più `trailhead-fix` e `trailhead-codebase-map`), scritto una volta come file `agents/trailhead-*.md` versionato e **proiettato su ogni host** (su Codex diventa `~/.codex/agents/trailhead-*.toml` generato dalla stessa sorgente). Questi agent sono **thin** (identità + tool policy + un modello guidato dalla config, con il protocollo della tecnica iniettato allo spawn) e girano sul toolkit di subagent nativo dell'host (il tool `Agent` integrato di Claude Code, oppure il toolkit `multi_agent` di Codex). L'unica cosa da installare è trailhead stesso. C'è un'unica eccezione opt-in:
|
|
29
|
+
> **trailhead è self-contained** nel senso che ha **zero dipendenze da plugin esterni**: gli agent di trailhead e i built-in dell'host vanno bene, e nessun'altra skill o plugin è richiesta. Wayfinder e GSD sono *ispirazione*, non dipendenze. Ogni tecnica che quei sistemi impacchettano come skill separata (grilling, TDD, debugging sistematico, codebase mapping, code review) è **integrata qui come protocollo inline**. Il core di trailhead non invoca nessun'altra skill; ogni tecnica del motore dispatcha al **proprio agent `trailhead-*`** (`trailhead-executor`, `trailhead-plan`, `trailhead-research`, `trailhead-code-review`, `trailhead-debug`, più `trailhead-fix` e `trailhead-codebase-map`), scritto una volta come file `agents/trailhead-*.md` versionato e **proiettato su ogni host** (su Codex diventa `~/.codex/agents/trailhead-*.toml` generato dalla stessa sorgente). Questi agent sono **thin** (identità + tool policy + un modello guidato dalla config, con il protocollo della tecnica iniettato allo spawn) e girano sul toolkit di subagent nativo dell'host (il tool `Agent` integrato di Claude Code, oppure il toolkit `multi_agent` di Codex). L'unica cosa da installare è trailhead stesso. C'è un'unica eccezione opt-in: i mockup hosted. `design: artifacts` usa il tool `Artifact` integrato in Claude Code (niente da installare), e `design: stitch` usa l'MCP Google Stitch (offerto come installazione una tantum). Vedi [Mockup prima del codice](#-mockup-prima-del-codice).
|
|
30
30
|
|
|
31
31
|
Le scelte di design che ne derivano:
|
|
32
32
|
|
|
@@ -36,7 +36,7 @@ Le scelte di design che ne derivano:
|
|
|
36
36
|
|
|
37
37
|
- **Costruito per i team, perché il piano è condiviso.** Il tracker è l'unica fonte di verità, quindi la mappa è un **workspace condiviso**, non il file locale di una singola persona. Molte persone (e i loro agenti) ci lavorano contemporaneamente, e i meccanismi impediscono che si scontrino:
|
|
38
38
|
- **Claiming.** Prendi un ticket assegnandolo a te stesso; l'assegnatario *è* il lock. Una collisione ti ferma e chiede, invece di sovrascrivere il lavoro di qualcun altro. Chi rivendica un ticket lo possiede dall'inizio alla fine e lo chiude, senza un approvatore separato.
|
|
39
|
-
- **Una frontier condivisa, un ticket per sessione.** La **frontier** (ticket aperti, non assegnati, non bloccati) è la coda comune di ciò che è prendibile ora; ognuno ne sceglie uno diverso. Risolvere un ticket termina la sessione, così il lavoro resta in porzioni revisionabili, un ticket alla volta.
|
|
39
|
+
- **Una frontier condivisa, un ticket per sessione.** La **frontier** (ticket aperti, non assegnati, non bloccati, non in pausa) è la coda comune di ciò che è prendibile ora; ognuno ne sceglie uno diverso. Risolvere un ticket termina la sessione, così il lavoro resta in porzioni revisionabili, un ticket alla volta.
|
|
40
40
|
- **Isolation per sessioni concorrenti su una macchina.** Due agenti che modificano un unico checkout si corrompono a vicenda, quindi la convenzione `isolation:` (default **`auto`**, che chiede al work-start di ogni ticket se lavorerai più di un ticket alla volta e poi sceglie la modalità giusta in base alla forma del repo) dà a ogni ticket in corso il proprio **`git worktree`** (o un intero **`clone`** per le app legate a un path, o i repo con submodule, che un worktree non riesce a isolare in sicurezza) quando ne lavori più di uno alla volta; righe `Scope:` disgiunte lasciano girare in parallelo lavori non sovrapposti e serializzano solo dove c'è vera sovrapposizione.
|
|
41
41
|
- **Pause, resume, split.** Qualsiasi ticket può essere messo in **pause** con un commento di checkpoint e **ripreso** più tardi da chiunque (una volta rilasciato), o **splittato** in figli quando supera la dimensione di una sessione, con i blocker ripuntati così la frontier resta onesta.
|
|
42
42
|
- **Più mappe insieme.** Un repo può portare **più di una mappa attiva** (milestone o feature parallele), ciascuna con la propria frontier con scope, così due persone possono condurre due sforzi sullo stesso repo senza pestarsi i piedi, e puoi parcheggiare una mappa per lavorarne un'altra.
|
|
@@ -68,14 +68,14 @@ npx @marcomigozzi/trailhead --symlink # dev install (Claude; symlink al check
|
|
|
68
68
|
npx @marcomigozzi/trailhead --uninstall # rimuove tutto ciò che ha aggiunto (abbinalo a --claude / --codex)
|
|
69
69
|
npx @marcomigozzi/trailhead --dir=<path> # punta a una config dir specifica
|
|
70
70
|
```
|
|
71
|
-
Su **Claude Code** copia la skill (+ le sue `references/`), i comandi `/trailhead:*`, gli hook (in `hooks/`, registrati in `settings.json`) incluso un **update check** al SessionStart, e i template
|
|
71
|
+
Su **Claude Code** copia la skill (+ le sue `references/`), i comandi `/trailhead:*`, gli hook (in `hooks/`, registrati in `settings.json`) incluso un **update check** al SessionStart, e i template (workflow label-guard, statusline, l'hook git `commit-msg` e gli script di supporto che il motore esegue), in modo idempotente.
|
|
72
72
|
|
|
73
|
-
Su **Codex CLI** (`--codex`) proietta una skill nativa Codex invocata come **`$trailhead`** (`$trailhead work`, `$trailhead new "idea"`, …), una skill sottile **`$trailhead-<verb>`** per ogni verbo per la discoverability, le
|
|
73
|
+
Su **Codex CLI** (`--codex`) proietta una skill nativa Codex invocata come **`$trailhead`** (`$trailhead work`, `$trailhead new "idea"`, …), una skill sottile **`$trailhead-<verb>`** per ogni verbo per la discoverability, le sette guardrail come **hook** nativi di Codex (`~/.codex/hooks.json`, abilitando `features.hooks`; i quattro guard Bash condividono un solo processo dietro una singola registrazione; la search guard è solo per Claude Code e non è proiettata su Codex), e i pin di modello per-tecnica da **`models.codex.*`** in `~/.codex/agents/`. Serve Codex **0.145.0+** (l'installer fa un gate su `codex --version`). La modalità mockup `artifacts` (il tool `Artifact` di Claude Code) non è disponibile su Codex; lì l'opzione hosted è la modalità cross-host `design: stitch` (MCP Google Stitch), con il disco locale come ripiego.
|
|
74
74
|
|
|
75
75
|
Ri-esegui l'install per aggiornare, oppure esegui **`/trailhead:update`** (Claude) / **`$trailhead update`** (Codex) da dentro l'agente: rileva come trailhead è stato installato e installa la versione più recente dove è sicuro farlo (un `git pull` per un dev-symlink, una ri-esecuzione `npx` per npm, o `/plugin update` per il plugin). Quando esiste una versione più recente, la statusline mostra un flag `⬆ trailhead <version>` (Claude).
|
|
76
76
|
|
|
77
77
|
### Dopo l'installazione
|
|
78
|
-
Riavvia o ricarica il tuo agente così i comandi si registrano, poi esegui **`/trailhead`** per iniziare (smart entry), o `/trailhead:new "<idea>"` per tracciare una mappa. **Su Codex** la superficie è `$trailhead`: esegui **`$trailhead`** per lo smart entry, `$trailhead new "<idea>"` per tracciare, o una skill per-verbo `$trailhead-<verb>`. Nota: una volta installato, l'**hook di commit guard gira a ogni `git commit`** (imponendo i Conventional Commits e bloccando `Co-Authored-By`); disabilita gli hook del plugin nelle impostazioni se non lo vuoi. In ogni caso trailhead è self-contained: nessuna skill o plugin esterna è richiesta, niente preflight, niente version drift.
|
|
78
|
+
Riavvia o ricarica il tuo agente così i comandi si registrano, poi esegui **`/trailhead`** per iniziare (smart entry), o `/trailhead:new "<idea>"` per tracciare una mappa. **Su Codex** la superficie è `$trailhead`: esegui **`$trailhead`** per lo smart entry, `$trailhead new "<idea>"` per tracciare, o una skill per-verbo `$trailhead-<verb>`. Nota: una volta installato, l'**hook di commit guard gira a ogni `git commit`** (imponendo i Conventional Commits e bloccando `Co-Authored-By`); disabilita gli hook del plugin nelle impostazioni se non lo vuoi. In ogni caso trailhead è self-contained: nessuna skill o plugin esterna è richiesta, niente preflight di plugin esterni, niente version drift.
|
|
79
79
|
|
|
80
80
|
---
|
|
81
81
|
|
|
@@ -87,7 +87,7 @@ Una **map** è una singola issue GitHub etichettata `trailhead:map`. È un indic
|
|
|
87
87
|
|
|
88
88
|
Ciò che **non** ha bisogno di una propria mappa è un singolo pezzo di lavoro definito senza domande aperte, abbastanza piccolo da finire in una sessione. Quello è semplicemente **un ticket**, un `build` diretto (o un `todo`): un *work* che prendi con `/trailhead:work` e risolvi in una seduta, senza bisogno di tracciare. **Regola pratica: decisioni da prendere, o troppo grande per una seduta → una mappa; "fai solo X" → un singolo work.** Una feature che nasce come un work isolato ma si scopre aver bisogno di decisioni viene promossa a una propria mappa (o splittata); una mappa le cui domande evaporano tutte collassa di nuovo in una manciata di work. E un repo può contenere **più mappe insieme** (milestone o feature parallele), ciascuna con la propria frontier, così puoi parcheggiarne una e lavorarne un'altra.
|
|
89
89
|
|
|
90
|
-
Ogni **ticket** è una child issue con una label di tipo e un corpo di una sola domanda. La **frontier** è l'insieme dei ticket aperti, non assegnati, i cui blocker sono tutti chiusi: ciò che è prendibile proprio ora. Rivendichi un ticket assegnandolo a te stesso, lo risolvi con il motore per il suo tipo, poi registri la risposta come commento, lo chiudi, e ne fai il gist di nuovo sulla mappa.
|
|
90
|
+
Ogni **ticket** è una child issue con una label di tipo e un corpo di una sola domanda. La **frontier** è l'insieme dei ticket aperti, non assegnati, i cui blocker sono tutti chiusi e che non sono in pausa: ciò che è prendibile proprio ora. Rivendichi un ticket assegnandolo a te stesso, lo risolvi con il motore per il suo tipo, poi registri la risposta come commento, lo chiudi, e ne fai il gist di nuovo sulla mappa.
|
|
91
91
|
|
|
92
92
|
Man mano che i ticket si risolvono, la fog si dirada: domande che erano troppo vaghe da formulare diventano abbastanza nitide da diventare ticket, una alla volta, finché non resta nulla da decidere o costruire e la destination è raggiunta.
|
|
93
93
|
|
|
@@ -106,7 +106,7 @@ Questi tre riempiono i **3 slot di issue pinnate** di GitHub, così gli anchor d
|
|
|
106
106
|
**Il ciclo di vita.** Ogni progetto percorre lo stesso loop:
|
|
107
107
|
|
|
108
108
|
1. **Start**: `/trailhead:new "<idea>"` (greenfield) o `/trailhead:adopt` (codice esistente: mappa la codebase una volta, poi vai lean). Questo *traccia la mappa*: dai un nome alla destination, poi mappa la frontier in ampiezza (breadth-first) nei primi ticket e nella fog.
|
|
109
|
-
2. **Lavora la frontier, un ticket per sessione**: `/trailhead:work` prende il prossimo ticket prendibile (o quello che nomini) ed esegue il motore per il suo tipo: `research` raccoglie un fatto · `decision` dirama le opzioni poi fa grilling per scegliere · `prototype` crea un artefatto grezzo a cui reagire · `build` esegue discuss → plan → execute → verify · `bug` esegue repro → diagnose → fix → verify · `task` è plumbing manuale che sblocca una decision. `/trailhead:auto` incatena la frontier in autonomia, un ticket dopo l'altro, fermandosi solo al safety rail, alla fog, o a una decisione che serve l'umano.
|
|
109
|
+
2. **Lavora la frontier, un ticket per sessione**: `/trailhead:work` prende il prossimo ticket prendibile (o quello che nomini) ed esegue il motore per il suo tipo: `research` raccoglie un fatto · `decision` dirama le opzioni poi fa grilling per scegliere · `prototype` crea un artefatto grezzo a cui reagire · `build` esegue discuss → plan → execute → verify · `bug` esegue repro → diagnose → fix → verify · `task` è plumbing manuale che sblocca una decision. `/trailhead:auto` incatena la frontier in autonomia, un ticket dopo l'altro, fermandosi solo al safety rail, alla fog, o a una decisione che serve l'umano. All'avvio di un ticket, `work` e `quick` mostrano un breve riepilogo con la scelta **Proceed / Change something**; viene saltata (al suo posto una riga di nota) per un ticket che hai creato o appena chiarito con un grilling in questa sessione, e `auto` non chiede mai.
|
|
110
110
|
3. **Chiudi e sblocca**: risolvi il ticket (commento + chiusura), fanne il gist in `Decisions so far`, e rimuovi `trailhead:blocked` da ogni dipendente il cui ultimo blocker si è appena chiuso, diplomandolo sulla frontier.
|
|
111
111
|
4. **Ripeti** finché la frontier è vuota e la fog si è diradata: la destination (un artefatto funzionante) è raggiunta.
|
|
112
112
|
|
|
@@ -185,6 +185,27 @@ Ogni verbo è anche un comando con namespace (`/trailhead:new`, `/trailhead:work
|
|
|
185
185
|
| `/trailhead:grill [topic]` | esegue una sessione di grilling autonoma su una decision/topic |
|
|
186
186
|
| `/trailhead:map` | mostra la mappa a bassa risoluzione (destination, decisions, frontier, fog) |
|
|
187
187
|
| `/trailhead:dashboard` | mostra la dashboard del repo: l'indice pinnato di ogni mappa aperta, la whiteboard, e i conteggi live |
|
|
188
|
+
| `/trailhead:panel` | apre o chiude il pannello live della mappa: i ticket aperti della mappa attiva per stato, con un pulsante `work` per ogni ticket della frontier (**solo Claude Code**: richiede la mod di trailhead, 2.1.287+) |
|
|
189
|
+
|
|
190
|
+
### 🖥️ A schermo in Claude Code
|
|
191
|
+
|
|
192
|
+
La mod di trailhead (Claude Code 2.1.287+) è inclusa nel plugin e disegna il lavoro accanto alla conversazione. Codex mantiene gli hook dei comandi e non ha un pannello.
|
|
193
|
+
|
|
194
|
+

|
|
195
|
+
|
|
196
|
+
Il pannello della mappa elenca le mappe aperte da consultare, la frontier con un pulsante `work` per ogni ticket che pulisce il contesto e avvia il ticket, chi tiene cosa (il tuo ticket è segnato `this session`), i follow-up UAT in sospeso in un gruppo `UAT` (ognuno con il ticket che collauda), i ticket in pausa in un gruppo `Paused` e cosa è bloccato. Il footer ha `refresh` e `close`. `/trailhead:panel` lo apre e lo chiude, e si apre da solo una volta in fullscreen.
|
|
197
|
+
|
|
198
|
+

|
|
199
|
+
|
|
200
|
+
Un click mostra soltanto una mappa, e `back to active` torna a quella attiva. La mappa attiva cambia quando lavori uno dei suoi ticket. Una riga `Whiteboard` sopra l'elenco delle mappe, con i conteggi `N open / M`, mostra invece l'indice del repo: tutte le mappe aperte (un click ne apre una) e i ticket sciolti della whiteboard per stato, ognuno della frontier con il suo pulsante `work`; `map` torna indietro.
|
|
201
|
+
|
|
202
|
+

|
|
203
|
+
|
|
204
|
+
Il burn-down mostra i ticket aperti nel tempo, dal primo ticket della mappa a oggi, con chiusi e rimossi contati a parte.
|
|
205
|
+
|
|
206
|
+

|
|
207
|
+
|
|
208
|
+
La pipeline band sopra il prompt e la voce di stato sotto mostrano il ticket in gioco e il suo step.
|
|
188
209
|
|
|
189
210
|
### Capture: zero attrito, una riga di conferma, non risolve nulla
|
|
190
211
|
|
|
@@ -194,7 +215,7 @@ Ogni verbo è anche un comando con namespace (`/trailhead:new`, `/trailhead:work
|
|
|
194
215
|
| `/trailhead:seed <text>` | un ticket bloccato (trigger annotato) | *lo farò quando X accade* |
|
|
195
216
|
| `/trailhead:idea <text>` | la fog (`Not yet specified`) | *forse lo farò*: si diploma a ticket se si affina |
|
|
196
217
|
| `/trailhead:note <text>` | testo verbatim | *ricorda questo*: non necessariamente lavoro |
|
|
197
|
-
| `/trailhead:bug [--of <ticket>] <text>` | un ticket `bug` | un difetto; `--of` lo registra come `Regression of:` di un ticket chiuso |
|
|
218
|
+
| `/trailhead:bug [--of <ticket>] <text>` | un ticket `bug` | un difetto; `--of` lo registra come `Regression of:` di un ticket chiuso e lo deposita sulla mappa di quel ticket (o sulla whiteboard) senza chiedere |
|
|
198
219
|
|
|
199
220
|
Le quattro capture fog/ticket formano uno spettro di impegno e tempistica: **note < idea < seed < todo**.
|
|
200
221
|
|
|
@@ -217,6 +238,15 @@ I tre che mandano le persone in confusione sono **idea, seed, todo**, quindi ecc
|
|
|
217
238
|
|
|
218
239
|
I due tagli che contano: **idea vs seed** è aspettare la *chiarezza* vs aspettare una *condizione* (entrambi atterrano "dopo", per ragioni diverse); **seed vs todo** è impegnato *dopo* vs impegnato *ora*. Sotto tutti e tre sta **`note`** (testo grezzo da ricordare, forse mai lavoro), e di lato c'è **`bug`** (un difetto, non un livello di impegno). Il test per idea vs ticket è sempre: **puoi formulare la domanda con precisione ora?** Sì → un ticket (`todo` se prendibile, `seed` se gated); no → la fog (`idea`).
|
|
219
240
|
|
|
241
|
+
### Manage: mantenere sani l'install e le mappe
|
|
242
|
+
|
|
243
|
+
| Comando | Cosa fa |
|
|
244
|
+
|---|---|
|
|
245
|
+
| `/trailhead:config [get\|set …]` | setup guidato a menu; `get` stampa la config effettiva, `set <key> <value>` scrive una chiave (vedi Configuration sotto) |
|
|
246
|
+
| `/trailhead:update` | cerca un trailhead più recente e lo installa dove è sicuro farlo |
|
|
247
|
+
| `/trailhead:prune [map]` | recupera gli slot di sub-issue di una mappa sotto il cap di 100 di GitHub (elimina gli edge chiusi/orfani, mantiene i riferimenti) |
|
|
248
|
+
| `/trailhead:audit [map] [--all]` | verifica i ticket chiusi contro il codice attuale per trovare regressioni, più i duplicati e i raggruppabili tra quelli aperti; in sola lettura finché non confermi |
|
|
249
|
+
|
|
220
250
|
---
|
|
221
251
|
|
|
222
252
|
## 🎫 Tipi di ticket e i loro motori
|
|
@@ -230,7 +260,7 @@ Ogni tipo ha il proprio motore inline: nessuna skill esterna viene invocata.
|
|
|
230
260
|
| 🧭 `decision` | una scelta | HITL | diverge le opzioni se non chiare, poi grill per convergere su una |
|
|
231
261
|
| 🔬 `research` | un fatto | AFK | un subagent su un branch usa-e-getta (l'unico tipo eseguito in parallelo) |
|
|
232
262
|
| 🎨 `prototype` | una direzione approvata | HITL | un artefatto grezzo usa-e-getta a cui reagire; le schermate UI passano da qui (disco, un canvas Artifacts, o Stitch) prima del codice UI |
|
|
233
|
-
| 🔨 `build` | codice funzionante | HITL/AFK | `discuss → plan → execute → verify`: commit atomici, TDD ai seam, **prima un mockup per la UI rivolta all'utente** (tecnica Prototype, gated da `design.approval`), code review + acceptance testing (chiede chi guida, AI o umano, poi browser-drive o UAT conversazionale passo-passo) |
|
|
263
|
+
| 🔨 `build` | codice funzionante | HITL/AFK | `discuss → plan → execute → verify`: commit atomici, TDD ai seam, **[prima un mockup](#-mockup-prima-del-codice) per la UI rivolta all'utente** (tecnica Prototype, gated da `design.approval`), code review + [acceptance testing](#-acceptance-testing-uat) (chiede chi guida, AI o umano, o skip per rinunciare, poi browser-drive o UAT conversazionale passo-passo) |
|
|
234
264
|
| 🐛 `bug` | codice corretto | HITL/AFK | `repro → diagnose → fix → verify`; un difetto in lavoro chiuso è un ticket *nuovo* (`Regression of:`), non una riapertura |
|
|
235
265
|
| 🔧 `task` | un cambiamento di stato esterno | HITL/AFK | lavoro manuale che sblocca una decision (provisioning accessi, spostamento dati, iscrizioni) |
|
|
236
266
|
|
|
@@ -240,6 +270,80 @@ Quando trailhead pone una scelta forzata, una scelta advisory (non una decisione
|
|
|
240
270
|
|
|
241
271
|
---
|
|
242
272
|
|
|
273
|
+
## 🎨 Mockup prima del codice
|
|
274
|
+
|
|
275
|
+
Ogni ticket che cambia la UI rivolta all'utente (una nuova schermata, un redesign, un layout cambiato) viene **messo in mockup prima di scrivere qualsiasi codice UI**. Reagisci al mockup, lo approvi, e il build lo riproduce fedelmente; l'acceptance testing poi verifica il risultato rispetto a esso. Dove vive il mockup lo decide la chiave `design`:
|
|
276
|
+
|
|
277
|
+
| `design` | Dove vive il mockup | Host |
|
|
278
|
+
|---|---|---|
|
|
279
|
+
| **`disk`** (default) | un file HTML statico usa-e-getta accanto al codice, collegato dal ticket | qualsiasi |
|
|
280
|
+
| `artifacts` | un **canvas Design Artifact** su claude.ai: lo modifichi visivamente, lo commenti, lo esporti | Claude Code con login a un account claude.ai |
|
|
281
|
+
| `stitch` | un progetto **Google Stitch** (o un design system Stitch) | Claude Code e Codex |
|
|
282
|
+
|
|
283
|
+
Una domanda di UI ancora aperta riceve **3 varianti strutturalmente diverse** (layout diversi, non colori o testi) tra cui scegliere, non una sola proposta.
|
|
284
|
+
|
|
285
|
+
### Come appare con `artifacts`
|
|
286
|
+
|
|
287
|
+
```text
|
|
288
|
+
you › /trailhead:work # ⑤ build: "login screen"
|
|
289
|
+
trailhead › This ticket changes UI. Mock it up first? → yes
|
|
290
|
+
trailhead › No canvas for this map yet: pick one, paste a URL, or create one?
|
|
291
|
+
you › create one, "Acme app"
|
|
292
|
+
trailhead › Installed your design system "Acme DS" on the canvas.
|
|
293
|
+
Canvas: https://claude.ai/artifact/… · page "#42 Login"
|
|
294
|
+
Artboards: Login-A (split hero) · Login-B (centered card) · Login-C (stepper)
|
|
295
|
+
Which direction?
|
|
296
|
+
you › B, but with the social buttons above the form # oppure modificalo tu sul canvas
|
|
297
|
+
trailhead › Updated Login-B. Approve? → approve
|
|
298
|
+
trailhead › Re-read the approved artboard (your live edits included) → planning the build
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
- **Un canvas per mappa**, in cache in `design.project`; ogni ticket ha la sua pagina del canvas, ogni schermata (e variante) la sua tavola. Le schermate di app hanno un frame fisso (es. un telefono 390×844), le pagine web uno fluido.
|
|
302
|
+
- **Il tuo design system sul canvas.** `design.system` (o quello predefinito del tuo account) viene installato, così l'editor del canvas offre i suoi colori, la sua tipografia e i suoi componenti invece di imitazioni.
|
|
303
|
+
- **Approvi con il link davanti.** Ogni richiesta di approvazione porta l'URL del canvas e i nomi delle tavole; il [guard del link al mockup](#-hooks) blocca quelle che non li hanno.
|
|
304
|
+
- **Modifica liberamente.** Cambia il canvas direttamente o lascia commenti lì; all'approvazione trailhead **rilegge** le tavole e costruisce da *quella* versione, non da quella che ha pubblicato per ultima.
|
|
305
|
+
- **`design.approval`**: `explicit` (default) attende il tuo via libera prima del codice UI; `auto` mostra il mockup e procede.
|
|
306
|
+
|
|
307
|
+
### `stitch` e `disk`
|
|
308
|
+
|
|
309
|
+
`design: stitch` usa l'**MCP Google Stitch**, il generatore UI di Google basato su Gemini, ed è l'opzione hosted che gira sia su **Claude Code sia su Codex**. `design.surface` sceglie un progetto Stitch di schermate (`canvas`, default) o un design system Stitch condiviso (`design-system`). Se l'MCP non è connesso, trailhead offre di installarlo una volta (se rifiuti, ripiega sul disco):
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
claude mcp add --scope user --transport http stitch https://stitch.googleapis.com/mcp
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Dove `artifacts` non può girare (Codex, o una sessione con API key), trailhead offre di passare a `stitch` prima di ripiegare sul disco, e lo dice: non sostituisce mai in silenzio una modalità hosted con un file locale.
|
|
316
|
+
|
|
317
|
+
**Passare da claude.ai/design.** Il sito standalone di Claude Design chiude il 14/12/2026 e i suoi design ora vivono in Claude come Artifacts. Una config che dice ancora `design: claude.ai/design` continua a funzionare come `artifacts` (trailhead te lo dice una volta e offre di riscrivere la chiave), ma un progetto claude.ai/design in cache non è riutilizzabile: migra i design system dal banner della pagina Artifacts e lascia che trailhead agganci un nuovo canvas.
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## 🧪 Acceptance testing (UAT)
|
|
322
|
+
|
|
323
|
+
I test verdi provano che il codice fa ciò che il *codice* intendeva; l'acceptance testing prova che fa ciò che volevi *tu*. Per tutto ciò che si vede (una nuova schermata, dati che ora compaiono, un flusso cambiato), una suite verde **non chiude il ticket**: la Verify esegue anche una UAT, dopo i test e la code review.
|
|
324
|
+
|
|
325
|
+
Prima di iniziare, trailhead **controlla la base**: misura quanto il tuo branch di lavoro è indietro rispetto al trunk, lo sincronizza (fast-forward, rebase o merge; un conflitto annulla e ripristina), rilancia i test ed esegue i tuoi `preflight.checks`, e lo stesso controllo precede l'integrazione; ciò che non riesce a verificare ferma il ticket. Poi **prepara l'ambiente**: i passi di `uat.setup` (avviare il dev server, accendere l'emulatore; un passo il cui `check` passa già viene saltato) girano prima della domanda qui sotto, un passo fallito si ferma con un motivo chiaro, e `uat.accounts` nomina i login di test (si salvano solo riferimenti `$ENV`). Senza setup configurato può analizzare il progetto e proporne uno da salvare. `/trailhead:auto` esegue solo il setup configurato.
|
|
326
|
+
|
|
327
|
+
1. **Chiede chi guida.** Prima di ogni passo: **AI-driven**, **human-driven** o **skip**. Attende una risposta chiara (il silenzio ripete la domanda). Se nessun passo è qualcosa che l'agente può fare in questa sessione (un dispositivo che non raggiunge, credenziali che non ha, un giudizio di feel o di suono), toglie l'opzione AI-driven e chiede **human-driven** o **skip**, dicendoti perché in una riga. **Skip è una rinuncia, non un rinvio**: rinunci all'acceptance, il commento `VERIFY` la registra come `waived by the user (unconfirmed)`, cioè non confermata, mai come superata, e non si apre alcun follow-up. L'agente non lo sceglie mai al posto tuo, nemmeno sotto `/trailhead:auto`.
|
|
328
|
+
2. **AI-driven: guida l'app da solo.** Per una web app trova da sé l'URL di destinazione (un dev server in esecuzione, lo script `dev`, la porta configurata del framework), te lo propone da confermare, poi naviga, compila, clicca e verifica cosa c'è a schermo, con uno **screenshot come prova** nel commento `VERIFY` del ticket. **Oltre al browser, guida qualsiasi dispositivo la sessione raggiunga**: un telefono o un emulatore via `adb`, un simulatore iOS, una smart TV, un'app desktop, tramite i comandi e i tool che hai collegato (un MCP di dispositivo, computer use, la CLI della piattaforma). Tornano a te solo i passi che davvero non può fare, uno alla volta.
|
|
329
|
+
3. **Human-driven, o ciò che l'agente non raggiunge: una guida passo-passo.** Un dispositivo non collegato, un account che non ha, un giudizio di feel o di suono: trailhead ti accompagna **un passo alla volta in chat** (cosa fare, dove toccare, cosa dovresti vedere), attende ciò che hai effettivamente visto, poi va avanti. Mai una checklist scaricata addosso da sbrigare da solo.
|
|
330
|
+
4. **Rispetto al mockup approvato.** Se il ticket ne aveva uno, la schermata costruita viene confrontata **elemento per elemento e stato per stato** (layout, spaziature, colore, tipografia, testi; vuoto, caricamento, errore, disabilitato…), partendo dal mockup riletto, mai a memoria. Una deviazione non forzata è un finding, non un "quasi uguale".
|
|
331
|
+
5. **I fallimenti diventano ticket sul momento.** Un passo fallito registra atteso vs. visto e apre subito un follow-up `bug` (o un fix su questo ticket), poi chiede se proseguire.
|
|
332
|
+
6. **Niente passa come "fatto".** Se la UAT non si può eseguire ora (il dispositivo non è a portata, il backend non è deployato), trailhead chiede: eseguirla adesso, o aprire un ticket di follow-up, collegato con una riga `UAT of:` e marcato con l'etichetta `trailhead:uat` così ogni UAT in sospeso si trova con una sola etichetta, che porta la checklist completa. Un ticket rivolto all'utente non si chiude mai su una UAT che nessuno ha eseguito, salvo che tu ci rinunci esplicitamente (registrato come non confermato).
|
|
333
|
+
|
|
334
|
+
```text
|
|
335
|
+
trailhead › Tests and review are green. Who drives the UAT: AI or you? → AI
|
|
336
|
+
trailhead › Acceptance will run against http://localhost:5173, correct? → yes
|
|
337
|
+
trailhead › ✓ Sign in with GitHub → lands on /dashboard (screenshot)
|
|
338
|
+
✓ Login-B vs. the build: 14/14 elements, 4/4 states match
|
|
339
|
+
✓ Android app on the connected phone (adb): GitHub sign-in → home (screenshot)
|
|
340
|
+
? Step 6 is the haptic on "Signed in": does it buzz once, softly?
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Config: `acceptance.browser` (`auto` default, `on`, `off`) governa la guida del browser; `off` mantiene i controlli AI-driven via comandi e suite, e chiede comunque chi guida. `testing.webapp` / `testing.url` dicono se l'app è guidabile da browser e dove. Sotto `/trailhead:auto` va in AI-driven; i passi che solo tu puoi fare non vengono mai simulati: il ticket viene messo da parte ed elencato nel riepilogo della run; `/trailhead:auto` non sceglie mai skip.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
243
347
|
## 🏷️ Labels
|
|
244
348
|
|
|
245
349
|
Tutto ciò di cui la mappa ha bisogno è espresso come label GitHub, così lo stato è interrogabile nella UI del tracker:
|
|
@@ -247,10 +351,11 @@ Tutto ciò di cui la mappa ha bisogno è espresso come label GitHub, così lo st
|
|
|
247
351
|
- **Strutturali:** `trailhead:map`, `trailhead:ticket`
|
|
248
352
|
- **Anchor con scope di repo (uno ciascuno per repo, pinnati):** `trailhead:codebase` 🧱 (la codebase map distillata), `trailhead:conventions` 📜 (il modo di lavorare), `trailhead:dashboard` 📊 (l'indice pinnato di mappe + whiteboard + conteggi); ogni titolo porta la sua icona (come il 🗺 della mappa) così gli anchor pinnati si distinguono a colpo d'occhio
|
|
249
353
|
- **Type (una per ticket):** 🧭 `trailhead:decision` · 🔬 `research` · 🎨 `prototype` · 🔨 `build` · 🐛 `bug` · 🔧 `task`
|
|
250
|
-
- **State:** `trailhead:blocked` (ha un blocker aperto) · `seed` (parcheggiato su un trigger) · `out-of-scope` (chiuso, oltre la destination) · `superseded` (chiuso, splittato in figli)
|
|
354
|
+
- **State:** `trailhead:blocked` (ha un blocker aperto) · `seed` (parcheggiato su un trigger) · `out-of-scope` (chiuso, oltre la destination) · `superseded` (chiuso, splittato in figli) · `paused` (con checkpoint, fuori dalla frontier) · `unverified` (in quarantena finché un maintainer non lo adotta) · `fog` (tenuto aperto per chiarimenti)
|
|
251
355
|
- **Container:** `trailhead:whiteboard` (un ticket sciolto, senza mappa, fuori dalla frontier di ogni mappa, sulla frontier propria della whiteboard)
|
|
356
|
+
- **Marker:** `trailhead:uat` (un follow-up UAT in sospeso; mai un filtro della frontier) · `trailhead:map-<n>` (lega un ticket alla sua mappa)
|
|
252
357
|
|
|
253
|
-
La **frontier** è quindi una singola query (aperto, non assegnato, non `trailhead:blocked
|
|
358
|
+
La **frontier** è quindi una singola query (aperto, non assegnato, non `trailhead:blocked`, non in pausa), senza bisogno di parsare il corpo.
|
|
254
359
|
|
|
255
360
|
## 👥 Lavorare in team
|
|
256
361
|
|
|
@@ -258,10 +363,10 @@ Molte persone (e le loro sessioni di agente) condividono una mappa e la lavorano
|
|
|
258
363
|
|
|
259
364
|
- **Claim = assegnare a te stesso.** Chi rivendica possiede il ticket dall'inizio alla fine e lo chiude: non c'è approvatore e nessuno da attendere. Su una collisione di claim la sessione si ferma e chiede a te, invece di risolverla silenziosamente.
|
|
260
365
|
- **Split** un ticket sovradimensionato in figli e supersede l'originale (`/trailhead:split`).
|
|
261
|
-
- **Pause/resume** tramite un commento di checkpoint `PAUSED
|
|
262
|
-
- **Isola le sessioni concorrenti con i worktree.** Di default (`isolation: auto`) trailhead lo fa per te: al work-start di ogni ticket chiede se ne lavorerai più di uno alla volta e sceglie la modalità in base alla forma del repo. Per forzarla in anticipo, imposta `isolation: worktree` nell'header delle conventions, e ogni ticket in esecuzione gira nel proprio `git worktree` su un branch `trailhead/t<n>`, integrato di nuovo nel trunk al Resolve. Implica un branch per ticket anche sotto `git: main` (git non farà il checkout del trunk due volte), ed è la postura giusta per un **monorepo** (un worktree condivide l'object store, molto più economico di un secondo clone). Un'avvertenza: un worktree isola il *source* ma è un path nuovo senza dipendenze installate, quindi un **package legato a un path** (React Native/Expo, toolchain native, qualsiasi cosa legata a un `node_modules` locale) non buildera da lì. Per questi c'è **`isolation: clone`**: un clone dedicato per-ticket che installa le proprie dipendenze e builda/UATa come l'app vera (più pesante di un worktree, e lo strumento giusto per un submodule Expo/RN). Oppure tieni `isolation: none` e serializza. Altrimenti esegui le sessioni concorrenti in clone separati.
|
|
366
|
+
- **Pause/resume** tramite un commento di checkpoint `PAUSED` e un'etichetta `trailhead:paused` (aggiunta da pause, tolta da resume), così qualsiasi sessione può riprendere un ticket. I ticket in pausa compaiono sotto un gruppo `Paused` nelle viste di mappa, whiteboard e dashboard.
|
|
367
|
+
- **Isola le sessioni concorrenti con i worktree.** Di default (`isolation: auto`) trailhead lo fa per te: al work-start di ogni ticket chiede se ne lavorerai più di uno alla volta e sceglie la modalità in base alla forma del repo. Per forzarla in anticipo, imposta `isolation: worktree` nell'header delle conventions, e ogni ticket in esecuzione gira nel proprio `git worktree` su un branch `trailhead/t<n>`, integrato di nuovo nel trunk al Resolve. Implica un branch per ticket anche sotto `git: main` (git non farà il checkout del trunk due volte), ed è la postura giusta per un **monorepo** (un worktree condivide l'object store, molto più economico di un secondo clone). Un'avvertenza: un worktree isola il *source* ma è un path nuovo senza dipendenze installate, quindi un **package legato a un path** (React Native/Expo, toolchain native, qualsiasi cosa legata a un `node_modules` locale) non buildera da lì. Per questi c'è **`isolation: clone`**: un clone dedicato per-ticket che installa le proprie dipendenze e builda/UATa come l'app vera (più pesante di un worktree, e lo strumento giusto per un submodule Expo/RN). Oppure tieni `isolation: none` e serializza. Altrimenti esegui le sessioni concorrenti in clone separati. Un worktree o un clone nuovo non ha il `.env`: elenca i file gitignorati che gli servono sotto `isolation.copy` in `.trailhead/config.json` e trailhead li copia subito dopo aver creato il workspace, senza mai sovrascrivere (vedi Configurazione).
|
|
263
368
|
- **Un marker session-ticket per la tua statusline.** Quando inizia a lavorare un ticket, trailhead deposita una riga singola, gitignorata, `.trailhead/session-ticket` (`#<n> <title>`) alla radice di lavoro e la pulisce all'handoff. È un hint economico e offline così una statusline (o qualsiasi tool) può mostrare *su quale ticket è questa sessione* senza colpire il tracker; trailhead stesso continua a trattare le Issue come fonte di verità. Fa anche di più: finché è presente, l'hook git commit-msg richiede che ogni commit porti un trailer `Refs: #<n>` corrispondente.
|
|
264
|
-
- **Sceglie l'isolation per te di default (`auto`).** Senza un `isolation:` esplicito impostato (il default è `auto`),
|
|
369
|
+
- **Sceglie l'isolation per te di default (`auto`).** Senza un `isolation:` esplicito impostato (il default è `auto`), al work-start di un ticket trailhead chiede se ne lavorerai più di uno alla volta su questa macchina in questa sessione; se sì usa un `git worktree` (repo semplice) o un `clone` (superrepo con submodule), altrimenti lavora semplicemente nel checkout corrente. Non viene scritto nulla nelle conventions: la risposta è ricordata su questa macchina nel file gitignorato `.trailhead/isolation-answer.json` e riusata, con una riga di nota, finché gli altri ticket assegnati a te restano gli stessi e l'ultimo work-start risale a meno di 8 ore fa; un cambiamento o un record scaduto chiede di nuovo. Puoi comunque forzare `none`/`worktree`/`clone` esplicitamente, e `/trailhead:auto` e le modalità esplicite non usano mai la risposta ricordata.
|
|
265
370
|
- **Dai scope ai ticket per path su un monorepo.** Un ticket può portare una riga `Scope:` che nomina il/i package/dir che tocca: scope disgiunti parallelizzano in sicurezza, e dà scope a build/test e ai commit del worktree limitandoli al package interessato. `/trailhead:adopt` rileva un monorepo e propone sia `isolation: worktree` sia la convenzione `Scope:`. Sotto `isolation: none`, `Scope:` **serializza** anche un'area condivisa: al momento del claim una sessione si trattiene se lo scope di un altro ticket in corso si sovrappone, così due ticket con scope sullo stesso submodule/package non possono girare insieme (è così che tieni due sessioni fuori da un'app legata a un path).
|
|
266
371
|
- **I git submodule sono gestiti come repo separati.** Il lavoro che atterra dentro un submodule viene committato *dentro il submodule* (su un branch) e pubblicato prima che un bump del gitlink nel parent lo referenzi. Poiché i worktree del superproject condividono un unico git dir del submodule, un **repo con submodule risolve a `clone`** (sotto il default `auto`, o scalando un `worktree` esplicito), così ogni ticket ottiene uno stato del submodule indipendente; il clone provvede i suoi submodule al setup (`--recurse-submodules`) e il Verify controlla `git status` dentro ogni submodule toccato. Un ticket che copre due submodule resta atomico tramite un singolo commit del parent che bumpa entrambi i gitlink insieme; il suo `Scope:` li nomina entrambi, e lo stesso submodule conta come scope sovrapposto, quindi due ticket su di esso serializzano. `/trailhead:adopt` rileva `.gitmodules` e scrive la regola nelle conventions.
|
|
267
372
|
- **Lo stato vive sui ticket** (claim, label, commenti; tutti conflict-free); il corpo della mappa è un indice ri-leggibile, non la fonte di verità. Il record durevole di una risoluzione è il commento del ticket stesso.
|
|
@@ -290,7 +395,7 @@ Tre layer: **il più vicino vince**, chiave per chiave (una chiave non impostata
|
|
|
290
395
|
- **Global**: `~/.claude/trailhead/config.json`: i tuoi default permanenti su ogni progetto.
|
|
291
396
|
- **Defaults**: i valori integrati.
|
|
292
397
|
|
|
293
|
-
`/trailhead:config` esegue un **setup guidato, a menu**: scegli lo scope, poi percorri ogni impostazione (⚙️ modo di lavorare (git · release · isolation) · 🌐 ticket language · 🧠 models · 🎨 design + approval · 🧪 TDD · 🖥️ acceptance testing · 🧑⚖️ plan review · 📊 statusline) come un menu con icone; niente editing manuale del JSON. Ogni passo è chiesto (nessuno saltato), e i **modelli plan ed execute sono sempre due scelte separate e version-pinned**. `config get` stampa la config effettiva unita; `config set <key> <value>` scrive una chiave.
|
|
398
|
+
`/trailhead:config` esegue un **setup guidato, a menu**: scegli lo scope, poi percorri ogni impostazione (⚙️ modo di lavorare (git · release · isolation) · 🌐 ticket language · 🧠 models (un profilo High / Balanced / Low, o Manual) · 🎨 design + approval · 🧪 TDD · ⚖️ effort · 🖥️ acceptance testing (browser, setup UAT, un account di test) · 🧑⚖️ plan review · 📊 statusline) come un menu con icone; niente editing manuale del JSON. Ogni passo è chiesto (nessuno saltato), e i **modelli plan ed execute sono sempre due scelte separate e version-pinned**. `config get` stampa la config effettiva unita; `config set <key> <value>` scrive una chiave.
|
|
294
399
|
|
|
295
400
|
`/trailhead:prune [map]` recupera gli slot di sub-issue di una mappa sotto il cap di 100 di GitHub (elimina gli edge chiusi/orfani, mantiene ogni riferimento). Offerto automaticamente quando una mappa è vicina o al cap, ed eseguibile anche su richiesta.
|
|
296
401
|
|
|
@@ -303,25 +408,31 @@ Il passo **📊 statusline** offre di installare la status bar di trailhead per
|
|
|
303
408
|
| Key | Values (default **bold**) | Effetto |
|
|
304
409
|
|---|---|---|
|
|
305
410
|
| `ticket.language` | un codice ISO 639-1 (**`en`**) | la lingua in cui trailhead **scrive** la sua prosa GitHub e le descrizioni dei commit, disaccoppiata dalla lingua in cui conversa |
|
|
306
|
-
| `models.{plan,execute,research,review,debug,verify,codebase-map}` | un id modello completo **versionato** (**inherit session
|
|
411
|
+
| `models.{plan,execute,research,review,debug,verify,codebase-map}` | un id modello completo **versionato** (**default del profilo Balanced**; `inherit session` è una scelta esplicita) | quale modello esegue ogni attività; `plan` ed `execute` sono sempre impostati separatamente |
|
|
412
|
+
| `models.codex.{plan,execute,research,review,debug,verify,codebase-map}` | un id modello OpenAI, o `{model, effort}` (**inherit session**) | la stessa divisione per attività su Codex, indipendente da `models.*` (id Claude); riesegui l'installer per proiettarla in `~/.codex/agents/` |
|
|
307
413
|
| `design` | **`disk`** \| `artifacts` \| `stitch` | dove vanno i mockup UI: HTML usa-e-getta locale, un canvas Design **Artifact** su claude.ai (solo Claude Code), o Google Stitch (cross-host, via l'MCP Stitch). Il vecchio valore `claude.ai/design` viene letto come `artifacts` |
|
|
414
|
+
| `design.project` | URL del canvas Artifact / id del progetto Stitch | solo `artifacts` e `stitch`: il canvas o il progetto Stitch su cui finiscono i mockup; impostato alla prima schermata UI (scegli, incolla o crea), non a mano. Un vecchio progetto claude.ai/design non viene riutilizzato |
|
|
308
415
|
| `design.surface` | **`canvas`** \| `design-system` | solo `stitch`: un progetto Stitch di schermate (default) o un design system Stitch condiviso |
|
|
309
416
|
| `design.system` | URL di un Design System Artifact | solo `artifacts`: il design system installato sul canvas dei mockup (chiesto alla prima schermata se non impostato) |
|
|
310
417
|
| `design.approval` | **`explicit`** \| `auto` | attendi l'approvazione del mockup prima del codice UI, o procedi senza bloccare |
|
|
311
418
|
| `tdd` | **`seams`** \| `on` \| `off` | come il motore `build` testa |
|
|
312
|
-
| `acceptance.browser` | **`auto`** \| `on` \| `off` | guida il browser in Verify (dopo aver chiesto chi guida, AI o umano); `off` esegue comunque controlli AI-driven via comandi, e ti accompagna in una UAT conversazionale per ciò che solo tu puoi fare (passo-passo in chat, non una checklist da fare da solo) |
|
|
419
|
+
| `acceptance.browser` | **`auto`** \| `on` \| `off` | guida il browser in Verify (dopo aver chiesto chi guida, AI o umano, o skip); `off` esegue comunque controlli AI-driven via comandi, e ti accompagna in una UAT conversazionale per ciò che solo tu puoi fare (passo-passo in chat, non una checklist da fare da solo) |
|
|
313
420
|
| `testing.webapp` / `testing.url` | bool / URL | è browser-drivabile, e dove |
|
|
314
421
|
| `plan_review` | **`off`** \| `on` \| CLI list | invia i PLAN di `build` ad AI CLI esterne (Gemini, Codex, …) per un secondo parere e converge sulle loro obiezioni |
|
|
315
422
|
| `plan_review.rounds` | integer (**`2`**) | numero massimo di round converge-and-re-review |
|
|
316
423
|
| `code_review.rounds` | integer (**`2`**) | numero massimo di round fix-and-re-review in Code review prima del checkpoint HITL di confine |
|
|
317
424
|
| `effort` | **`standard`** \| `lean` | quanto lavora il motore `build`/`bug` su una modifica: `standard` esegue ogni step, `lean` fa una triage di dimensione sulle modifiche piccole e offre di saltare quelli pesanti (plan, TDD, cross-AI review, code review completa, verify goal-backward). Governa solo `build`/`bug`: `quick` fa sempre la triage di dimensione, a prescindere da questa chiave |
|
|
425
|
+
| `isolation.copy` | array di path relativi al repo (**unset**) | file e directory gitignorati (`.env`, `.npmrc`, config locale) copiati dal checkout principale in ogni nuovo workspace `worktree`/`clone`, senza mai sovrascrivere; i path non sicuri (assoluti, `..`, `.git`) vengono rifiutati. Se non impostata, trailhead suggerisce i file `.env` che hanno un fratello `*.example` tracciato |
|
|
426
|
+
| `preflight.checks` | array di comandi shell (**unset**) | i controlli del tuo progetto, eseguiti dal preflight della base prima della UAT e prima dell'integrazione; un exit diverso da zero ferma il ticket (es. un controllo sui timestamp di migration duplicati) |
|
|
427
|
+
| `uat.setup` | array di `{name, run, check?, note?}` (**unset**) | passi di setup in ordine, eseguiti a ogni avvio di UAT, prima della domanda sul drive-mode (avviare il dev server, accendere l'emulatore); un `check` che passa salta il passo; `[]` significa nessun setup necessario |
|
|
428
|
+
| `uat.accounts` | oggetto di `role: {user, secret}` (**unset**) | account di test nominati per la UAT; `secret` è sempre un riferimento `$ENV`, mai un valore, così la config committata resta generica (il setup guidato chiede solo il nome della variabile) |
|
|
318
429
|
|
|
319
430
|
**Models.** Ogni chiave esegue la sua attività come **subagent** sul modello che nomini, così l'intera suddivisione per-attività si applica dentro una singola sessione di lavoro, qualunque modello quella sessione esegua:
|
|
320
431
|
|
|
321
432
|
- `plan` ed `execute` sono i passi del motore build/bug. Execute è anch'esso un subagent, e committa su `main`.
|
|
322
433
|
- `research`, `review`, `debug`, `verify` (il controllo goal-backward in Verify), e il fan-out della codebase-map girano ciascuno sulla propria chiave.
|
|
323
434
|
|
|
324
|
-
Scegli `plan` ed `execute` separatamente, ciascuno per **id completo versionato** (mai un `opus` o `sonnet` nudo). Una chiave non impostata,
|
|
435
|
+
Scegli `plan` ed `execute` separatamente, ciascuno per **id completo versionato** (mai un `opus` o `sonnet` nudo). Una chiave non impostata usa il default del profilo Balanced, e una uguale al modello della sessione gira semplicemente inline; imposta `inherit session` per usare il modello della sessione.
|
|
325
436
|
|
|
326
437
|
La **sessione principale resta l'orchestratore**. Tiene i momenti interattivi (il Discuss di un build, e l'acceptance/UAT del Verify) e fa charting, grilling e scrittura dei ticket sul proprio modello. Nessuna chiave governa la qualità dei ticket, quindi esegui le sessioni di charting sul tuo modello forte.
|
|
327
438
|
|
|
@@ -331,13 +442,9 @@ Esempio di file di config (la stessa forma funziona per il `.trailhead/config.js
|
|
|
331
442
|
{ "ticket": { "language": "en" }, "models": { "plan": "claude-opus-5-5", "execute": "claude-sonnet-5-5" }, "tdd": "seams", "acceptance": { "browser": "auto" } }
|
|
332
443
|
```
|
|
333
444
|
|
|
334
|
-
**
|
|
445
|
+
**Mockup di design e acceptance testing.** Come si comportano le chiavi `design.*` (canvas, design system, approvazione, passaggio da claude.ai/design) è in [Mockup prima del codice](#-mockup-prima-del-codice); come `acceptance.browser` e `testing.*` guidano la Verify è in [Acceptance testing](#-acceptance-testing-uat).
|
|
335
446
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
Con **`stitch`**, `design.surface` sceglie un progetto Stitch di schermate (`canvas`, default) o un design system Stitch condiviso (`design-system`); trailhead lo sceglie, incolla o crea allo stesso modo, e offre una volta di installare l'MCP Stitch se non è connesso (se rifiuti, ripiega sul disco locale).
|
|
339
|
-
|
|
340
|
-
**Passare da claude.ai/design.** Il sito standalone di Claude Design chiude il 14/12/2026 e i suoi design ora vivono in Claude come Artifacts. Una config che dice ancora `design: claude.ai/design` continua a funzionare come `artifacts` (trailhead te lo dice una volta e offre di riscrivere la chiave), ma un progetto claude.ai/design in cache non è riutilizzabile: migra i design system dal banner della pagina Artifacts e lascia che trailhead agganci un nuovo canvas. Dove il tool `Artifact` non c'è (Codex, o una sessione con API key), trailhead offre di passare a `stitch` prima di ripiegare sul disco locale. `design.approval` decide se il build attende il tuo esplicito via libera (`explicit`), o procede subito dopo aver mostrato il mockup (`auto`).
|
|
447
|
+
**Annidata o piatta.** Le chiavi a lista qui sopra (`isolation.copy`, `preflight.checks`, `uat.setup`, `uat.accounts`) si possono scrivere annidate (`{"uat": {"setup": [...]}}`) o piatte (`"uat.setup": [...]`); se un file ha entrambe vince la forma annidata con un avviso, e un valore di progetto sostituisce quello globale per intero (le liste non si uniscono). `git`, `release` e la *modalità* isolation restano nell'header delle conventions; solo `isolation.copy` sta in `config.json`.
|
|
341
448
|
|
|
342
449
|
---
|
|
343
450
|
|
|
@@ -347,13 +454,19 @@ Oltre alle istruzioni della skill, trailhead include otto hook propri (in `hooks
|
|
|
347
454
|
|
|
348
455
|
- **Commit guard** (`PreToolUse` su `git commit`): blocca in modo netto un commit il cui subject non è [Conventional Commits](https://www.conventionalcommits.org), e blocca in modo netto qualsiasi trailer `Co-Authored-By`. Questo rispecchia la validazione dei commit di GSD.
|
|
349
456
|
- **Secret guard** (`PreToolUse` sulle scritture `gh` di issue/PR): trailhead pubblica molto sul tracker (corpi dei ticket, commenti del motore, issue codebase/conventions, risoluzioni). Questo scansiona ciò che una scrittura `gh issue`/`gh pr`/`gh api` sta per pubblicare (l'inline `--body`, un heredoc, o un `--body-file`) e lo **blocca in modo netto** se corrisponde a un pattern di credenziale (chiavi private, token GitHub/AWS/OpenAI/Slack/Google/Stripe, JWT, o un `password`/`secret`/`token=…` hardcoded). Il blocco è un **segnale di pulisci-e-riprova, non un vicolo cieco**: trailhead redige il valore segnalato sul posto (`<REDACTED>` o un riferimento a env-var) e ripubblica automaticamente, così il contenuto pulito atterra comunque: il segreto semplicemente non raggiunge mai il tracker. Resta un *blocco* fail-safe anziché una silenziosa auto-riscrittura di proposito: un blocco non fa mai leak, mentre una redazione che silenziosamente non è stata applicata sì. Non scansiona mai le letture, solo le scritture in uscita.
|
|
350
|
-
- **Install guard** (`PreToolUse` sulle installazioni di pacchetti): una barriera anti-slopsquatting. Blocca in modo netto un'installazione da registry pubblico (npm / PyPI / crates.io / Go / RubyGems) finché il pacchetto non è verificato (similarità typosquat a nomi popolari, età / prima apparizione, numero di download, metadati del repository presenti e coerenti); una volta verificato, ri-esegui il comando esatto con il prefisso `TRAILHEAD_VERIFIED_INSTALL=1` per procedere. Il motore Execute / Fix porta lo stesso block-and-ask.
|
|
351
|
-
- **Search guard** (`PreToolUse` su `Bash`): un backstop strutturale per la regola di igiene dei comandi di ricerca (mai `cd` seguito da una lettura/ricerca su percorso relativo). Blocca in modo netto un singolo comando Bash che sia insieme un cambio di directory (`cd`/`pushd`/`env -C`) e, in un'istruzione unita o successiva, una lettura/ricerca su percorso relativo (`grep`/`rg`/`ag`/`cat`/`head`/`tail`/`wc`/`nl`/`sed`/`awk`/`less`/`more`, o `git grep`/`log`/`show`/`diff` senza `-C`), così la forma che fa scattare una regola di deny su `Read()` sotto bypass permissions (ripiegando su un prompt di approvazione manuale invece di girare headless) non viene mai eseguita, anziché essere solo scoraggiata nella prosa dell'agente. Solo Claude Code; non è proiettata su Codex, che non ha una regola di deny su `Read()`.
|
|
457
|
+
- **Install guard** (`PreToolUse` sulle installazioni di pacchetti): una barriera anti-slopsquatting. Blocca in modo netto un'installazione da registry pubblico (npm / PyPI / crates.io / Go / RubyGems) finché il pacchetto non è verificato (similarità typosquat a nomi popolari, età / prima apparizione, numero di download, metadati del repository presenti e coerenti); una volta verificato, ri-esegui il comando esatto con il prefisso `TRAILHEAD_VERIFIED_INSTALL=1` per procedere. Il motore Execute / Fix porta lo stesso block-and-ask. Legge i comandi come una shell: il testo dentro virgolette o heredoc (un `echo`, un messaggio di commit) non è un'installazione, le installazioni da lockfile passano e wrapper come `sudo`, `time`, `env` o `xargs` vengono attraversati.
|
|
458
|
+
- **Search guard** (`PreToolUse` su `Bash`): un backstop strutturale per la regola di igiene dei comandi di ricerca (mai `cd` seguito da una lettura/ricerca su percorso relativo). Blocca in modo netto un singolo comando Bash che sia insieme un cambio di directory (`cd`/`pushd`/`env -C`) e, in un'istruzione unita o successiva, una lettura/ricerca su percorso relativo (`grep`/`rg`/`ag`/`cat`/`head`/`tail`/`wc`/`nl`/`sed`/`awk`/`less`/`more`, o `git grep`/`log`/`show`/`diff` senza `-C`), così la forma che fa scattare una regola di deny su `Read()` sotto bypass permissions (ripiegando su un prompt di approvazione manuale invece di girare headless) non viene mai eseguita, anziché essere solo scoraggiata nella prosa dell'agente. I target di redirezione (`2>/dev/null`) non contano come letture, e un `cd` alla directory della sessione stessa non la attiva. Solo Claude Code; non è proiettata su Codex, che non ha una regola di deny su `Read()`.
|
|
352
459
|
- **Body guard** (`PreToolUse` sulle scritture `gh` di body issue/PR): blocca in modo netto una scrittura `gh issue edit` / `gh pr edit` / `gh api` che imposterebbe il body di un issue a vuoto o solo spazi, così un read-modify-write la cui lettura è tornata con un body vuoto/degradato (es. un HTTP 5xx transitorio su `gh issue view --json body`) non può mai cancellare il body esistente.
|
|
353
460
|
- **Secret-read guard** (`PreToolUse` su `Read|Bash`): blocca in modo netto la lettura di `.env`/`.env.*`/`.secrets`, sia tramite il tool Read sia tramite un comando Bash (un operando file, il valore di un'opzione, o un target di redirect `<`). È una decisione `deny` a livello di hook anziché una regola di permesso su `Read()`, quindi i segreti restano illeggibili senza attivare il prompt di approvazione `cd-compound-read` di Claude Code 2.1.259.
|
|
354
|
-
- **Mockup-link guard** (`PreToolUse` su `AskUserQuestion`): rete di sicurezza strutturale per la regola della tecnica Prototype secondo cui la richiesta di approvazione di un mockup porta con sé il link al mockup. Blocca un `AskUserQuestion` che chiede di approvare un mockup (o di scegliere tra varianti) quando il testo della risposta subito prima
|
|
461
|
+
- **Mockup-link guard** (`PreToolUse` su `AskUserQuestion`): rete di sicurezza strutturale per la regola della tecnica Prototype secondo cui la richiesta di approvazione di un mockup porta con sé il link al mockup. Blocca un `AskUserQuestion` che chiede di approvare un mockup (o di scegliere tra varianti) quando né il testo della risposta subito prima né la domanda di approvazione stessa contengono un URL o un path (se il messaggio corrente non è ancora nel transcript, la guardia non può giudicare e lascia passare), così l'agente mette il link cliccabile nel messaggio prima di richiedere. Su Codex, che non ha il tool `AskUserQuestion` e pone le domande come elenco numerato in testo, il gemello `mockup-link-stop` gira su `Stop`: se la risposta finale chiede quell'approvazione senza link, Codex fa proseguire il turno e l'agente riscrive la domanda col link.
|
|
355
462
|
- **Issue injection scanner** (`PostToolUse` sulle letture `gh`): trailhead legge testo di issue/PR/commenti scritto da chiunque abbia accesso al repo, cioè input non fidato. Quando quel testo contiene frasi di prompt-injection, l'hook inietta un avviso che ricorda all'agente di trattarlo come dati, mai come comandi. Solo advisory: non blocca mai.
|
|
356
463
|
|
|
464
|
+
I guard di commit, secret, install, search e body girano in **un solo processo**: una singola registrazione `trailhead-bash-guards.js` li valuta in quell'ordine, così una chiamata Bash paga un solo avvio di node invece di cinque (tre processi hook per chiamata Bash in tutto: l'hook unificato, il secret-read guard e l'injection scanner). Restano cinque guard distinti con verdetti invariati; vince il primo blocco, e un guard che va in errore consente da solo senza fermare gli altri. Anche un guard il cui modulo manca o è rotto viene saltato, ma mai in silenzio: l'hook segnala alla sessione quale guard non ha controllato il comando, così un'installazione parziale non passa inosservata. Su Codex lo stesso hook è registrato con `--guards=commit,secret,install,body`, perché lì non c'è la search guard.
|
|
465
|
+
|
|
466
|
+
I guard secret, body e secret-read **falliscono in modo chiuso sui costrutti shell che non sanno interpretare con certezza** (`eval`, `source` / `.`, un `${ cmd; }` di bash 5.3, `printf -v`, la definizione di una funzione, un alias, una chiave body di `gh api` quotata, un backslash-a-capo dentro una parola): quando uno di questi può nascondere o precedere una scrittura (o sta accanto a un path segreto) il comando viene bloccato con un messaggio "riscrivilo in forma semplice" invece di essere emulato; gli stessi costrutti senza scritture o segreti vicini passano.
|
|
467
|
+
|
|
468
|
+
Accanto a questi trailhead installa un **hook git `commit-msg`** (un wrapper POSIX `sh`, quindi funziona anche nei repo con `"type": "module"`) che impone le stesse regole di commit su ogni host, più il trailer `Refs: #<n>` mentre c'è un ticket di sessione attivo. Se non può girare (script mancante, nessun `node`) stampa `trailhead: commit-msg hook inactive (<reason>); commit rules not enforced.` su stderr e lascia passare il commit; un hook già installato viene aggiornato al prossimo avvio di un ticket.
|
|
469
|
+
|
|
357
470
|
Tutti e otto sono crash-safe (qualsiasi errore → allow) e attivi ogni volta che il plugin è installato. I guard di commit, secret, install, search, body e secret-read quindi si applicano in **ogni** repo, non solo nei progetti trailhead: intenzionale, dato che i conventional commit, niente `Co-Authored-By`, nessun segreto leakato, nessuna installazione non verificata, niente `cd`-poi-lettura-relativa, nessun body issue cancellato, e niente `.env`/`.secrets` leggibili sono regole permanenti di trailhead. Per fare opt-out, disabilita gli hook del plugin nelle impostazioni di Claude Code.
|
|
358
471
|
|
|
359
472
|
---
|