Add composable --research flag to /gsd:quick that spawns a focused gsd-phase-researcher before planning. Investigates implementation approaches, library options, and pitfalls for the task. Addresses the middle-ground gap between quick (no quality agents) and full milestone workflows. All three flags are composable: --discuss --research --full gives the complete quality pipeline. Made-with: Cursor Co-authored-by: ralberts3 <ralberts3@gatech.edu>
This commit is contained in:
@@ -6,6 +6,9 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- **`/gsd:quick --research` flag** — Spawns focused research agent before planning, composable with `--discuss` and `--full`. Addresses the middle-ground gap between quick and full milestone workflows (#317)
|
||||
|
||||
### Fixed
|
||||
- OpenCode agent frontmatter conversion — agents now get correct `name:`, `model: inherit`, `mode: subagent` instead of broken command-style conversion that stripped name and kept `color:`/`skills:`/`tools:`
|
||||
- Local install: workflow and reference files now get absolute path to `gsd-tools.cjs` instead of `$HOME/.claude/get-shit-done/`, so local installs work when GSD is outside `$HOME` and spawned subagents with empty `$HOME` still resolve the path (#820)
|
||||
|
||||
12
README.md
12
README.md
@@ -372,10 +372,16 @@ Then `/gsd:new-milestone` starts the next version — same flow as `new-project`
|
||||
Quick mode gives you GSD guarantees (atomic commits, state tracking) with a faster path:
|
||||
|
||||
- **Same agents** — Planner + executor, same quality
|
||||
- **Skips optional steps** — No research, no plan checker, no verifier
|
||||
- **Skips optional steps** — No research, no plan checker, no verifier by default
|
||||
- **Separate tracking** — Lives in `.planning/quick/`, not phases
|
||||
|
||||
Use for: bug fixes, small features, config changes, one-off tasks.
|
||||
**`--discuss` flag:** Lightweight discussion to surface gray areas before planning.
|
||||
|
||||
**`--research` flag:** Spawns a focused researcher before planning. Investigates implementation approaches, library options, and pitfalls. Use when you're unsure how to approach a task.
|
||||
|
||||
**`--full` flag:** Enables plan-checking (max 2 iterations) and post-execution verification.
|
||||
|
||||
Flags are composable: `--discuss --research --full` gives discussion + research + plan-checking + verification.
|
||||
|
||||
```
|
||||
/gsd:quick
|
||||
@@ -532,7 +538,7 @@ You're never locked in. The system adapts.
|
||||
| `/gsd:add-todo [desc]` | Capture idea for later |
|
||||
| `/gsd:check-todos` | List pending todos |
|
||||
| `/gsd:debug [desc]` | Systematic debugging with persistent state |
|
||||
| `/gsd:quick [--full] [--discuss]` | Execute ad-hoc task with GSD guarantees (`--full` adds plan-checking and verification, `--discuss` gathers context first) |
|
||||
| `/gsd:quick [--full] [--discuss] [--research]` | Execute ad-hoc task with GSD guarantees (`--full` adds plan-checking and verification, `--discuss` gathers context first, `--research` investigates approaches before planning) |
|
||||
| `/gsd:health [--repair]` | Validate `.planning/` directory integrity, auto-repair with `--repair` |
|
||||
| `/gsd:stats` | Display project statistics — phases, plans, requirements, git metrics |
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: gsd:quick
|
||||
description: Execute a quick task with GSD guarantees (atomic commits, state tracking) but skip optional agents
|
||||
argument-hint: "[--full] [--discuss]"
|
||||
argument-hint: "[--full] [--discuss] [--research]"
|
||||
allowed-tools:
|
||||
- Read
|
||||
- Write
|
||||
@@ -26,7 +26,9 @@ Quick mode is the same system with a shorter path:
|
||||
|
||||
**`--full` flag:** Enables plan-checking (max 2 iterations) and post-execution verification. Use when you want quality guarantees without full milestone ceremony.
|
||||
|
||||
Flags are composable: `--discuss --full` gives discussion + plan-checking + verification.
|
||||
**`--research` flag:** Spawns a focused research agent before planning. Investigates implementation approaches, library options, and pitfalls for the task. Use when you're unsure of the best approach.
|
||||
|
||||
Flags are composable: `--discuss --research --full` gives discussion + research + plan-checking + verification.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
|
||||
@@ -118,17 +118,23 @@ Usage: `/gsd:execute-phase 5`
|
||||
|
||||
### Quick Mode
|
||||
|
||||
**`/gsd:quick`**
|
||||
**`/gsd:quick [--full] [--discuss] [--research]`**
|
||||
Execute small, ad-hoc tasks with GSD guarantees but skip optional agents.
|
||||
|
||||
Quick mode uses the same system with a shorter path:
|
||||
- Spawns planner + executor (skips researcher, checker, verifier)
|
||||
- Spawns planner + executor (skips researcher, checker, verifier by default)
|
||||
- Quick tasks live in `.planning/quick/` separate from planned phases
|
||||
- Updates STATE.md tracking (not ROADMAP.md)
|
||||
|
||||
Use when you know exactly what to do and the task is small enough to not need research or verification.
|
||||
Flags enable additional quality steps:
|
||||
- `--discuss` — Lightweight discussion to surface gray areas before planning
|
||||
- `--research` — Focused research agent investigates approaches before planning
|
||||
- `--full` — Adds plan-checking (max 2 iterations) and post-execution verification
|
||||
|
||||
Flags are composable: `--discuss --research --full` gives the complete quality pipeline for a single task.
|
||||
|
||||
Usage: `/gsd:quick`
|
||||
Usage: `/gsd:quick --research --full`
|
||||
Result: Creates `.planning/quick/NNN-slug/PLAN.md`, `.planning/quick/NNN-slug/SUMMARY.md`
|
||||
|
||||
### Roadmap Management
|
||||
|
||||
@@ -5,7 +5,9 @@ With `--discuss` flag: lightweight discussion phase before planning. Surfaces as
|
||||
|
||||
With `--full` flag: enables plan-checking (max 2 iterations) and post-execution verification for quality guarantees without full milestone ceremony.
|
||||
|
||||
Flags are composable: `--discuss --full` gives discussion + plan-checking + verification.
|
||||
With `--research` flag: spawns a focused research agent before planning. Investigates implementation approaches, library options, and pitfalls. Use when you're unsure how to approach a task.
|
||||
|
||||
Flags are composable: `--discuss --research --full` gives discussion + research + plan-checking + verification.
|
||||
</purpose>
|
||||
|
||||
<required_reading>
|
||||
@@ -18,6 +20,7 @@ Read all files referenced by the invoking prompt's execution_context before star
|
||||
Parse `$ARGUMENTS` for:
|
||||
- `--full` flag → store as `$FULL_MODE` (true/false)
|
||||
- `--discuss` flag → store as `$DISCUSS_MODE` (true/false)
|
||||
- `--research` flag → store as `$RESEARCH_MODE` (true/false)
|
||||
- Remaining text → use as `$DESCRIPTION` if non-empty
|
||||
|
||||
If `$DESCRIPTION` is empty after parsing, prompt user interactively:
|
||||
@@ -36,7 +39,16 @@ If still empty, re-prompt: "Please provide a task description."
|
||||
|
||||
Display banner based on active flags:
|
||||
|
||||
If `$DISCUSS_MODE` and `$FULL_MODE`:
|
||||
If `$DISCUSS_MODE` and `$RESEARCH_MODE` and `$FULL_MODE`:
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GSD ► QUICK TASK (DISCUSS + RESEARCH + FULL)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
◆ Discussion + research + plan checking + verification enabled
|
||||
```
|
||||
|
||||
If `$DISCUSS_MODE` and `$FULL_MODE` (no research):
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GSD ► QUICK TASK (DISCUSS + FULL)
|
||||
@@ -45,6 +57,24 @@ If `$DISCUSS_MODE` and `$FULL_MODE`:
|
||||
◆ Discussion + plan checking + verification enabled
|
||||
```
|
||||
|
||||
If `$DISCUSS_MODE` and `$RESEARCH_MODE` (no full):
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GSD ► QUICK TASK (DISCUSS + RESEARCH)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
◆ Discussion + research enabled
|
||||
```
|
||||
|
||||
If `$RESEARCH_MODE` and `$FULL_MODE` (no discuss):
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GSD ► QUICK TASK (RESEARCH + FULL)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
◆ Research + plan checking + verification enabled
|
||||
```
|
||||
|
||||
If `$DISCUSS_MODE` only:
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
@@ -54,6 +84,15 @@ If `$DISCUSS_MODE` only:
|
||||
◆ Discussion phase enabled — surfacing gray areas before planning
|
||||
```
|
||||
|
||||
If `$RESEARCH_MODE` only:
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GSD ► QUICK TASK (RESEARCH)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
◆ Research phase enabled — investigating approaches before planning
|
||||
```
|
||||
|
||||
If `$FULL_MODE` only:
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
@@ -234,6 +273,69 @@ Report: `Context captured: ${QUICK_DIR}/${quick_id}-CONTEXT.md`
|
||||
|
||||
---
|
||||
|
||||
**Step 4.75: Research phase (only when `$RESEARCH_MODE`)**
|
||||
|
||||
Skip this step entirely if NOT `$RESEARCH_MODE`.
|
||||
|
||||
Display banner:
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GSD ► RESEARCHING QUICK TASK
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
◆ Investigating approaches for: ${DESCRIPTION}
|
||||
```
|
||||
|
||||
Spawn a single focused researcher (not 4 parallel researchers like full phases — quick tasks need targeted research, not broad domain surveys):
|
||||
|
||||
```
|
||||
Task(
|
||||
prompt="
|
||||
<research_context>
|
||||
|
||||
**Mode:** quick-task
|
||||
**Task:** ${DESCRIPTION}
|
||||
**Output:** ${QUICK_DIR}/${quick_id}-RESEARCH.md
|
||||
|
||||
<files_to_read>
|
||||
- .planning/STATE.md (Project state — what's already built)
|
||||
- .planning/PROJECT.md (Project context)
|
||||
- ./CLAUDE.md (if exists — project-specific guidelines)
|
||||
${DISCUSS_MODE ? '- ' + QUICK_DIR + '/' + quick_id + '-CONTEXT.md (User decisions — research should align with these)' : ''}
|
||||
</files_to_read>
|
||||
|
||||
</research_context>
|
||||
|
||||
<focus>
|
||||
This is a quick task, not a full phase. Research should be concise and targeted:
|
||||
1. Best libraries/patterns for this specific task
|
||||
2. Common pitfalls and how to avoid them
|
||||
3. Integration points with existing codebase
|
||||
4. Any constraints or gotchas worth knowing before planning
|
||||
|
||||
Do NOT produce a full domain survey. Target 1-2 pages of actionable findings.
|
||||
</focus>
|
||||
|
||||
<output>
|
||||
Write research to: ${QUICK_DIR}/${quick_id}-RESEARCH.md
|
||||
Use standard research format but keep it lean — skip sections that don't apply.
|
||||
Return: ## RESEARCH COMPLETE with file path
|
||||
</output>
|
||||
",
|
||||
subagent_type="gsd-phase-researcher",
|
||||
model="{planner_model}",
|
||||
description="Research: ${DESCRIPTION}"
|
||||
)
|
||||
```
|
||||
|
||||
After researcher returns:
|
||||
1. Verify research exists at `${QUICK_DIR}/${quick_id}-RESEARCH.md`
|
||||
2. Report: "Research complete: ${QUICK_DIR}/${quick_id}-RESEARCH.md"
|
||||
|
||||
If research file not found, warn but continue: "Research agent did not produce output — proceeding to planning without research."
|
||||
|
||||
---
|
||||
|
||||
**Step 5: Spawn planner (quick mode)**
|
||||
|
||||
**If `$FULL_MODE`:** Use `quick-full` mode with stricter constraints.
|
||||
@@ -253,6 +355,7 @@ Task(
|
||||
- .planning/STATE.md (Project State)
|
||||
- ./CLAUDE.md (if exists — follow project-specific guidelines)
|
||||
${DISCUSS_MODE ? '- ' + QUICK_DIR + '/' + quick_id + '-CONTEXT.md (User decisions — locked, do not revisit)' : ''}
|
||||
${RESEARCH_MODE ? '- ' + QUICK_DIR + '/' + quick_id + '-RESEARCH.md (Research findings — use to inform implementation choices)' : ''}
|
||||
</files_to_read>
|
||||
|
||||
**Project skills:** Check .claude/skills/ or .agents/skills/ directory (if either exists) — read SKILL.md files, plans should account for project skill rules
|
||||
@@ -262,7 +365,7 @@ ${DISCUSS_MODE ? '- ' + QUICK_DIR + '/' + quick_id + '-CONTEXT.md (User decision
|
||||
<constraints>
|
||||
- Create a SINGLE plan with 1-3 focused tasks
|
||||
- Quick tasks should be atomic and self-contained
|
||||
- No research phase
|
||||
${RESEARCH_MODE ? '- Research findings are available — use them to inform library/pattern choices' : '- No research phase'}
|
||||
${FULL_MODE ? '- Target ~40% context usage (structured for verification)' : '- Target ~30% context usage (simple, focused)'}
|
||||
${FULL_MODE ? '- MUST generate `must_haves` in plan frontmatter (truths, artifacts, key_links)' : ''}
|
||||
${FULL_MODE ? '- Each task MUST have `files`, `action`, `verify`, `done` fields' : ''}
|
||||
@@ -545,6 +648,7 @@ Build file list:
|
||||
- `${QUICK_DIR}/${quick_id}-SUMMARY.md`
|
||||
- `.planning/STATE.md`
|
||||
- If `$DISCUSS_MODE` and context file exists: `${QUICK_DIR}/${quick_id}-CONTEXT.md`
|
||||
- If `$RESEARCH_MODE` and research file exists: `${QUICK_DIR}/${quick_id}-RESEARCH.md`
|
||||
- If `$FULL_MODE` and verification file exists: `${QUICK_DIR}/${quick_id}-VERIFICATION.md`
|
||||
|
||||
```bash
|
||||
@@ -566,6 +670,7 @@ GSD > QUICK TASK COMPLETE (FULL MODE)
|
||||
|
||||
Quick Task ${quick_id}: ${DESCRIPTION}
|
||||
|
||||
${RESEARCH_MODE ? 'Research: ' + QUICK_DIR + '/' + quick_id + '-RESEARCH.md' : ''}
|
||||
Summary: ${QUICK_DIR}/${quick_id}-SUMMARY.md
|
||||
Verification: ${QUICK_DIR}/${quick_id}-VERIFICATION.md (${VERIFICATION_STATUS})
|
||||
Commit: ${commit_hash}
|
||||
@@ -583,6 +688,7 @@ GSD > QUICK TASK COMPLETE
|
||||
|
||||
Quick Task ${quick_id}: ${DESCRIPTION}
|
||||
|
||||
${RESEARCH_MODE ? 'Research: ' + QUICK_DIR + '/' + quick_id + '-RESEARCH.md' : ''}
|
||||
Summary: ${QUICK_DIR}/${quick_id}-SUMMARY.md
|
||||
Commit: ${commit_hash}
|
||||
|
||||
@@ -596,12 +702,13 @@ Ready for next task: /gsd:quick
|
||||
<success_criteria>
|
||||
- [ ] ROADMAP.md validation passes
|
||||
- [ ] User provides task description
|
||||
- [ ] `--full` and `--discuss` flags parsed from arguments when present
|
||||
- [ ] `--full`, `--discuss`, and `--research` flags parsed from arguments when present
|
||||
- [ ] Slug generated (lowercase, hyphens, max 40 chars)
|
||||
- [ ] Quick ID generated (YYMMDD-xxx format, 2s Base36 precision)
|
||||
- [ ] Directory created at `.planning/quick/YYMMDD-xxx-slug/`
|
||||
- [ ] (--discuss) Gray areas identified and presented, decisions captured in `${quick_id}-CONTEXT.md`
|
||||
- [ ] `${quick_id}-PLAN.md` created by planner (honors CONTEXT.md decisions when --discuss)
|
||||
- [ ] (--research) Research agent spawned, `${quick_id}-RESEARCH.md` created
|
||||
- [ ] `${quick_id}-PLAN.md` created by planner (honors CONTEXT.md decisions when --discuss, uses RESEARCH.md findings when --research)
|
||||
- [ ] (--full) Plan checker validates plan, revision loop capped at 2
|
||||
- [ ] `${quick_id}-SUMMARY.md` created by executor
|
||||
- [ ] (--full) `${quick_id}-VERIFICATION.md` created by verifier
|
||||
|
||||
297
tests/quick-research.test.cjs
Normal file
297
tests/quick-research.test.cjs
Normal file
@@ -0,0 +1,297 @@
|
||||
/**
|
||||
* GSD Quick Research Flag Tests
|
||||
*
|
||||
* Validates the --research flag for /gsd:quick:
|
||||
* - Command frontmatter advertises --research
|
||||
* - Workflow includes research step (Step 4.75)
|
||||
* - Research artifacts work within quick task directories
|
||||
* - Workflow spawns gsd-phase-researcher for research
|
||||
*/
|
||||
|
||||
const { test, describe, beforeEach, afterEach } = require('node:test');
|
||||
const assert = require('node:assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { runGsdTools, createTempProject, cleanup } = require('./helpers.cjs');
|
||||
|
||||
const COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'gsd');
|
||||
const WORKFLOWS_DIR = path.join(__dirname, '..', 'get-shit-done', 'workflows');
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Command frontmatter: --research flag advertised
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('quick command: --research in frontmatter', () => {
|
||||
const commandPath = path.join(COMMANDS_DIR, 'quick.md');
|
||||
let content;
|
||||
|
||||
test('quick.md exists', () => {
|
||||
assert.ok(fs.existsSync(commandPath), 'commands/gsd/quick.md should exist');
|
||||
});
|
||||
|
||||
test('argument-hint includes --research', () => {
|
||||
content = fs.readFileSync(commandPath, 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('--research'),
|
||||
'quick.md argument-hint should mention --research'
|
||||
);
|
||||
});
|
||||
|
||||
test('argument-hint includes all three flags', () => {
|
||||
content = fs.readFileSync(commandPath, 'utf-8');
|
||||
const hintLine = content.split('\n').find(l => l.includes('argument-hint'));
|
||||
assert.ok(hintLine, 'should have argument-hint line');
|
||||
assert.ok(hintLine.includes('--full'), 'argument-hint should include --full');
|
||||
assert.ok(hintLine.includes('--discuss'), 'argument-hint should include --discuss');
|
||||
assert.ok(hintLine.includes('--research'), 'argument-hint should include --research');
|
||||
});
|
||||
|
||||
test('objective section describes --research flag', () => {
|
||||
content = fs.readFileSync(commandPath, 'utf-8');
|
||||
const objectiveMatch = content.match(/<objective>([\s\S]*?)<\/objective>/);
|
||||
assert.ok(objectiveMatch, 'should have <objective> section');
|
||||
assert.ok(
|
||||
objectiveMatch[1].includes('--research'),
|
||||
'objective should describe --research flag'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Workflow: research step present and correct
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('quick workflow: research step', () => {
|
||||
const workflowPath = path.join(WORKFLOWS_DIR, 'quick.md');
|
||||
let content;
|
||||
|
||||
test('workflow file exists', () => {
|
||||
assert.ok(fs.existsSync(workflowPath), 'workflows/quick.md should exist');
|
||||
content = fs.readFileSync(workflowPath, 'utf-8');
|
||||
});
|
||||
|
||||
test('purpose mentions --research flag', () => {
|
||||
content = fs.readFileSync(workflowPath, 'utf-8');
|
||||
const purposeMatch = content.match(/<purpose>([\s\S]*?)<\/purpose>/);
|
||||
assert.ok(purposeMatch, 'should have <purpose> section');
|
||||
assert.ok(
|
||||
purposeMatch[1].includes('--research'),
|
||||
'purpose should mention --research flag'
|
||||
);
|
||||
});
|
||||
|
||||
test('step 1 parses --research flag', () => {
|
||||
content = fs.readFileSync(workflowPath, 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('$RESEARCH_MODE'),
|
||||
'workflow should reference $RESEARCH_MODE variable'
|
||||
);
|
||||
});
|
||||
|
||||
test('step 4.75 research phase exists', () => {
|
||||
content = fs.readFileSync(workflowPath, 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('Step 4.75'),
|
||||
'workflow should contain Step 4.75 (research phase)'
|
||||
);
|
||||
});
|
||||
|
||||
test('research step spawns gsd-phase-researcher', () => {
|
||||
content = fs.readFileSync(workflowPath, 'utf-8');
|
||||
const researchSection = content.substring(
|
||||
content.indexOf('Step 4.75'),
|
||||
content.indexOf('Step 5:')
|
||||
);
|
||||
assert.ok(
|
||||
researchSection.includes('subagent_type="gsd-phase-researcher"'),
|
||||
'research step should spawn gsd-phase-researcher agent'
|
||||
);
|
||||
});
|
||||
|
||||
test('research step writes RESEARCH.md', () => {
|
||||
content = fs.readFileSync(workflowPath, 'utf-8');
|
||||
const researchSection = content.substring(
|
||||
content.indexOf('Step 4.75'),
|
||||
content.indexOf('Step 5:')
|
||||
);
|
||||
assert.ok(
|
||||
researchSection.includes('RESEARCH.md'),
|
||||
'research step should reference RESEARCH.md output file'
|
||||
);
|
||||
});
|
||||
|
||||
test('planner context includes RESEARCH.md when research mode', () => {
|
||||
content = fs.readFileSync(workflowPath, 'utf-8');
|
||||
const plannerSection = content.substring(
|
||||
content.indexOf('Step 5: Spawn planner'),
|
||||
content.indexOf('Step 5.5')
|
||||
);
|
||||
assert.ok(
|
||||
plannerSection.includes('RESEARCH_MODE') && plannerSection.includes('RESEARCH.md'),
|
||||
'planner should read RESEARCH.md when $RESEARCH_MODE is true'
|
||||
);
|
||||
});
|
||||
|
||||
test('file commit list includes RESEARCH.md', () => {
|
||||
content = fs.readFileSync(workflowPath, 'utf-8');
|
||||
const commitSection = content.substring(
|
||||
content.indexOf('Step 8:'),
|
||||
content.indexOf('</process>')
|
||||
);
|
||||
assert.ok(
|
||||
commitSection.includes('RESEARCH_MODE') && commitSection.includes('RESEARCH.md'),
|
||||
'commit step should include RESEARCH.md when research mode is active'
|
||||
);
|
||||
});
|
||||
|
||||
test('success criteria includes research items', () => {
|
||||
content = fs.readFileSync(workflowPath, 'utf-8');
|
||||
const criteriaMatch = content.match(/<success_criteria>([\s\S]*?)<\/success_criteria>/);
|
||||
assert.ok(criteriaMatch, 'should have <success_criteria> section');
|
||||
assert.ok(
|
||||
criteriaMatch[1].includes('--research'),
|
||||
'success criteria should mention --research flag'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Quick task directory: RESEARCH.md file management
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('quick task: research file in task directory', () => {
|
||||
let tmpDir;
|
||||
|
||||
beforeEach(() => {
|
||||
tmpDir = createTempProject();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup(tmpDir);
|
||||
});
|
||||
|
||||
test('init quick returns valid task_dir for research file placement', () => {
|
||||
const result = runGsdTools('init quick "Add caching layer"', tmpDir);
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const output = JSON.parse(result.output);
|
||||
assert.ok(output.task_dir, 'task_dir should be non-null');
|
||||
assert.ok(
|
||||
output.task_dir.startsWith('.planning/quick/'),
|
||||
'task_dir should be under .planning/quick/'
|
||||
);
|
||||
|
||||
const expectedResearchPath = path.join(
|
||||
output.task_dir,
|
||||
`${output.next_num}-RESEARCH.md`
|
||||
);
|
||||
assert.ok(
|
||||
expectedResearchPath.endsWith('-RESEARCH.md'),
|
||||
'research path should end with -RESEARCH.md'
|
||||
);
|
||||
});
|
||||
|
||||
test('verify-path-exists detects RESEARCH.md in quick task directory', () => {
|
||||
const quickTaskDir = path.join(tmpDir, '.planning', 'quick', '1-test-task');
|
||||
fs.mkdirSync(quickTaskDir, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(quickTaskDir, '1-RESEARCH.md'),
|
||||
'# Research\n\nFindings for test task.\n'
|
||||
);
|
||||
|
||||
const result = runGsdTools(
|
||||
'verify-path-exists .planning/quick/1-test-task/1-RESEARCH.md',
|
||||
tmpDir
|
||||
);
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const output = JSON.parse(result.output);
|
||||
assert.strictEqual(output.exists, true, 'RESEARCH.md should be detected');
|
||||
assert.strictEqual(output.type, 'file', 'should be detected as file');
|
||||
});
|
||||
|
||||
test('verify-path-exists returns false for missing RESEARCH.md', () => {
|
||||
const quickTaskDir = path.join(tmpDir, '.planning', 'quick', '1-test-task');
|
||||
fs.mkdirSync(quickTaskDir, { recursive: true });
|
||||
|
||||
const result = runGsdTools(
|
||||
'verify-path-exists .planning/quick/1-test-task/1-RESEARCH.md',
|
||||
tmpDir
|
||||
);
|
||||
assert.ok(result.success, `Command failed: ${result.error}`);
|
||||
|
||||
const output = JSON.parse(result.output);
|
||||
assert.strictEqual(output.exists, false, 'missing RESEARCH.md should return false');
|
||||
});
|
||||
|
||||
test('quick task directory supports all research workflow artifacts', () => {
|
||||
const quickTaskDir = path.join(tmpDir, '.planning', 'quick', '1-add-caching');
|
||||
fs.mkdirSync(quickTaskDir, { recursive: true });
|
||||
|
||||
const artifacts = [
|
||||
'1-CONTEXT.md',
|
||||
'1-RESEARCH.md',
|
||||
'1-PLAN.md',
|
||||
'1-SUMMARY.md',
|
||||
'1-VERIFICATION.md',
|
||||
];
|
||||
|
||||
for (const artifact of artifacts) {
|
||||
fs.writeFileSync(path.join(quickTaskDir, artifact), `# ${artifact}\n`);
|
||||
}
|
||||
|
||||
for (const artifact of artifacts) {
|
||||
const result = runGsdTools(
|
||||
`verify-path-exists .planning/quick/1-add-caching/${artifact}`,
|
||||
tmpDir
|
||||
);
|
||||
assert.ok(result.success, `Command failed for ${artifact}: ${result.error}`);
|
||||
const output = JSON.parse(result.output);
|
||||
assert.strictEqual(
|
||||
output.exists,
|
||||
true,
|
||||
`${artifact} should exist in quick task directory`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Flag composability: banner variants in workflow
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
describe('quick workflow: banner variants for flag combinations', () => {
|
||||
let content;
|
||||
|
||||
test('has banner for research-only mode', () => {
|
||||
content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'quick.md'), 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('QUICK TASK (RESEARCH)'),
|
||||
'should have banner for --research only'
|
||||
);
|
||||
});
|
||||
|
||||
test('has banner for discuss + research mode', () => {
|
||||
content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'quick.md'), 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('DISCUSS + RESEARCH)'),
|
||||
'should have banner for --discuss --research'
|
||||
);
|
||||
});
|
||||
|
||||
test('has banner for research + full mode', () => {
|
||||
content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'quick.md'), 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('RESEARCH + FULL)'),
|
||||
'should have banner for --research --full'
|
||||
);
|
||||
});
|
||||
|
||||
test('has banner for all three flags', () => {
|
||||
content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'quick.md'), 'utf-8');
|
||||
assert.ok(
|
||||
content.includes('DISCUSS + RESEARCH + FULL)'),
|
||||
'should have banner for --discuss --research --full'
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user