feat(workflows): expand pause-work for non-phase contexts and richer handoffs (#1608)

- Detects spike/deliberation/research context and writes to appropriate path (#1489)
- Adds Required Reading, Anti-Patterns, and Infrastructure State sections to
  continue-here template (#1490)
- Documents pre-execution design critique gate for design→execution transitions (#1487)

Closes #1487
Closes #1489
Closes #1490
This commit is contained in:
Tom Boucher
2026-04-03 12:40:17 -04:00
committed by GitHub
parent ec7bf04a4d
commit bb74bd96d8
2 changed files with 116 additions and 10 deletions

View File

@@ -9,14 +9,28 @@ Read all files referenced by the invoking prompt's execution_context before star
<process>
<step name="detect">
Find current phase directory from most recently modified files:
## Context Detection
Determine what kind of work is being paused and set the handoff destination accordingly:
```bash
# Find most recent phase directory with work
(ls -lt .planning/phases/*/PLAN.md 2>/dev/null || true) | head -1 | grep -oP 'phases/\K[^/]+' || true
# Check for active phase
phase=$(( ls -lt .planning/phases/*/PLAN.md 2>/dev/null || true ) | head -1 | grep -oP 'phases/\K[^/]+' || true)
# Check for active spike
spike=$(( ls -lt .planning/spikes/*/SPIKE.md .planning/spikes/*/DESIGN.md 2>/dev/null || true ) | head -1 | grep -oP 'spikes/\K[^/]+' || true)
# Check for active deliberation
deliberation=$(ls .planning/deliberations/*.md 2>/dev/null | head -1 || true)
```
If no active phase detected, ask user which phase they're pausing work on.
- **Phase work**: active phase directory → handoff to `.planning/phases/XX-name/.continue-here.md`
- **Spike work**: active spike directory or spike-related files (no active phase) → handoff to `.planning/spikes/SPIKE-NNN/.continue-here.md` (create directory if needed)
- **Deliberation work**: active deliberation file (no phase/spike) → handoff to `.planning/deliberations/.continue-here.md`
- **Research work**: research notes exist but no phase/spike/deliberation → handoff to `.planning/.continue-here.md`
- **Default**: no detectable context → handoff to `.planning/.continue-here.md`, note the ambiguity in `<current_state>`
If phase is detected, proceed with phase handoff path. Otherwise use the first matching non-phase path above.
</step>
<step name="gather">
@@ -85,10 +99,11 @@ timestamp=$(node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" current-timesta
</step>
<step name="write">
**Write handoff to `.planning/phases/XX-name/.continue-here.md`:**
**Write handoff to the path determined in the detect step** (e.g. `.planning/phases/XX-name/.continue-here.md`, `.planning/spikes/SPIKE-NNN/.continue-here.md`, or `.planning/.continue-here.md`):
```markdown
---
context: [phase|spike|deliberation|research|default]
phase: XX-name
task: 3
total_tasks: 7
@@ -124,6 +139,24 @@ last_updated: [timestamp from current-timestamp]
- [Blocker 1]: [status/workaround]
</blockers>
## Required Reading (in order)
<!-- List documents the resuming agent must read before acting -->
1. [document] — [why it matters]
## Critical Anti-Patterns (do NOT repeat these)
<!-- Mistakes discovered this session that must be structurally avoided -->
- [ANTI-PATTERN]: [what it is] → [structural mitigation]
## Infrastructure State
<!-- Running services, external state, environment specifics -->
- [service/env]: [current state]
## Pre-Execution Critique Required
<!-- Fill in ONLY if pausing between design and execution (e.g. spike design done, not yet run) -->
- Design artifact: [path]
- Critique focus: [key questions the critic should probe]
- Gate: Do NOT begin execution until critique is complete and design is revised
<context>
[Mental state, what were you thinking, the plan]
</context>
@@ -143,7 +176,7 @@ 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 .planning/HANDOFF.json
node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "wip: [context-name] paused at [X]/[Y]" --files [handoff-path] .planning/HANDOFF.json
```
</step>
@@ -151,11 +184,12 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "wip: [phase-name] p
```
✓ Handoff created:
- .planning/HANDOFF.json (structured, machine-readable)
- .planning/phases/[XX-name]/.continue-here.md (human-readable)
- [handoff-path] (human-readable)
Current state:
- Phase: [XX-name]
- Context: [phase|spike|deliberation|research]
- Location: [XX-name or SPIKE-NNN]
- Task: [X] of [Y]
- Status: [in_progress/blocked]
- Blockers: [count] ({human_actions_pending count} need human action)
@@ -169,8 +203,10 @@ To resume: /gsd:resume-work
</process>
<success_criteria>
- [ ] .continue-here.md created in correct phase directory
- [ ] All sections filled with specific content
- [ ] Context detected (phase/spike/deliberation/research/default)
- [ ] .continue-here.md created at correct path for detected context
- [ ] Required Reading, Anti-Patterns, and Infrastructure State sections filled
- [ ] Pre-Execution Critique section filled if pausing between design and execution
- [ ] Committed as WIP
- [ ] User knows location and how to resume
</success_criteria>

View File

@@ -0,0 +1,70 @@
const { test, describe } = require('node:test');
const assert = require('node:assert');
const fs = require('fs');
const path = require('path');
describe('pause-work improvements', () => {
let pauseContent;
test('pause-work.md exists', () => {
const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'pause-work.md');
assert.ok(fs.existsSync(p));
pauseContent = fs.readFileSync(p, 'utf-8');
});
test('#1489: pause-work detects non-phase contexts (spike, deliberation, research)', () => {
pauseContent = pauseContent || fs.readFileSync(
path.join(__dirname, '..', 'get-shit-done', 'workflows', 'pause-work.md'), 'utf-8'
);
assert.ok(pauseContent.includes('spike') || pauseContent.includes('Spike'),
'pause-work should handle spike context');
assert.ok(pauseContent.includes('deliberation') || pauseContent.includes('research'),
'pause-work should handle deliberation/research context');
});
test('#1489: pause-work writes to non-phase paths when appropriate', () => {
pauseContent = pauseContent || fs.readFileSync(
path.join(__dirname, '..', 'get-shit-done', 'workflows', 'pause-work.md'), 'utf-8'
);
assert.ok(pauseContent.includes('.planning/.continue-here') ||
pauseContent.includes('.planning/spikes') ||
pauseContent.includes('non-phase'),
'pause-work should write to root .planning/ when not in a phase');
});
test('#1490: continue-here template includes required-reading section', () => {
pauseContent = pauseContent || fs.readFileSync(
path.join(__dirname, '..', 'get-shit-done', 'workflows', 'pause-work.md'), 'utf-8'
);
assert.ok(pauseContent.includes('Required Reading') || pauseContent.includes('required-reading'),
'Template should include Required Reading section');
});
test('#1490: continue-here template includes anti-patterns section', () => {
pauseContent = pauseContent || fs.readFileSync(
path.join(__dirname, '..', 'get-shit-done', 'workflows', 'pause-work.md'), 'utf-8'
);
assert.ok(pauseContent.includes('Anti-Pattern') || pauseContent.includes('anti-pattern') ||
pauseContent.includes('do NOT repeat'),
'Template should include Anti-Patterns section');
});
test('#1490: continue-here template includes infrastructure-state section', () => {
pauseContent = pauseContent || fs.readFileSync(
path.join(__dirname, '..', 'get-shit-done', 'workflows', 'pause-work.md'), 'utf-8'
);
assert.ok(pauseContent.includes('Infrastructure') || pauseContent.includes('infrastructure'),
'Template should include Infrastructure State section');
});
test('#1487: pause-work documents pre-execution critique gate', () => {
pauseContent = pauseContent || fs.readFileSync(
path.join(__dirname, '..', 'get-shit-done', 'workflows', 'pause-work.md'), 'utf-8'
);
assert.ok(
pauseContent.includes('critique') || pauseContent.includes('design gate') ||
pauseContent.includes('Pre-Execution'),
'pause-work should document design critique gate for design→execution transitions'
);
});
});