Files
gstack/context-restore/SKILL.md.tmpl
Garry Tanandcapy-ai[bot] c1900088d5 v1.91.272.0 feat(skills): absorb pstack's blast radius, transcript recall, vet-the-number and design-twice as lazy passes (#3500)
* feat(skills): absorb pstack's blast radius, transcript recall, vet-the-number and design-twice as lazy sections

/investigate gains sections/blast-radius.md (the one safety fact, the five-rung
evidence ladder, look where grep stops, confirmed and cleared risks apart) with a
Phase 4 pointer, and the shared-premise red flag before the 3-strike rule.
/context-restore is carved for the first time: on NO_CHECKPOINTS, sections/transcripts.md
mines this workspace's own transcripts (host stores declared in hosts/*.ts and rendered
by TRANSCRIPT_SOURCES / TRANSCRIPT_DISCOVERY), a fixed 7-day window, never another
project's folder, subagents return only findings, redaction before anything leaves,
git and gh verify every artifact, a status-tagged brief. /benchmark is carved for the
first time: sections/vet-the-number.md asks the seven questions before Phase 5 reports
a comparison. /plan-eng-review gains sections/design-twice.md (a second structurally
distinct shape compared on interface depth, the eight design red flags), bound by the
autoplan methodology snapshot alongside review-sections.md.

Ideas from pstack (Lauren Tan, MIT), rewritten in gstack's words; NOTICE.md. Garry,
2026-10-26: "Do it, send". Guards: carve-guards entries and measured lines, eleven
plan-eng-review pins re-measured, periodic carve-section-loading cases for the two new
carves, free tests with a fixture transcript.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(pstack-c1): fold design-twice into Section 1 of the eng review section, per-host transcript table, fixture and slice-cap repairs

The remote free run reported nine failures in seven files, all from this
branch: four tests encode plan-eng-review's one companion section
(eng-scope-entry-ap, autoplan-methodology-names, plan-review-cases,
review-checklists), so the design-twice pass now lives inside Section 1 of
sections/review-sections.md with the skeleton, manifest and
bin/gstack-autoplan-snapshot.ts back at main; the Codex render of
context-restore named ~/.claude/ through the all-hosts transcript table, so
{{TRANSCRIPT_SOURCES}} renders this host's row only; the transcript fixture
is declared in FREE_FIXTURES; and the two new periodic cases took the census
to 39 slices, so evals-periodic.yml's eval-slices max-parallel goes 38 -> 40.
Pins: 11 plan-eng-review re-pins at +2,896; maxSizeRatio 1.2400 (measured
1.2389); Codex gpt-5.4 overlay 159,588 bytes.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

