# Session Wrap

> The session-transition front door. Bare invocation TRIAGES the session — context utilization, task-boundary state from current.md, git state, armed /goal — announces one route, then ACTS: continue (checkpoint + one line), clear-next (durable state to disk, git verb, emit /clear), or end-window (full wrap, handoff rendered to handoff-prompt.md, Pick-up-here block). Use at any transition moment: ta…

- **Type:** Skill
- **Install:** `agentstack add skill-aberson-claude-skills-session-wrap`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [aberson](https://agentstack.voostack.com/s/aberson)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [aberson](https://github.com/aberson)
- **Source:** https://github.com/aberson/claude-skills/tree/main/session-wrap

## Install

```sh
agentstack add skill-aberson-claude-skills-session-wrap
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# session-wrap

One decision-making front door for session transitions. Invoked bare, it TRIAGES the
session against mechanical signals, announces the chosen route in one line, then ACTS.
No mid-run (y/n) gates — bare invocation is the safest mode. The single ask-first
exception is a detected parallel-session anomaly before the git verb; the detection
pre-flight is the Git-verb router's Step A (section below).

Division of labor: `/task-handoff` is the checkpoint *library* this skill calls; the
`current.md` file contract is owned by
`.claude/references/task-state-schema.md` (workspace reference, not published in
this mirror; cite it, never restate it). Phase-shipping territory (README/plan updates, issue
closing, push-everything) belongs to `/repo-update` — the git-verb router delegates
there; this skill never duplicates it.

---

## Threshold constants (operator-tunable)

Defaults from community threshold doctrine (proactive boundary at ~60% utilization,
~120k-token quality "dumb zone", 95% auto-compact "too late"). The internal
degradation floor is unmeasured — these are defaults, not findings; when the floor
gets measured, one edit here moves them.

| Constant | Value | Raw-token proxy | Meaning |
|---|---|---|---|
| `CONTINUE_MAX_UTIL` | 60% |  `continue` |
| `CLEARNEXT_UTIL` | 60% | >120k tokens | At or near a task boundary -> `clear-next` |
| `CLEARNEXT_FORCE_UTIL` | 75% | >150k tokens | Take the next boundary aggressively, regardless of task state |
| (end-window) | — | — | No threshold. Operator intent only ("done", "end of day", explicit `--end`), or no agent-completable next action exists |

Raw tokens are not a percentage: a percentage needs a model-aware window size, and
extended (>200k) windows exist on this machine. When the window size is unknown, apply
the raw-token proxies directly and, if a percentage is reported at all, SAY the
denominator is assumed — e.g. `162,340 tokens (~78% assuming a 200k window)`. Never
present an assumed percentage as a measurement.

---

## Step 0 — triage: collect, score, announce

**Read this session's own state first.** Before deriving any next action or route, read
**this session's** `sessions/.md` (the session UUID from your scratchpad path;
fallback to the derived `current.md` rollup, then the freshest session file — resolution +
the per-session model are owned by the schema doc). Reading your OWN session file, not the
shared `current.md` rollup, is what keeps a concurrent window's task from surfacing as this
session's state. Absent file = no recorded task — it gets created on the first route write.
That file plus git is the state; conversation prose is not. Every next action this skill
writes or renders derives from it, never in parallel from prose.

Collect four signals:

**(a) Context utilization.** Chosen signal (decision doc:
[`docs/investigations/context-signal-spike.md`](../../../docs/investigations/context-signal-spike.md)):
the `message.usage` sum (`input_tokens + cache_creation_input_tokens +
cache_read_input_tokens`) of the LAST top-level main-chain assistant entry in the
session transcript JSONL. Run the reference implementation rather than reimplementing
the guarded recipe: `docs/investigations/high-context-usage-tools/read-context-signal.ps1`.
Skill-mode transcript resolution: glob `~/.claude/projects//*.jsonl` and
require EXACTLY ONE file modified within the last ~2 minutes — zero or more than one
candidate is ambiguous and means signal absent (sibling-session risk; never blindly
take the newest). When the signal is absent for ANY reason, print exactly this line
(ASCII hyphen — this exact wording is the contract) and triage on (b)-(d) alone:

    context signal unavailable - boundary-only triage

Never guess, estimate, or fabricate a token count or percentage — a fabricated number
is indistinguishable from a real one and steers the route wrong (measurement-validity
rule).

**(b) Task-boundary state.** From the `current.md` read above: Status + Next Action.
Plus the active plan's step `**Status:**` lines (plan located per CLAUDE.md § Plan
location — `plan.md`/`master_plan.md` at the project root or under
`plans/`/`docs/`/`documentation/`; descriptor-contract §4), and whether the
just-finished turn completed a step or phase. At/near a boundary = Status COMPLETE, a step just flipped
DONE, or the turn closed a task. Mid-task = everything else.

