# Session Handoff

> Session handoff writer. Use when the user asks to hand off, wrap up, end the session, prepare next-session notes, record completed work, or write the final session entry. Writes Board updates and appends a session log entry.

- Skill: `57luo/session-handoff` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add 57luo/session-handoff`
- Raw SKILL.md: https://api.skillmd.com/api/skills/57luo/session-handoff/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: 57Luo (https://skillmd.com/u/57luo)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/57luo/session-handoff

---


# Session Handoff

Write the session handoff: update the Board, sync related docs, and append a session entry.

## Shared Handoff Schema

Read `session-handoff/schema/handoff.md` for handoff file structure, Active Work column semantics, Board vs Log boundaries, write guards, Related Docs freshness, Open Questions pruning, and Spectra Board scope. The sections below define handoff-specific behavior and fallback details; when duplicated rules differ, the shared schema is authoritative unless this skill states a handoff-specific exception.

## Artifact Boundary

- Write handoff state only under shared project paths, preferably `.session/handoff/` at the main repo/worktree root.
- Related-doc writes may occur elsewhere in the project only when the doc is
  listed or clearly affected by this session's work.
- `Related Docs` entries must follow `Related Docs Scope` in the shared schema:
  use them for durable docs that need a sync check because of the claimed work
  item, not for source/test/generated files, Spectra workflow artifacts, or
  files related to the handoff itself.
- Never write runtime handoff data inside skill installation directories.
- Use `.session/handoff/YYYY-MM-DD.md` for today's handoff; create it if missing.
- Historical handoffs are read-only. Record corrections in today's handoff rather than editing older daily files.

## Handoff Root Resolution

Follow `## Handoff Root Resolution` in `schema/handoff.md`. As a writer skill: refuse to write a divergent worktree-local handoff directory and report it as a migration/mismatch warning.

## Core Rules

- Treat the Board as living state and the Session Log as append-only history.
- `session-handoff` is the terminal sync point for the current task. Do not require
  a separate `session-update` before ending a completed/paused task; fold the
  relevant Board update logic into this handoff.
- Compare current dirty files with any baseline captured by `session-claim` when available.
- Attribute only this session's intentional changes to the session entry.
- Keep `Remaining` for claimable unfinished work only.
- Do not duplicate active/in-progress/paused work across both `Active Work` and `Remaining`.
- Keep completed Active Work rows for same-day visibility.
- Preserve other sessions' Active Work rows.
- If the session moved to another worktree or branch after claim (for example through Spectra `worktree: true` apply flow), refresh this session's Active Work row to match the actual checkout before marking status: set `Workspace` and `Branch` to the current values. When marking the row `completed`, clear `Branch` and fill `MergeCommit` with the landing commit's 7-character short SHA.
- Before changing this session's Active Work row, compare the current `git
  rev-parse --show-toplevel` and current branch/ref with the row's `Workspace`
  and `Branch`. If they differ because this session moved worktrees/branches,
  update the row under the Board write guard before marking status.
- If another different work item is still `in-progress` in the same normalized
  `Workspace` and `Branch`, preserve that row but report the occupied-checkout
  conflict in the session entry or remaining risks.
- Update related docs when implementation or discussion changed assumptions, logic, mappings, decisions, tasks, or blockers.
- If related docs are intentionally not updated, record why in `#### Docs Updated`.
- Even when `session-claim` was not run, write a session entry for substantial completed work and clearly note that no durable baseline was available.
- When creating today's handoff from an older file, follow the inheritance rules in `## Artifact Boundary` of the shared schema and renumber inherited Active Work rows per the schema's `Slot` rule (fresh `S1` sequence).
- Keep `Remaining` as the claimable queue and `Phase Plan` as ordering,
  dependency, or phase context. Do not carry completed/archived work forward in
  `Phase Plan` as a historical checklist, and do not duplicate the complete
  `Remaining` queue there.

## Concurrent Write Guard

Follow `## Concurrent Write Guard` in `schema/handoff.md` — prefer the `scripts/locked_write.py` helper over manual lock steps. Apply the guard to `Active Work`, `Phase Plan`, `Remaining`, `Related Docs`, `Open Questions`, `Blockers`, and `Spectra`. Never hold the Board lock while invoking `insert_session_entry.py` (it acquires the same lock): write Board edits under the lock, release, then call the script — or script first, then Board edits under a fresh lock.

## Quote-Trace Discipline

Follow `## Quote-Trace Discipline` in `schema/handoff.md`.

## Claim Board Scope

- If Spectra is detected by CLI or `openspec/`, `Active Work`, `Remaining`, and `Phase Plan` should track Spectra change names only.
- In Spectra projects, do not add ad-hoc/non-Spectra work to claimable Board sections. Record ad-hoc work in the Session Entry, `Open Questions`, `Blockers`, or `Related Docs`.
- In Spectra projects, move existing non-Spectra `Remaining` entries out of the claimable queue during end handoff if current sources confirm they are not Spectra changes.