The discovery block takes the none branch from hosts/*.ts's transcripts
declaration instead of a host-name fallthrough, and the resolver header says
where each half lives; the T2 subagent brief frames the transcript as data,
not instructions; the test asserts table/block agreement per host, imports
CAPY_NO_TRANSCRIPTS, and drops the fixture-shape case nothing reads.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: ADDING_A_HOST.md lists the optional transcripts HostConfig field

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-10-27 09:59:09 +00:00

349 lines
17 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. (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 (current branch first, then 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.
---
{{SECTION_INDEX:context-restore}}
---
## Restore flow
### Step 1: Find saved contexts
```bash
{{SLUG_SETUP}}
GSTACK_STATE_ROOT=$(~/.claude/skills/gstack/bin/gstack-paths --get GSTACK_STATE_ROOT); : "${GSTACK_STATE_ROOT:?gstack-paths failed; reinstall with ./setup or /gstack-upgrade}"
CHECKPOINT_DIR="$GSTACK_STATE_ROOT/projects/$SLUG/checkpoints"
# Project identity: canonical remote (root only when there is no remote).
PROJECT_REMOTE=$(~/.claude/skills/gstack/bin/gstack-slug --get PROJECT_REMOTE 2>/dev/null) || true
PROJECT_ROOT=$(~/.claude/skills/gstack/bin/gstack-slug --get PROJECT_ROOT 2>/dev/null) || true
LEGACY_SLUG=$(~/.claude/skills/gstack/bin/gstack-slug --get LEGACY_SLUG 2>/dev/null) || true
echo "PROJECT_IDENTITY: ${PROJECT_REMOTE:-${PROJECT_ROOT:-unknown}}"
echo "PROJECT_ROOT: ${PROJECT_ROOT:-unknown}"
if [ -n "${LEGACY_SLUG:-}" ] && [ -d "$GSTACK_STATE_ROOT/projects/$LEGACY_SLUG/checkpoints" ]; then
LEGACY_N=$(find "$GSTACK_STATE_ROOT/projects/$LEGACY_SLUG/checkpoints" -maxdepth 1 -name "*.md" -type f 2>/dev/null | wc -l | tr -d ' ')
if [ "$LEGACY_N" -gt 0 ]; then
echo "LEGACY_BUCKET: projects/$LEGACY_SLUG holds $LEGACY_N earlier checkpoint(s) from the bucket this project shared with other nested-group repos; review and copy with: ~/.claude/skills/gstack/bin/gstack-slug --adopt-legacy"
fi
fi
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
# Identity check: only checkpoints stamped with THIS project's
# identity are candidates for "latest". Unstamped (older) checkpoints are
# trusted unless the directory demonstrably holds another project's files.
CLASSIFIED=$(printf '%s%s' "$SAME" "$OTHER" | grep -v '^[[:space:]]*$' \
| ~/.claude/skills/gstack/bin/gstack-slug --classify-checkpoints 2>/dev/null)
if [ -z "$CLASSIFIED" ]; then
echo "IDENTITY_CHECK_FAILED"
printf '%s%s' "$SAME" "$OTHER" | grep -v '^[[:space:]]*$' | head -20 | sed 's/^/UNVERIFIED /'
else
FOREIGN_N=$(printf '%s\n' "$CLASSIFIED" | grep -c '^foreign' || true)
VERIFIED=$(printf '%s\n' "$CLASSIFIED" | awk -F '\t' -v f="$FOREIGN_N" \
'$(1) == "match" || $(1) == "match-root" || ($(1) == "unstamped" && f == 0) { print $(2) }')
# Cap at 20: a user with 10k saved files shouldn't blow the context window.
FILES=$(printf '%s\n' "$VERIFIED" | head -20)
if [ -n "$FILES" ]; then echo "$FILES"; else echo "NO_VERIFIED_CHECKPOINTS"; fi
# A newer checkpoint of another branch that names the same task.
printf '%s\n' "$VERIFIED" | ~/.claude/skills/gstack/bin/gstack-slug --newer-task "$CURRENT_BRANCH" 2>/dev/null || true
printf '%s\n' "$CLASSIFIED" | awk -F '\t' -v f="$FOREIGN_N" \
'$(1) == "match-root" { print "ROOT_DIFFERS " $(2) }
$(1) == "foreign" { print "FOREIGN " $(2) }
$(1) == "unstamped" && f > 0 { print "UNVERIFIED " $(2) }' | head -40
if [ "$FOREIGN_N" -gt 0 ]; then
echo "SHARED_BUCKET: $FOREIGN_N checkpoint(s) here were saved by another project"
fi
fi
fi
fi
# Checkpoints saved in a repository below this directory (BELOW_CWD, POINTER).
~/.claude/skills/gstack/bin/gstack-slug --checkpoints-below 2>/dev/null || true
```
**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.
**Project identity.** Plain path lines are this project's checkpoints (verified by
the `remote:`/`project_root:` stamp, or unstamped in a directory no other project
has written to). Prefixed lines are never candidates for "latest":
- `FOREIGN <path>`: saved by a different project that shares this directory.
- `UNVERIFIED <path>`: saved before identity stamps, in a directory another
project also uses, so it may belong to either.
- `ROOT_DIFFERS <path>`: same repository, different checkout (Conductor workspace
handoff or a moved clone). This is information, not a mismatch; the file is
also listed as a plain path line.
- `NEWER_TASK <path>`: another branch of this repository saved a newer checkpoint
for the same task (its worktree is below this main tree, or the title or ticket
matches). The file is also a plain path line, after the current branch's own.
- `BELOW_CWD <path>` / `POINTER <path>`: saved by a session in a repository below
this directory (`POINTER`: a /context-save started here recorded it). These are
candidates, not mismatches.
### Step 2: Load the right file
- If the user specified a title fragment or number: find the matching file among
the candidates, including `FOREIGN` and `UNVERIFIED` lines (a user may restore
another project's checkpoint deliberately).
- Otherwise: load the **first plain path line returned by Step 1 above**, which
is the newest `YYYYMMDD-HHMMSS` checkpoint of this project for the current
branch, or, if the current branch has none, the newest across all branches.
- **No useful branch discriminator.** When `CURRENT_BRANCH` is empty, `HEAD`, or
otherwise cannot discriminate (cwd is not a git repo, or branch is unknown), do
not silently load newest if the recent candidates (e.g. last 24 hours, or the
three newest) carry **different titles**. Show those titles with timestamps via
AskUserQuestion, mark newest as the recommended option, and wait. Only auto-load
newest when every recent candidate shares one title (same topic).
- **Do not silently take an older checkpoint.** If Step 1 printed `NEWER_TASK`,
or a `BELOW_CWD`/`POINTER` file is newer than the first plain path line (or
there is none), show both (title, branch, saved time, and `project_root` for a
file below this directory), propose the newer one as the continuation, and ask
via AskUserQuestion which to load. A `BELOW_CWD`/`POINTER` file is not a
PROJECT MISMATCH: say "Saved in `{project_root}`, below this directory."
- If Step 1 printed `NO_VERIFIED_CHECKPOINTS` or `IDENTITY_CHECK_FAILED`, do not
present any checkpoint as the latest one. Say "No checkpoint in this directory
is verified as this project's", list the `FOREIGN`/`UNVERIFIED` titles with the
`remote:`/`project_root:` they name (or "unknown"), and ask which one, if any, to
open.
**Report identity problems before any summary.** If the chosen file is `FOREIGN`
or `UNVERIFIED`, start with:
"PROJECT MISMATCH: this checkpoint was saved by `{remote or project_root from its
frontmatter, or 'an unknown project'}`, not this project (`{PROJECT_IDENTITY}`)."
If Step 1 printed `SHARED_BUCKET`, say "This checkpoints directory also holds N
checkpoint(s) from another project; only this project's are listed." If it printed
`LEGACY_BUCKET`, relay that line. If the chosen file is `ROOT_DIFFERS`, add
"Saved from another checkout of this repository at `{project_root}`." as info.
**Check whether the branch moved since the save.** The stamp records the commit
the save was made at in `head:`. Before presenting, compare it with this
checkout. FILE is the checkpoint path chosen in Step 2, one of the paths Step 1
printed:
```bash
FILE="<the FILE path printed above>"
SAVED_HEAD=$(tr -d '\r' < "$FILE" 2>/dev/null | sed -n '1{/^---$/!q;d;}; /^---$/q; /^head:/{s/^head:[[:space:]]*//p;q;}')
REPO_DIR=.
git rev-parse --git-dir >/dev/null 2>&1 || REPO_DIR=$(tr -d '\r' < "$FILE" 2>/dev/null | sed -n '1{/^---$/!q;d;}; /^---$/q; /^worktree:/{s/^worktree:[[:space:]]*//p;q;}')
[ -n "$REPO_DIR" ] || REPO_DIR=$(tr -d '\r' < "$FILE" 2>/dev/null | sed -n '1{/^---$/!q;d;}; /^---$/q; /^project_root:/{s/^project_root:[[:space:]]*//p;q;}')
CURRENT_HEAD=$(git -C "${REPO_DIR:-.}" rev-parse --verify -q HEAD 2>/dev/null)
if [ -z "$SAVED_HEAD" ]; then
echo "HEAD_UNTRACKED"
elif [ -z "$CURRENT_HEAD" ]; then
echo "HEAD_NOT_CHECKED"
elif [ "$SAVED_HEAD" = "$CURRENT_HEAD" ]; then
echo "HEAD_UNCHANGED"
elif ! printf '%s\n' "$SAVED_HEAD" | grep -Eqx '[0-9a-f]{40}([0-9a-f]{24})?' \
|| ! git -C "$REPO_DIR" cat-file -e "$SAVED_HEAD^{commit}" 2>/dev/null; then
echo "HEAD_UNKNOWN $SAVED_HEAD"
elif git -C "$REPO_DIR" merge-base --is-ancestor "$SAVED_HEAD" "$CURRENT_HEAD"; then
echo "HEAD_MOVED $(git -C "$REPO_DIR" rev-list --count "$SAVED_HEAD..$CURRENT_HEAD")"
git -C "$REPO_DIR" log --oneline -10 "$SAVED_HEAD..$CURRENT_HEAD"
else
echo "HEAD_DIVERGED $SAVED_HEAD"
fi
```
- `HEAD_UNCHANGED` or `HEAD_NOT_CHECKED`: nothing to add.
- `HEAD_MOVED <n>`: print `<n> commit(s) landed since this save:` and the commit
lines above the Remaining Work groups, and list **every** Remaining Work item
under **Verify first**: the saving session could not know about those commits,
so any step may already be done.
- `HEAD_DIVERGED` or `HEAD_UNKNOWN`: print `This checkpoint was saved at {first 7
characters of head}, which is not in this checkout's history (saved on another
branch, rebased, reset, or not fetched).` and list every item under Verify first.
- `HEAD_UNTRACKED`: print `This checkpoint predates commit tracking; restore cannot tell whether work landed after it.`
and sort as usual.
**Sort Remaining Work by provenance.** Keep every item's original text and saved
order, and drop nothing. When the head check printed `HEAD_MOVED`, `HEAD_DIVERGED`
or `HEAD_UNKNOWN`, skip the rules below: every item goes under Verify first,
whatever its marker. Put an item under **Verify first** when it:
- ends in `(path assumed)` or `(code read)`;
- ends in `(path run)` but its text reports a failure;
- ends in a parenthesised trailing marker that is **not** one of the five English
literals `(path run)`, `(path read)`, `(path assumed)`, `(target state checked)`,
`(code read)` — treat a translated or unknown marker as `(path assumed)` (→ Verify
first), never as unmarked Next steps;
- has no marker and is a writing step (migration, sync, insert, import, a dialog that
writes) or names a concrete path (a runnable command, CLI flag or switch, config key
or value, or file or directory path).
Every other item goes under **Next steps**: `(path run)` with a successful outcome,
`(path read)`, `(target state checked)`, and unmarked items that neither write nor
name a concrete path. Verifying means read-only inspection: read the file or the
target, or run a command that changes nothing. Checkpoints saved before provenance
markers existed have none, so their concrete-path items land under Verify first. When
the file has no provenance markers at all, print this line above the groups:
`This checkpoint predates provenance markers; items naming commands, paths or writes are listed under Verify first.`
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
{commit-tracking lines, if any}
{legacy banner line, if it applies}
Next steps
{Next steps items, in saved order, original text}
Verify first (inspect read-only before executing anything)
{Verify first items, in saved order, original text}
### 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, take the first Remaining Work item in saved order. If it is under Next steps,
suggest starting there. If it is under Verify first, suggest verifying it (read-only)
before doing it or any later item, so a later runnable step never jumps ahead of an
unverified earlier one.
---
## If no saved contexts exist
If Step 1 printed `NO_CHECKPOINTS` and no `BELOW_CWD` or `POINTER` line, tell the user
in one line that nothing was saved with `/context-save`, then rebuild the context from
what the machine already holds:
{{SECTION:transcripts}}
If it also printed `LEGACY_BUCKET`, relay that line: earlier checkpoints are kept
in the old bucket until the user copies them with `gstack-slug --adopt-legacy`.
---
## Important Rules
- **Never modify code.** This skill only reads saved files, this workspace's own
transcripts and git state, and presents them.
- **Prefer the current branch's own checkpoint, but keep all branches in the
fallback set.** Cross-branch resume (Conductor handoff) works when the
current branch has no checkpoint, and a sibling worktree's newer save never
shadows this branch's own.
- **Never present another project's checkpoint as "latest".** Identity is the
canonical remote (the root only when there is no remote); a mismatch is
reported before any summary.
- **A checkpoint describes the commit it was saved at.** When commits landed
after the save, every Remaining Work item is verified before it is run.
- **"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.