diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1eee1e152..6f1947b3f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
diff --git a/docs/FEATURES.md b/docs/FEATURES.md
index 88c543a1f..b706e257d 100644
--- a/docs/FEATURES.md
+++ b/docs/FEATURES.md
@@ -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
---
diff --git a/docs/USER-GUIDE.md b/docs/USER-GUIDE.md
index d29455860..4dcfca52b 100644
--- a/docs/USER-GUIDE.md
+++ b/docs/USER-GUIDE.md
@@ -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 |
diff --git a/get-shit-done/workflows/pause-work.md b/get-shit-done/workflows/pause-work.md
index f723ef81a..ccdba267d 100644
--- a/get-shit-done/workflows/pause-work.md
+++ b/get-shit-done/workflows/pause-work.md
@@ -1,5 +1,5 @@
-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.
@@ -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.
+
+
+
+**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}"
+}
+```
@@ -92,19 +143,22 @@ timestamp=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" current-timesta
```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
```
```
-✓ 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
diff --git a/get-shit-done/workflows/resume-project.md b/get-shit-done/workflows/resume-project.md
index 7ebdc2150..a8dafcf2c 100644
--- a/get-shit-done/workflows/resume-project.md
+++ b/get-shit-done/workflows/resume-project.md
@@ -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):**