**(c) Git state.** Per touched repo — a multi-project session (2+ distinct project
dirs edited, or a project repo plus `dev/` workspace-root files) checks EACH repo:
branch, short SHA, dirty-file count, ahead-of-origin count.

**(d) Armed `/goal`.** An unmet agent-completable goal biases `continue`.

**Score — first match wins:**

1. Operator intent ("done", "end of day", explicit `--end`), or no agent-completable
   next action exists -> `end-window`.
2. Utilization >= `CLEARNEXT_FORCE_UTIL` -> `clear-next` now (finish only the
   in-flight edit, not the task).
3. Utilization >= `CLEARNEXT_UTIL` and at/near a boundary -> `clear-next`.
4. Everything else — below `CONTINUE_MAX_UTIL` and mid-task, signal absent with no
   operator intent, armed unmet `/goal`, or any uncertainty -> `continue`.
   `continue` is the bias because it is the cheapest wrong answer.

**Announce, then act.** Print exactly ONE triage line BEFORE acting, so a wrong route
is visible and correctable immediately:

    triage:  | context:  | boundary: )> | git:  | goal: 

(substitute the fail-loud contract line for the context segment when the signal is
absent).

---

## Route: `continue`

Invoke `task-handoff --loop` via the Skill tool. Screen output is ONE composed line
total — the library's own `Checkpoint written.` line is subsumed into it, never
printed separately:

    Checkpoint written — continuing ().

Nothing else — no summary, no rendered prompt, no wall of text.

## Route: `clear-next`

Durable state to disk, then the git verb, then hand the operator `/clear`. Execute in
this exact order — `current.md` first, render second, screen last:

1. **Write `current.md`** — invoke `task-handoff --loop --no-commit` via the Skill
   tool (read-merge-write per the schema doc, which owns the per-field
   append-vs-overwrite rules). Next Action = the exact command or skill invocation.
   **No-regress clause:** the read-merge-write must never regress a Next Action that
   is already the exact next command from a boundary write made earlier this same
   turn/step (e.g. plan-expedite's `--next-task` write) — preserve it verbatim; the
   render carries Next Action verbatim (rendering contract item 4), so an overwrite
   here would silently drop it.
   The route's own git verb (step 5) carries the commit — same no-double-commit
   rationale as build-phase Step 2e. Do NOT use `--next-task` here: it commits and
   pushes itself, doubling up with the route's git verb.
2. **Decisions log + salvage sweep** (section below) — bounded; results land in
   `current.md` (§ Parked / Critical Gotchas) and the render, not on screen.
3. **Cheap memory subset only:** correct the project's MEMORY.md status pointer line
   if this session made it wrong, and park unfiled TODOs; the full
   memory/lessons/friction passes are end-window-only.
4. **Render `handoff-prompt.md`** from `current.md` + the decisions log (rendering
   contract below).
5. **Execute the git verb** — run the Git-verb router (section below): anomaly
   pre-flight, commit-owner decision, additive recommendation, one-line report.
   The router's base commit is the carrying commit step 1 deferred; when it
   delegates, `/repo-update`'s commit sweeps `current.md` in.
6. **Screen: the Pick-up-here block** (contract below), exact next command =
   `/clear`. The next window resumes via the SessionStart hook re-injecting
   `current.md`.

## Route: `end-window`

Everything in `clear-next`, same order — including step 1's
`task-handoff --loop --no-commit` write — with these passes inserted after step 3
(before the render, so their outcomes are renderable):

- **Full memory pass — read-then-report (invariants 1 and 4).** Read MEMORY.md
  (`~/.claude/projects//memory/MEMORY.md`) fully
  (if the first Read reports a partial load, continue with offset reads until the
  whole file is covered — a partial read cannot honestly claim "Read MEMORY.md"). For
  every topic touched this session, state `existing entry for  was
  current|stale` or `no existing entry for ` BEFORE describing any change.
  Update stale entries in place; never append a duplicate. Multi-project sessions
  check each touched project's heading. If MEMORY.md exceeds 200 lines or any line
  exceeds 200 chars, add a `MEMORY.md over budget (X lines)` invariant flag to the
  digest — do not auto-trim.
- **Lessons-learned sync.** Any feedback memory created or edited this session syncs
  both layers: long form in `docs/lessons-learned.md` (matching `### Title` heading +
  ToC entry), thin pointer in the `feedback_*.md`, index line in MEMORY.md. Never
  leave the long form duplicated in both layers. Project-scoped memories do not sync
  there.
- **Friction review.** Scan the session for patterns that would slow future sessions:
  failed commands that needed rework, wrong assumptions, missing context, clunky
  workflows. Actionable friction becomes a feedback memory (then syncs per the bullet
  above). Skip one-off flukes entirely and never record retry counts (invariant 6). A
  clean session reports nothing.
- **Docs staleness.** If plan.md or a session doc no longer reflects what shipped,
  update it now or name it in the digest — never silently leave a stale doc. Cheap
  side-check: if `docs/friction-catalog.md` exists and any `feedback_*.md` is newer
  than its indexed date, add a `friction catalog stale` digest flag (do not
  regenerate it).

The Pick-up-here block's exact next command becomes the fresh-window opener instead
of `/clear` (contract below) — the SessionStart hook does not fire on plain startup,
so the opener must carry the pointer. With opt-in `--spawn` (section below), the deep
link then auto-opens the next window pre-filled with that opener; the block on screen
stays the baseline.

---

## Git-verb router (clear-next + end-window, step 5)

The single owner of the route's git verb. Four steps, in order: A anomaly
pre-flight, B commit owner, C additive recommendation, D report. Multi-project
sessions run Steps A-C independently PER TOUCHED REPO — mixed outcomes across
repos are legal — and Step D joins the segments.

**Step A — anomaly pre-flight (before ANY verb, delegation included).**
CLAUDE.md § Parallel session safety and § Session wrap & commit discipline stay
senior to execute-by-default. Run all four checks BEFORE Step B
(PowerShell-first). Scope: check 1 runs at the workspace root — a trigger
there downgrades ALL repos; checks 2-4 run per touched repo — a trigger
downgrades that repo only.

On a trigger, the downgraded scope's Steps B/C are WITHHELD — the route is
not: the render and the Step D report still run, the pending repo's segment
reads `ask-first pending`, and route step 6 does NOT emit `/clear` while any
segment is pending. The Pick-up-here block's exact next command becomes the
ask response — approve or adjust the presented plan — never `/clear` past an
open gate (never co-locate a gate and an action; rendering-contract item 4).
Presentation: base-action path = the scoped add list + the commit message;
delegate path = the intended `/repo-update` invocation + the trigger evidence.
This ask is the single sanctioned (y/n) gate in this skill. The checks:

    # 1. Foreign state file at the workspace root
    Get-ChildItem -Force \.plan-expedite-state.* | Where-Object { $_.LastWriteTime -gt (Get-Date).AddHours(-24) }
    # 2. Worktrees beyond the main checkout, then two activity probes per hit
    git worktree list
    git log -1 --format=%cr 
    Get-Item \.git\worktrees\*\index -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -gt (Get-Date).AddHours(-24) }
    # 3. Cross-repo/foreign edits
    git status --porcelain
    # 4. Foreign commits: reachable from other refs, not from this HEAD
    git log --all --not HEAD --since='1 hour ago' --oneline

