mirror of https://github.com/garrytan/gstack.git
188 lines
6.9 KiB
Cheetah
188 lines
6.9 KiB
Cheetah
---
|
|
name: context-restore
|
|
preamble-tier: 2
|
|
version: 1.0.0
|
|
description: |
|
|
Restore working context saved earlier by /context-save. Loads the most recent
|
|
saved state (preferring the current branch, falling back across branches) so
|
|
you can pick up where you left off — even across Conductor workspace handoffs.
|
|
Use when asked to "resume", "restore context", "where was I", or
|
|
"pick up where I left off". Pair with /context-save.
|
|
Formerly /checkpoint resume — renamed because Claude Code treats /checkpoint
|
|
as a native rewind alias in current environments. (gstack)
|
|
allowed-tools:
|
|
- Bash
|
|
- Read
|
|
- Glob
|
|
- Grep
|
|
- AskUserQuestion
|
|
triggers:
|
|
- resume where i left off
|
|
- restore context
|
|
- where was i
|
|
- pick up where i left off
|
|
- context restore
|
|
---
|
|
|
|
{{PREAMBLE}}
|
|
|
|
# /context-restore — Restore Saved Working Context
|
|
|
|
You are a **Staff Engineer reading a colleague's meticulous session notes** to
|
|
pick up exactly where they left off. Your job is to load the most recent saved
|
|
context and present it clearly so the user can resume work without losing a beat.
|
|
|
|
**HARD GATE:** Do NOT implement code changes. This skill only reads saved
|
|
context files and presents the summary.
|
|
|
|
**Default: prefer the most recent checkpoint saved on the CURRENT branch; if
|
|
this branch has none, fall back to the most recent across ALL branches.** The
|
|
fallback is for Conductor workspace handoff — a context saved on one branch can
|
|
be resumed from another. The current-branch preference exists because every
|
|
worktree of a repo shares one checkpoints directory (same origin-derived slug),
|
|
so without it `/context-restore` in one worktree could silently load a sibling
|
|
worktree's newer checkpoint.
|
|
|
|
**Do NOT hard-filter the candidate set to the current branch** — other-branch
|
|
checkpoints stay in the set as a fallback. They are just ordered *after* the
|
|
current branch's own, so a current-branch save is never shadowed by a newer
|
|
sibling-worktree save. (`/context-save list` is the flow that hard-scopes to one
|
|
branch.)
|
|
|
|
---
|
|
|
|
## Detect command
|
|
|
|
Parse the user's input:
|
|
|
|
- `/context-restore` → load the most recent saved context (any branch)
|
|
- `/context-restore <title-fragment-or-number>` → load a specific saved context
|
|
- `/context-restore list` → tell the user "Use `/context-save list` — listing
|
|
lives on the save side" and exit. No mode detection here.
|
|
|
|
---
|
|
|
|
## Restore flow
|
|
|
|
### Step 1: Find saved contexts
|
|
|
|
```bash
|
|
{{SLUG_SETUP}}
|
|
eval "$(~/.claude/skills/gstack/bin/gstack-paths)"
|
|
CHECKPOINT_DIR="$GSTACK_STATE_ROOT/projects/$SLUG/checkpoints"
|
|
if [ ! -d "$CHECKPOINT_DIR" ]; then
|
|
echo "NO_CHECKPOINTS"
|
|
else
|
|
# Use find + sort instead of ls -1t. Two reasons:
|
|
# 1. Canonical order is the filename YYYYMMDD-HHMMSS prefix (stable across
|
|
# copies/rsync). Filesystem mtime drifts and is not authoritative.
|
|
# 2. On macOS, `find ... | xargs ls -1t` with zero results falls back to
|
|
# listing cwd. `sort -r` on empty input cleanly returns nothing.
|
|
# Scan the 200 newest so a current-branch checkpoint sitting below a burst of
|
|
# sibling-worktree saves can still be found; the result is capped at 20 below.
|
|
ALL=$(find "$CHECKPOINT_DIR" -maxdepth 1 -name "*.md" -type f 2>/dev/null | sort -r | head -200)
|
|
if [ -z "$ALL" ]; then
|
|
echo "NO_CHECKPOINTS"
|
|
else
|
|
# Order current-branch checkpoints first, other branches after. A git branch
|
|
# is checked out in at most one worktree, and all worktrees of a repo share
|
|
# one checkpoints dir (same origin-derived slug), so without this preference
|
|
# `/context-restore` in worktree A could load worktree B's newer checkpoint.
|
|
# Cross-branch resume (Conductor handoff) is preserved as the fallback: when
|
|
# the current branch has no checkpoint, the full newest-first set is used.
|
|
# CURRENT_BRANCH may be pre-set (tests); otherwise resolve it from git.
|
|
: "${CURRENT_BRANCH:=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)}"
|
|
SAME=""; OTHER=""
|
|
while IFS= read -r f; do
|
|
[ -n "$f" ] || continue
|
|
b=$(grep -m1 '^branch:' "$f" 2>/dev/null | sed 's/^branch:[[:space:]]*//')
|
|
if [ -n "$CURRENT_BRANCH" ] && [ "$b" = "$CURRENT_BRANCH" ]; then
|
|
SAME="${SAME}${f}
|
|
"
|
|
else
|
|
OTHER="${OTHER}${f}
|
|
"
|
|
fi
|
|
done <<EOF
|
|
$ALL
|
|
EOF
|
|
# Cap at 20: a user with 10k saved files shouldn't blow the context window.
|
|
FILES=$(printf '%s%s' "$SAME" "$OTHER" | grep -v '^[[:space:]]*$' | head -20)
|
|
echo "$FILES"
|
|
fi
|
|
fi
|
|
```
|
|
|
|
**Candidates include every `.md` file in the directory**, but they are ordered
|
|
**current-branch-first** (the branch is read from each file's `branch:`
|
|
frontmatter). Other-branch files stay in the set as a fallback, which preserves
|
|
Conductor workspace handoff when the current branch has no checkpoint of its own.
|
|
|
|
### Step 2: Load the right file
|
|
|
|
- If the user specified a title fragment or number: find the matching file among
|
|
the candidates.
|
|
- Otherwise: load the **first file returned by Step 1 above** — that is the
|
|
newest `YYYYMMDD-HHMMSS` checkpoint for the current branch, or, if the current
|
|
branch has none, the newest across all branches.
|
|
|
|
Read the chosen file and present a summary:
|
|
|
|
```
|
|
RESUMING CONTEXT
|
|
════════════════════════════════════════
|
|
Title: {title}
|
|
Branch: {branch from frontmatter}
|
|
Saved: {timestamp, human-readable}
|
|
Duration: Last session was {formatted duration} (if available)
|
|
Status: {status}
|
|
════════════════════════════════════════
|
|
|
|
### Summary
|
|
{summary from saved file}
|
|
|
|
### Remaining Work
|
|
{remaining work items}
|
|
|
|
### Notes
|
|
{notes}
|
|
```
|
|
|
|
If the current branch differs from the saved context's branch, note this:
|
|
"This context was saved on branch `{branch}`. You are currently on
|
|
`{current branch}`. You may want to switch branches before continuing."
|
|
|
|
### Step 3: Offer next steps
|
|
|
|
After presenting, ask via AskUserQuestion:
|
|
|
|
- A) Continue working on the remaining items
|
|
- B) Show the full saved file
|
|
- C) Just needed the context, thanks
|
|
|
|
If A, summarize the first remaining work item and suggest starting there.
|
|
|
|
---
|
|
|
|
## If no saved contexts exist
|
|
|
|
If Step 1 printed `NO_CHECKPOINTS`, tell the user:
|
|
|
|
"No saved contexts yet. Run `/context-save` first to save your current working
|
|
state, then `/context-restore` will find it."
|
|
|
|
---
|
|
|
|
## Important Rules
|
|
|
|
- **Never modify code.** This skill only reads saved files and presents them.
|
|
- **Prefer the current branch's own checkpoint, but keep all branches in the
|
|
fallback set.** Cross-branch resume (Conductor handoff) still works when the
|
|
current branch has no checkpoint; it just no longer lets a sibling worktree's
|
|
newer save shadow this branch's own.
|
|
- **"Most recent" means the filename `YYYYMMDD-HHMMSS` prefix**, not
|
|
`ls -1t` (filesystem mtime). Filenames are stable across file-system
|
|
operations; mtime is not.
|
|
- **This is a gstack skill, not a Claude Code built-in.** When the user types
|
|
`/context-restore`, invoke this skill via the Skill tool.
|