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:
@@ -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>
|
||||
|
||||
70
tests/pause-work-improvements.test.cjs
Normal file
70
tests/pause-work-improvements.test.cjs
Normal 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'
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user