mirror of
https://github.com/garrytan/gstack.git
synced 2026-08-18 03:57:15 +02:00
feat: continuous checkpoint mode with non-destructive WIP squash
Adds opt-in auto-commit during long sessions so work survives Claude Code crashes, Conductor workspace handoffs, and context switches. Local-only by default — pushing requires explicit opt-in. Codex review caught multiple landmines that would have shipped: 1. checkpoint_push=true default would push WIP commits to shared branches, trigger CI/deploys, expose secrets. Now default false. 2. Plan's original /ship squash (git reset --soft to merge base) was destructive — uncommitted ALL branch commits, not just WIP, and caused non-fast-forward pushes. Redesigned: rebase --autosquash scoped to WIP commits only, with explicit fallback for WIP-only branches and STOP-and-ask for conflicts. 3. gstack-config get returned empty for missing keys with exit 0, ignoring the annotated defaults in the header comments. Fixed: get now falls back to a lookup_default() table that is the canonical source for defaults. 4. Telemetry default mismatched: header said 'anonymous' but runtime treated empty as 'off'. Aligned: default is 'off' everywhere. 5. /checkpoint resume only read markdown checkpoint files, not the WIP commit [gstack-context] bodies the plan referenced. Wired up parsing of [gstack-context] blocks from WIP commits as a second recovery trail alongside the markdown checkpoints. Changes: - bin/gstack-config: add checkpoint_mode (default explicit) and checkpoint_push (default false) to CONFIG_HEADER. Add lookup_default() as canonical default source. get() falls back to defaults when key absent. list now shows value + source (set/default). New 'defaults' subcommand to inspect the table. - scripts/resolvers/preamble.ts: preamble bash reads _CHECKPOINT_MODE and _CHECKPOINT_PUSH, prints CHECKPOINT_MODE: and CHECKPOINT_PUSH: so the mode is visible. New generateContinuousCheckpoint() section in T2+ tier describes WIP commit format with [gstack-context] body and the rules (never git add -A, never commit broken tests, push only if opted in). Example deliberately shows a clean-state context so it doesn't contradict the rules. - ship/SKILL.md.tmpl: new Step 5.75 WIP Commit Squash. Detects WIP count, exports [gstack-context] blocks before squash (as backup), uses rebase --autosquash for mixed branches and soft-reset only when VERIFIED WIP-only. Explicit anti-footgun rules against blind soft- reset. Aborts with BLOCKED status on conflict instead of destroying non-WIP commits. - checkpoint/SKILL.md.tmpl: new Step 1.5 to parse [gstack-context] blocks from WIP commits via git log --grep="^WIP:". Merges with markdown checkpoint for fuller session recovery. - Golden ship fixtures regenerated (ship is T4, preamble change shows up). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
6c8cf6774f
commit
fe34349966
@@ -189,6 +189,41 @@ in their frontmatter, so all files in the directory are candidates). This enable
|
||||
Conductor workspace handoff — a checkpoint saved on one branch can be resumed from
|
||||
another.
|
||||
|
||||
### Step 1.5: Check for WIP commit context (continuous checkpoint mode)
|
||||
|
||||
If `CHECKPOINT_MODE` was `"continuous"` during prior work, the branch may have
|
||||
`WIP:` commits with structured `[gstack-context]` blocks in their bodies. These
|
||||
are a second recovery trail alongside the markdown checkpoint files.
|
||||
|
||||
```bash
|
||||
_BRANCH=$(git branch --show-current 2>/dev/null)
|
||||
# Detect if this branch has any WIP commits against the nearest remote ancestor
|
||||
_BASE=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD origin/master 2>/dev/null)
|
||||
if [ -n "$_BASE" ]; then
|
||||
WIP_COMMITS=$(git log "$_BASE"..HEAD --grep="^WIP:" --format="%H" 2>/dev/null | head -20)
|
||||
if [ -n "$WIP_COMMITS" ]; then
|
||||
echo "WIP_COMMITS_FOUND"
|
||||
# Extract [gstack-context] blocks from each WIP commit body
|
||||
for SHA in $WIP_COMMITS; do
|
||||
echo "--- commit $SHA ---"
|
||||
git log -1 "$SHA" --format="%s%n%n%b" 2>/dev/null | \
|
||||
awk '/\[gstack-context\]/,/\[\/gstack-context\]/ { print }'
|
||||
done
|
||||
else
|
||||
echo "NO_WIP_COMMITS"
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
If `WIP_COMMITS_FOUND`: Read the extracted `[gstack-context]` blocks. Each block
|
||||
represents a logical unit of prior work with Decisions/Remaining/Tried/Skill.
|
||||
Merge these with the markdown checkpoint file to reconstruct session state. The
|
||||
git history shows the chronological arc; the markdown checkpoint shows the
|
||||
intentional save points. Both matter.
|
||||
|
||||
**Important:** Do NOT delete WIP commits during resume. They remain the recovery
|
||||
trail until /ship squashes them into clean commits during PR creation.
|
||||
|
||||
### Step 2: Load checkpoint
|
||||
|
||||
If the user specified a checkpoint (by number, title fragment, or date), find the
|
||||
|
||||
Reference in New Issue
Block a user