# 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