## Spectra Discipline

If Spectra is relevant:

1. Follow `## Spectra Discovery` in `schema/handoff.md` for detection (the
   collector output's `spectra` section covers it; report a non-null
   `spectra.error` as a CLI failure, not as "Spectra absent").
2. Update relevant `tasks.md` checkboxes and change notes when implementation progress or decisions changed.
3. Do not archive, unpark, apply, or ingest Spectra changes from this skill unless the user explicitly asks for that separate action.

## Handoff Board Sync

`session-handoff` must perform the subset of `session-update` that is needed to make
the Board truthful after the current task:

- `Active Work`: mark the current row completed, paused, or still in progress.
  Refresh `Workspace` and `Branch` first if the actual checkout changed. When
  marking the row `completed`, clear `Branch` and fill `MergeCommit` with the
  landing commit's 7-character short SHA. See the shared schema's Active Work
  Schema for full per-column lifecycle rules.
- `Phase Plan`: update only milestones, dependencies, order, or phase notes
  directly changed by this task. Remove completed/archived checklist entries
  unless they are brief context for current work.
- `Remaining`: remove completed/closed work; keep unfinished claimable work; do
  not duplicate work that remains active/paused in `Active Work`.
- `Related Docs`: check whether the listed docs need updates because of this
  task, then add, remove, or retag durable documentation entries as needed,
  preserving `triggers:` notes when possible
  and enforcing `Related Docs Scope` from the shared schema.
- `Open Questions`: close only questions resolved by this task/current sources;
  add only unresolved questions discovered during this session that affect
  future work.
- `Blockers`: close only blockers resolved by this task/current sources; add
  only concrete blockers that prevent progress and include the blocked work item
  plus required unblock action.
- `Spectra`: update status/counts/parked-active notes relevant to the current
  change when Spectra is detected. If a Spectra change was archived, unparked,
  or moved to/from active during this session, sync `## Spectra` Active,
  Parked, and recent archive entries to match current `spectra list`,
  `spectra list --parked`, and archive state for that change.

Use `session-update` separately only for broader queue grooming or stale Board
cleanup that is not caused by the current task.

## Board vs Log Boundary

- **Board** (`## Active Work` through `## Spectra`) = current state. Next agent
  must be able to pick up work by reading only the Board.
- **Session Log** (`### Session {N}` and below) = append-only history. May be long;
  preserves decision journey, reflections, trade-offs, verification detail.
- **Related Docs** = durable documentation sync checks for claimed work.
  **Spectra artifacts** = workflow materials unless explicitly maintained as
  documentation by the claimed task. Neither replaces Session Log reasoning
  notes.

Concrete enforcement during handoff:

- Baseline dirty files: Board keeps a one-line summary
  (`Session N baseline: X modified + Y untracked; see Session N Notes`).
  Detailed listing belongs in the Session Log entry's Notes. If the baseline
  is later superseded (e.g., committed), append a status note in the Log
  (`Status: superseded by commit <SHA>`); do NOT delete from the Log.
- Resolved Board notes (conflict warnings, stale "inherited from" labels,
  occupancy notes that no longer apply) must be removed from the Board on
  handoff and, if historically interesting, summarized into the Session Log
  entry's Notes.
- Do not use `(inherited from YYYY-MM-DD)` labels on Board sections after the
  section has been touched today. Use plain `## Related Docs`; freshness is
  tracked per-entry via the `last reviewed: YYYY-MM-DD` mechanism below.

## Open Questions Prune

Handoff is wrap-up, not Board grooming. It surfaces stale Open Questions but
does not interactively prune them — the three-way prune (move / delete / keep)
is owned by `session-update`. Definition of staleness lives in
`## Open Questions and Ideas Backlog` in `schema/handoff.md`.

- Detect: an Open Question unchanged for 14+ days AND not affecting any current
  Active Work / Remaining / Phase Plan entry. Item-specific questions tied to an
  active/parked/relevant item are exempt while that item is in scope.
- Surface: list each detected question in the handoff output as a
  `prune candidate (run /session-update to prune)`. Do not delete, move, or
  reset its clock here.
- Exception: only when the user explicitly asks to groom during handoff, run
  `session-update`'s interactive prune flow — do not re-implement it here.

Open Questions directly resolved by this session's work are still closed during
Handoff Board Sync (see `Open Questions` under that section); that is recording
resolution, not grooming.

### Ideas Backlog Review (only when this session archived a Spectra change)

