185 lines
7 KiB
Markdown
185 lines
7 KiB
Markdown
# graceful-handoff
|
|
|
|
> Auto-trigger session handoff at context threshold. Manual `/graceful-handoff` always works. Designet for Opus 4.7.
|
|
|
|
**Problemet:** Opus 4.7 fyller kontekstvinduet raskt — ofte innen ~5 minutter for reelt arbeid. Når du er på 60-70% og må starte ny sesjon, er det tre manuelle steg som blir hastverk eller glemt:
|
|
|
|
1. Oppsummere hvor arbeidet står (commits, lokale endringer, hva som er testet)
|
|
2. Commite og pushe ferdig arbeid (ellers tapes det)
|
|
3. Skrive en copy-paste-prompt som lar neste sesjon fortsette uten tap
|
|
|
|
**v2.0 fjerner alle tre steg fra brukerens hender:**
|
|
|
|
- **statusLine-hint ved 60%** og urgent reminder ved 70% (display-only, trygt)
|
|
- **Stop hook auto-eksekvering ved estimert ≥70%**: skriver artefakt + commit (push gjenstår — irreversibel handling beholdes manuell)
|
|
- **SessionStart auto-load ved `source: resume`/`compact`**: handoff-innholdet injiseres automatisk i ny sesjon, ingen `cat` nødvendig
|
|
- **Manuell `/graceful-handoff`** fungerer som backup — alltid
|
|
|
|
## Installasjon
|
|
|
|
```bash
|
|
claude plugin marketplace add https://git.fromaitochitta.com/open/ktg-plugin-marketplace.git
|
|
# Deretter: /plugin install graceful-handoff
|
|
```
|
|
|
|
## Bruk
|
|
|
|
### Manuell trigger
|
|
|
|
```
|
|
/graceful-handoff
|
|
```
|
|
|
|
Med slug:
|
|
|
|
```
|
|
/graceful-handoff refactor-auth
|
|
```
|
|
|
|
Uten auto-commit:
|
|
|
|
```
|
|
/graceful-handoff --no-commit
|
|
```
|
|
|
|
Dry-run:
|
|
|
|
```
|
|
/graceful-handoff --dry-run
|
|
```
|
|
|
|
Auto-mode (used internally by Stop hook):
|
|
|
|
```
|
|
/graceful-handoff --auto --no-push --non-interactive
|
|
```
|
|
|
|
### Automatisk trigger
|
|
|
|
Ingen handling kreves. Når kontekst krysser estimert 70%, fyrer Stop hook automatisk:
|
|
|
|
1. Skriver `NEXT-SESSION-PROMPT.local.md`
|
|
2. Stager kun handoff-artefakten (IKKE andre dirty filer — eksplisitt fix i v2.0)
|
|
3. Committer
|
|
4. **Pusher IKKE** — dette gjør du selv når du er klar
|
|
|
|
Ved ny sesjon (`claude --resume`), SessionStart hook leser handoff-filen automatisk og injiserer innhold i konteksten. Filen blir deretter renamet til `*.archived.local.md` for å hindre stale-load.
|
|
|
|
## Arkitektur (v2.0)
|
|
|
|
```
|
|
skills/graceful-handoff/SKILL.md # Frontmatter: disable-model-invocation, model: sonnet-4-6
|
|
scripts/handoff-pipeline.mjs # Deterministisk pipeline, returnerer JSON
|
|
hooks/scripts/statusline-monitor.mjs # Display: 60% / 70% hint
|
|
hooks/scripts/stop-context-monitor.mjs # Auto-execute ved estimert ≥70%
|
|
hooks/scripts/session-start-load-handoff.mjs # Auto-load på resume/compact
|
|
hooks/hooks.json # Registrerer alt
|
|
```
|
|
|
|
`disable-model-invocation: true` betyr at Claude IKKE kan invokere skill-en autonomt — bruker må trigge manuelt eller hook må kalle pipeline-skriptet direkte (Stop hook gjør det siste).
|
|
|
|
## Auto-trigger ved kontekst-terskel — hvordan virker det?
|
|
|
|
Det finnes ingen Claude Code-primitiv som eksponerer real-time kontekst-prosent til hooks (Anthropic har closed feature requests #16988, #27969, #34340). Vi bruker derfor en **approksimasjon**:
|
|
|
|
1. **Stop hook** fyrer etter hver model-respons og får `transcript_path` i payload
|
|
2. Hooken leser `wc -c <transcript>` for char-count
|
|
3. Estimerer tokens som `chars / 3.5`
|
|
4. Sammenligner mot `context_window_size` fra payload (default 200k, men respekterer 1M-windows)
|
|
5. Ved estimert ≥ 70%: spawner pipeline synkront
|
|
|
|
Dette estimatet kan avvike ±10% fra Claude's reelle telling. **70% er konservativt valgt** — gir buffer mot drift.
|
|
|
|
For å hindre repeat-firing innen samme sesjon: lock-fil `<transcript_dir>/.handoff-lock-<session_id>` opprettes ved første trigger.
|
|
|
|
## Argumenter
|
|
|
|
| Argument | Beskrivelse |
|
|
|----------|-------------|
|
|
| `[topic-slug]` | Kebab-case slug. Med slug: `NEXT-SESSION-<slug>.local.md`. Uten: `NEXT-SESSION-PROMPT.local.md` |
|
|
| `--no-commit` | Hopp over commit+push. Bruker håndterer commit manuelt |
|
|
| `--no-push` | Commit OK, men ikke push (Stop hook bruker dette) |
|
|
| `--dry-run` | Ingen filer skrives, ingen git-operasjoner |
|
|
| `--auto` | Non-interactive, auto-Y på commit-bekreftelse (kun for hooks) |
|
|
| `--non-interactive` | Uten `--auto`: feil; med: kjør uten prompts |
|
|
|
|
## Frontmatter (SKILL.md)
|
|
|
|
```yaml
|
|
---
|
|
name: graceful-handoff
|
|
description: Produser handoff-artefakt, commit+push, og copy-paste-prompt for neste sesjon.
|
|
disable-model-invocation: true
|
|
model: claude-sonnet-4-6
|
|
allowed-tools: Bash(git:*) Bash(jq:*) Bash(node:*) Bash(find:*) Bash(pwd:*) Read Write Glob
|
|
---
|
|
```
|
|
|
|
**Merk:** `allowed-tools` er pre-approval, ikke restriction. Den fjerner permission-prompts for listede verktøy, men blokkerer ikke ulistede. For ekte sandbox: bruk project-level `permissions.deny` rules.
|
|
|
|
## Tidsbudsjett
|
|
|
|
< 60 sekunder totalt for hele pipelinen (manuell eller auto). Pipeline-skriptet er testbart med `node:test` uten LLM-kall.
|
|
|
|
## Eksempler
|
|
|
|
**Plugin-arbeid:**
|
|
|
|
```
|
|
cd plugins/llm-security
|
|
# ... arbeid frem til 65% kontekst ...
|
|
# Auto-trigger: ved 70% fyrer Stop hook automatisk:
|
|
# → skriver plugins/llm-security/NEXT-SESSION-PROMPT.local.md
|
|
# → committer ARTEFAKTEN (ikke andre dirty filer)
|
|
# → IKKE pusher (du gjør det selv)
|
|
git push # når klar
|
|
```
|
|
|
|
**Manuell trigger med flagg:**
|
|
|
|
```
|
|
/graceful-handoff refactor-auth --no-commit
|
|
# → skriver plugins/<rot>/NEXT-SESSION-refactor-auth.local.md
|
|
# → ingen git-operasjoner
|
|
```
|
|
|
|
**Ny sesjon:**
|
|
|
|
```
|
|
claude --resume
|
|
# SessionStart hook auto-injiserer handoff-innholdet i konteksten
|
|
# Du kan starte å jobbe direkte
|
|
```
|
|
|
|
## Tester
|
|
|
|
```bash
|
|
node --test plugins/graceful-handoff/tests/
|
|
```
|
|
|
|
36 tester på tvers av:
|
|
- `skill-structure.test.mjs` — frontmatter + commands/-fjerning (8)
|
|
- `scripts/handoff-pipeline.test.mjs` — pipeline JSON, idempotens, no-staging-regression, edge cases (11)
|
|
- `hooks/statusline-monitor.test.mjs` — terskler, null payload, malformed JSON (9)
|
|
- `hooks/stop-context-monitor.test.mjs` — estimering, lock-fil, stub pipeline (7)
|
|
- `hooks/session-start-load-handoff.test.mjs` — source filter, multi-level search, archive (9)
|
|
- `plugin-manifest.test.mjs` — plugin.json schema, CHANGELOG (6)
|
|
|
|
## Begrensninger og åpne antakelser
|
|
|
|
- **statusLine-plassering i `hooks/hooks.json`** er en åpen antakelse. Verifiser med smoke-test; fallback er å flytte til global `~/.claude/settings.json`.
|
|
- **Token-estimering ±10%** mot Claude's reelle telling. 70%-tersklen er konservativ.
|
|
- **Issue [#26251](https://github.com/anthropics/claude-code/issues/26251)** — `disable-model-invocation: true` regression kan blokkere user-invocation. Manuell smoke-test før du stoler på det.
|
|
- **Push gjenstår alltid manuell.** Auto-eksekvering pusher ALDRI — irreversibel handling beholdes hos bruker.
|
|
- Auto-trigger respekterer pre-commit hooks (secrets, pathguard) — bypasser ALDRI med `--no-verify`.
|
|
|
|
## Sikkerhet
|
|
|
|
- Pipeline stager **kun** handoff-artefakten + REMEMBER.md/TODO.md (hvis de finnes). Stagger ALDRI andre dirty filer (regression-test håndhever dette).
|
|
- Filer er `*.local.md` → matches av `.gitignore`-mønstre i alle prosjekter
|
|
- Ingen nettverks-kall (ingen WebSearch, ingen Agent-delegering)
|
|
- Bash sub-scoped: `Bash(git:*)`, `Bash(jq:*)`, `Bash(node:*)`, `Bash(find:*)`, `Bash(pwd:*)`
|
|
|
|
## Lisens
|
|
|
|
MIT
|