feat: structured session handoff artifact for cross-session continuity (#940) (#1122)

Enhance /gsd:pause-work to write .planning/HANDOFF.json alongside
.continue-here.md. The JSON provides machine-readable state that
/gsd:resume-work can parse for precise resumption.

HANDOFF.json includes:
- Task position (phase, plan, task number, status)
- Completed and remaining tasks with commit hashes
- Blockers with type classification (technical/human_action/external)
- Human actions pending (API keys, approvals, manual testing)
- Uncommitted files list
- Context notes for mental model restoration

Resume-work changes:
- HANDOFF.json is primary resumption source (highest priority)
- Surfaces blockers and human actions immediately on session start
- Validates uncommitted files against git status
- Deletes HANDOFF.json after successful resumption
- Falls back to .continue-here.md if no JSON exists

Also checks for placeholder content in SUMMARY.md files to catch
false completions (frontmatter claims complete but body has TBD).

Fixes #940
This commit is contained in:
Tom Boucher
2026-03-18 12:01:25 -04:00
committed by GitHub
parent a97e4c2c6f
commit f54f3df776
5 changed files with 87 additions and 10 deletions

View File

@@ -17,6 +17,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Fixed
- **Requirements `mark-complete` is now idempotent** — Re-marking already-completed requirements returns `already_complete` instead of `not_found` (#948)
### Improved
- **Structured session handoff** — `/gsd:pause-work` now writes `.planning/HANDOFF.json` alongside `.continue-here.md`. JSON provides machine-readable state (task position, blockers, human actions pending, uncommitted files) that `/gsd:resume-work` parses for precise resumption instead of generic "what do you want to do?" (#940)
## [1.25.0] - 2026-03-16
### Added

View File

@@ -513,11 +513,13 @@
**Purpose:** Maintain project continuity across context resets and sessions.
**Requirements:**
- REQ-SESSION-01: Pause MUST save current position and next steps to `continue-here.md`
- REQ-SESSION-02: Resume MUST restore full project context from state files
- REQ-SESSION-01: Pause MUST save current position and next steps to `continue-here.md` and structured `HANDOFF.json`
- REQ-SESSION-02: Resume MUST restore full project context from HANDOFF.json (preferred) or state files (fallback)
- REQ-SESSION-03: Progress MUST show current position, next action, and overall completion
- REQ-SESSION-04: Progress MUST read all state files (STATE.md, ROADMAP.md, phase directories)
- REQ-SESSION-05: All session operations MUST work after `/clear` (context reset)
- REQ-SESSION-06: HANDOFF.json MUST include blockers, human actions pending, and in-progress task state
- REQ-SESSION-07: Resume MUST surface human actions and blockers immediately on session start
---

View File

@@ -296,7 +296,7 @@ Controlled by `workflow.ui_safety_gate` config toggle.
|---------|---------|-------------|
| `/gsd:progress` | Show status and next steps | Anytime -- "where am I?" |
| `/gsd:resume-work` | Restore full context from last session | Starting a new session |
| `/gsd:pause-work` | Save context handoff | Stopping mid-phase |
| `/gsd:pause-work` | Save structured handoff (HANDOFF.json + continue-here.md) | Stopping mid-phase |
| `/gsd:help` | Show all commands | Quick reference |
| `/gsd:update` | Update GSD with changelog preview | Check for new versions |
| `/gsd:join-discord` | Open Discord community invite | Questions or community |

View File

@@ -1,5 +1,5 @@
<purpose>
Create `.continue-here.md` handoff file to preserve complete work state across sessions. Enables seamless resumption with full context restoration.
Create structured `.planning/HANDOFF.json` and `.continue-here.md` handoff files to preserve complete work state across sessions. The JSON provides machine-readable state for `/gsd:resume-work`; the markdown provides human-readable context.
</purpose>
<required_reading>
@@ -27,10 +27,61 @@ If no active phase detected, ask user which phase they're pausing work on.
3. **Work remaining**: What's left in current plan/phase
4. **Decisions made**: Key decisions and rationale
5. **Blockers/issues**: Anything stuck
6. **Mental context**: The approach, next steps, "vibe"
7. **Files modified**: What's changed but not committed
6. **Human actions pending**: Things that need manual intervention (MCP setup, API keys, approvals, manual testing)
7. **Background processes**: Any running servers/watchers that were part of the workflow
8. **Files modified**: What's changed but not committed
Ask user for clarifications if needed via conversational questions.
**Also inspect SUMMARY.md files for false completions:**
```bash
# Check for placeholder content in existing summaries
grep -l "To be filled\|placeholder\|TBD" .planning/phases/*/*.md 2>/dev/null
```
Report any summaries with placeholder content as incomplete items.
</step>
<step name="write_structured">
**Write structured handoff to `.planning/HANDOFF.json`:**
```bash
timestamp=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" current-timestamp full --raw)
```
```json
{
"version": "1.0",
"timestamp": "{timestamp}",
"phase": "{phase_number}",
"phase_name": "{phase_name}",
"phase_dir": "{phase_dir}",
"plan": {current_plan_number},
"task": {current_task_number},
"total_tasks": {total_task_count},
"status": "paused",
"completed_tasks": [
{"id": 1, "name": "{task_name}", "status": "done", "commit": "{short_hash}"},
{"id": 2, "name": "{task_name}", "status": "done", "commit": "{short_hash}"},
{"id": 3, "name": "{task_name}", "status": "in_progress", "progress": "{what_done}"}
],
"remaining_tasks": [
{"id": 4, "name": "{task_name}", "status": "not_started"},
{"id": 5, "name": "{task_name}", "status": "not_started"}
],
"blockers": [
{"description": "{blocker}", "type": "technical|human_action|external", "workaround": "{if any}"}
],
"human_actions_pending": [
{"action": "{what needs to be done}", "context": "{why}", "blocking": true}
],
"decisions": [
{"decision": "{what}", "rationale": "{why}", "phase": "{phase_number}"}
],
"uncommitted_files": [],
"next_action": "{specific first action when resuming}",
"context_notes": "{mental state, approach, what you were thinking}"
}
```
</step>
<step name="write">
@@ -92,19 +143,22 @@ timestamp=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" current-timesta
<step name="commit">
```bash
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "wip: [phase-name] paused at task [X]/[Y]" --files .planning/phases/*/.continue-here.md
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "wip: [phase-name] paused at task [X]/[Y]" --files .planning/phases/*/.continue-here.md .planning/HANDOFF.json
```
</step>
<step name="confirm">
```
✓ Handoff created: .planning/phases/[XX-name]/.continue-here.md
✓ Handoff created:
- .planning/HANDOFF.json (structured, machine-readable)
- .planning/phases/[XX-name]/.continue-here.md (human-readable)
Current state:
- Phase: [XX-name]
- Task: [X] of [Y]
- Status: [in_progress/blocked]
- Blockers: [count] ({human_actions_pending count} need human action)
- Committed as WIP
To resume: /gsd:resume-work

View File

@@ -63,6 +63,9 @@ cat .planning/PROJECT.md
Look for incomplete work that needs attention:
```bash
# Check for structured handoff (preferred — machine-readable)
cat .planning/HANDOFF.json 2>/dev/null
# Check for continue-here files (mid-plan resumption)
ls .planning/phases/*/.continue-here*.md 2>/dev/null
@@ -78,7 +81,18 @@ if [ "$has_interrupted_agent" = "true" ]; then
fi
```
**If .continue-here file exists:**
**If HANDOFF.json exists:**
- This is the primary resumption source — structured data from `/gsd:pause-work`
- Parse `status`, `phase`, `plan`, `task`, `total_tasks`, `next_action`
- Check `blockers` and `human_actions_pending` — surface these immediately
- Check `completed_tasks` for `in_progress` items — these need attention first
- Validate `uncommitted_files` against `git status` — flag divergence
- Use `context_notes` to restore mental model
- Flag: "Found structured handoff — resuming from task {task}/{total_tasks}"
- **After successful resumption, delete HANDOFF.json** (it's a one-shot artifact)
**If .continue-here file exists (fallback):**
- This is a mid-plan resumption point
- Read the file for specific resumption context
@@ -145,8 +159,12 @@ Based on project state, determine the most logical next action:
→ Primary: Resume interrupted agent (Task tool with resume parameter)
→ Option: Start fresh (abandon agent work)
**If HANDOFF.json exists:**
→ Primary: Resume from structured handoff (highest priority — specific task/blocker context)
→ Option: Discard handoff and reassess from files
**If .continue-here file exists:**
→ Primary: Resume from checkpoint
→ Fallback: Resume from checkpoint
→ Option: Start fresh on current plan
**If incomplete plan (PLAN without SUMMARY):**