When a Spectra change is archived during this session, check
`.knowledge/ideas-backlog.md` for entries whose status references that change
(e.g. `status: active`). Invoke the `project-logbook` skill (via the Skill
tool) with `--milestone move` to move the completed entry from the ideas
backlog into `.knowledge/milestones.md`, or with `--backlog update` if only
status/`last-seen` needs refreshing. NEVER edit `.knowledge/ideas-backlog.md`
or `.knowledge/milestones.md` directly from this skill — all writes must go
through project-logbook's scripts (`backlog_move.py` / `backlog_insert.py`),
which validate the schema and rebuild `_backlog_index.json`; a direct edit
leaves the index stale. Record the outcome in `#### Docs Updated`.

## Related Docs Freshness

- Each `## Related Docs` entry may carry a `last reviewed: YYYY-MM-DD` tag.
- Each entry must follow `Related Docs Scope` from the shared schema; remove or
  migrate source/test/generated paths during handoff Board sync.
- Do not list parked Spectra change directories in `Related Docs` merely
  because those changes are queued in `Remaining`; the queued change name is
  the Board pointer. Add a parked proposal/design/spec artifact only when this
  handoff actually changed or must synchronize that artifact's content.
- Do not list archived Spectra directories in `Related Docs` as history; keep
  only the latest one or two relevant archives in `## Spectra` Recent archive.
- Only update `last reviewed` when this session actually read or synced the
  doc as part of its work. Do NOT auto-stamp based on `git diff` showing the
  file changed; "touched" is not the same as "reviewed for trigger
  correctness".
- `session-start` flags entries with `last reviewed` >30 days old (or missing)
  as `stale-check needed`.

## Spectra Section Scope

- Board `## Spectra` lists Active changes in full, plus only the parked
  changes that are relevant to current Phase Plan / Remaining / Active Work
  items. Append a one-line count `parked total: N (see spectra list --parked)`
  to point at the CLI for the rest.
- Recent archive: keep the latest one or two archives directly relevant to
  current work. Older archives can be referenced via `openspec/changes/archive/`
  rather than re-listed in the daily Board.
- Parked Spectra changes that can be claimed as future work belong in
  `Remaining`; claiming one does not imply immediate apply. `Phase Plan` should
  only explain sequencing or dependency between them.

## Handoff File Structure

The file has two layers:

- Board:
  - `## Active Work`
  - `## Phase Plan`
  - `## Remaining`
  - `## Related Docs`
  - `## Open Questions`
  - `## Blockers`
  - `## Spectra` when relevant
- Session Log:
  - `### Session N - [Title]`
  - `> summary: <one-line summary, ≤120 chars>`
  - `#### Completed`
  - `#### Notes`
  - `#### Docs Updated`
  - `#### Stopped At`
  - `#### Suggested Next Start`

The `> summary:` blockquote is required on every session entry, placed
immediately after the `### Session N` header. It provides a one-line digest
(≤120 characters) of what the session accomplished, so that `session-start`
can show recent session context without loading full entry bodies.
`insert_session_entry.py` validates its presence.

`Session N` in the log is a time-ordered counter allocated by
`insert_session_entry.py` on every handoff invocation. It is independent
of the Active Work `Slot` column (S1/S2/etc.). Title convention:

- When the session entry advances a specific Slot, prefix the title with
  the Slot ID: `### Session 3 - S2 / change2 summary`.
- When the session is ad-hoc (merge / Q&A / refactor without a claim),
  omit the Slot prefix: `### Session 2 - Merge Billy's tokens into dev/main`.

Do not assume Slot `S2` corresponds to `### Session 2`. A single Slot can
span several Log sessions; ad-hoc handoffs consume Log numbers without
consuming a Slot.

### New Entry vs Follow-up / Correction

A second handoff on the same day does NOT automatically deserve a new
`### Session {N}`. Decide which case applies:

- **New entry** - if any new code, decision, verification, or task progress
  occurred after the previous handoff, allocate a new `### Session {N}` via the
  insertion script; link it to its work item with the Slot prefix. Multiple
  Log entries for one Slot are correct and expected (Slot and Log number are
  independent axes); do not try to avoid them.
- **Follow-up / Correction** - if this handoff is a correction or addendum to
  the latest entry for the same Slot on the same day, and no new work occurred
  after that entry, do NOT allocate a new `### Session {N}`. Instead, under the
  handoff lock, append a `### Follow-up HH:MM` (addendum) or
  `### Correction HH:MM` (fixing something previously recorded) block to that
  existing Session entry. This is a plain locked Edit, not a script insertion; the script's only job is allocating and inserting a NEW numbered entry.

Never overwrite or rewrite an existing Session entry's recorded content; the
Session Log is append-only. Corrections are appended as a `### Correction`
block stating what was wrong and what is right, not by editing the original
text.

## Workflow