Trigger tests, one per check:

1. **Foreign state file** — a hit whose plan path does not match this
   session's active plan (from `current.md`'s Task / plan reference).
   Plan-mismatch or unknown = foreign = trigger.
2. **ACTIVE foreign worktree** — a worktree beyond the main checkout whose
   branch tip committed within ~24h OR whose git index mtime is within ~24h
   (index mtime moves on staging/checkout activity before any commit exists —
   a tip-only test reads an uncommitted parallel session as stale). A worktree
   failing both probes is stale: ONE digest note line, never an ask.
3. **Cross-repo/foreign edits** — a modified TRACKED file outside this
   session's edit set. The edit set = the files the executor knows it edited
   this session (its own history), corroborated by `current.md`'s Completed
   entries; Key Files is a CURATED subset (schema: populated only on notable
   discoveries), never the authoritative touched list. Untracked strays never
   fire — they are simply not added.
4. **Foreign commits** — any output line. `--not HEAD` excludes this session's
   own HEAD-lineage checkpoints; the session's own commits on OTHER refs (e.g.
   an unmerged build-step worktree branch) may still surface — that ask errs
   safe.

**Step B — commit owner (exactly one).** The scoped commit+push of session
files is the ALWAYS-RUN base action unless explicitly delegated:

- **Delegate to `/repo-update`** — phase/feature completed this session.
  Detection: the active plan (discovered per Step 0(b)) exists, has >= 1
  step, and every step reads `**Status:** DONE` (the >= 1-step guard blocks
  the vacuous all-DONE of a step-less pointer plan), OR a build-phase
  completion report was produced this session. Action: invoke `/repo-update`
  via the Skill tool — it owns shipping (README/docs updates, commit, push,
  posterity issue); this skill duplicates none of that work. (Task-state is now
  gitignored, so nothing sweeps in `current.md`; route step 1's session-file write
  is already durable on disk.) If `/repo-update` fails
  partway, run the base action below so nothing is stranded, and surface the
  repo-update failure in the digest.
- **Base action** — everything else. Detection: the delegate test above did
  not match. Action: scoped `git add` of the session edit set (as defined in
  check 3) + commit + push, EXECUTED by default. (Task-state is now gitignored —
  `sessions/*.md` and the derived `current.md` are NOT committed; route step 1's
  session-file write already durably landed on disk, so there is no
  carrying-commit of state to defer.) A clean tree is a LEGAL outcome — e.g. a boundary
  write earlier this turn (plan-expedite's `--next-task`) already carried the
  commit+push; skip the empty commit and report `nothing to commit` in Step D.
  Clean but AHEAD of origin (an earlier push failed): still push, and report
  `pushed  pending` as the verb outcome instead.
  Never `git add -A` — every add names explicit
  paths; never add `handoff-prompt.md`.

**Step C — additive recommendation (independent of Step B).** Step C runs
regardless of which owner committed (withheld only when Step A downgraded its
scope, like Step B) and NEVER changes the commit owner; the recommended
COMMAND is never run mid-wrap.
Detection: the plan doc structurally changed this session — `### Step`
headings added/removed/renumbered, or step fields (Type / Depends on /
Done when) edited; more than Status-line flips. Action: add ONE recommendation
line to the digest —

- plan-review ran this session (in `current.md` Completed or this
  conversation), or the plan carries a fresh review marker → recommend
  `/repo-sync`. Order guard: never repo-sync before plan-review
  ([`.claude/rules/plan-and-issue-flow.md`](../../rules/plan-and-issue-flow.md)).
- review sta

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [aberson](https://github.com/aberson)
- **Source:** [aberson/claude-skills](https://github.com/aberson/claude-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-aberson-claude-skills-session-wrap
- Seller: https://agentstack.voostack.com/s/aberson
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