1. Run the deterministic collector first:
   `python <skill-dir>/scripts/collect_briefing.py --full-backlog`
   (cwd = project root; `--full-backlog` because the Ideas Backlog Review
   below needs per-item `status` metadata). One JSON blob covers: latest
   handoff path + Board content, `git status`/`log`/`worktree list`, Spectra
   detection + active/parked lists, and ideas-backlog items — use it for Board
   sync verification and the Ideas Backlog Review instead of re-running those
   commands. Fall back to manual collection only if the script fails to run.
2. Read today's handoff file or create it from the most recent unfinished Board.
3. Run Handoff Board Sync (see section above) for `Active Work`, `Phase Plan`, `Remaining`, `Related Docs`, `Open Questions`, `Blockers`, and `Spectra`.
4. Enforce Board vs Log Boundary: collapse baseline detail to summary, remove resolved Board notes, drop stale `(inherited from...)` labels. Move displaced content into the new Session Log entry's Notes when historically useful.
5. Surface stale Open Questions only: for each Open Question, check 14-day staleness and current-item relevance; list qualifying items in the output as `prune candidate`. Do NOT stop to prompt the three-way prune (move / delete / keep) — that is `session-update`'s job. See `## Open Questions Prune` above.
6. If this session archived a Spectra change, run Ideas Backlog Review (see section above) on matching entries in `.knowledge/ideas-backlog.md`.
7. Update `Related Docs` `last reviewed: YYYY-MM-DD` only on entries this session actually read or synced (not on `git diff` evidence alone).
8. Sync related docs that drifted from this session's work. Detection must NOT
   rely only on the claim-seeded `Related Docs` list (claim-time recall misses
   docs). Drive it from the session's actual changes:
   - If the project provides a docs catalog validator (e.g.
     `docs/_catalog/validate.py`), run it first and resolve any unregistered or
     stale docs — drift detection cannot flag a doc that is not catalogued.
   - If the project provides a docs catalog (e.g. `docs/_catalog/drift_match.py`
     matching changed files against per-doc `paths` globs), run it against this
     session's `git diff` and treat its output as doc sync candidates,
     independent of what claim listed.
   - Otherwise, match `git status`/`git diff --name-only` against known docs
     plus `Related Docs` `triggers:` notes.
   Either way, do not add implementation source, test, generated, or lock files
   to `Related Docs` merely because they changed.
9. Decide New Entry vs Follow-up / Correction (see that section above). If this is a Follow-up / Correction to the same Slot's latest same-day entry with no new work after it, skip step 9a: instead append a `### Follow-up HH:MM` or `### Correction HH:MM` block to that existing entry under the handoff lock, then go to step 11.
   9a. Otherwise, build the session entry with completed work, notes (include relocated baseline detail and any conflict-resolution history), docs updated, stopped-at state, next-start guidance, and the Backlog Review audit summary if any candidates were processed.
10. Append the new session entry with `scripts/insert_session_entry.py` so session order remains stable.
11. **Project Knowledge Review gate**: Before the final report, evaluate whether
    this session produced knowledge worth preserving. Check the session's
    Completed work and Notes against these criteria:
    - Non-obvious bug fix (root cause wasn't apparent, easy to hit again)
    - New pattern or technique likely to recur
    - Architecture change (new module, changed data flow, new schema)
    - Build / environment / platform issue
    - Process or workflow convention change
    - User correction on a reusable rule

    If **any** criterion is met, invoke `/project-logbook --review` before
    proceeding to step 12. Review is **candidate-only and MUST NOT block
    handoff**: it lists at most 3 KB candidates in the final report and does NOT
    stop to prompt or write. Entries are written later only if the user says
    `record KB <n>` (which routes to `--record`). Also surface any "KB recall
    gap" the review detects (a mistake an existing KB entry covered but that was
    not auto-recalled, or the same error twice) and name the backlog item it
    activates. If no criterion applies (e.g., pure doc edits, backlog grooming,
    propose-only sessions, routine config changes), skip the review and note
    "KB review: skipped (no KB-worthy content)" in the report.
12. Report the handoff file, session number (or the Follow-up/Correction target entry), docs updated, OQ items moved to Backlog, Backlog Review outcomes, KB review outcome, occupied-checkout/stale-row warnings, and remaining risks.

## Session Entry Insertion

Write the entry content to a temporary file under `.session/scratch/` (e.g.
`.session/scratch/session-entry.md`), then pass it via `--entry-file`:

```powershell
python <skill-dir>\scripts\insert_session_entry.py <handoff-file> --entry-file .session/scratch/session-entry.md
```

The script reads entry content as UTF-8, locks the handoff file, auto-allocates the next session number, rewrites the first `### Session {N}` header in the entry, and inserts the entry in numeric order. Prefer `--entry-file` on Windows so PowerShell pipeline encoding cannot corrupt Chinese headings.

After successful insertion, delete the temporary entry file. If `.session/scratch/` is empty after deletion, remove the directory as well.





