diff --git a/commands/gsd/explore.md b/commands/gsd/explore.md new file mode 100644 index 00000000..d1bd2a33 --- /dev/null +++ b/commands/gsd/explore.md @@ -0,0 +1,27 @@ +--- +name: gsd:explore +description: Socratic ideation and idea routing — think through ideas before committing to plans +allowed-tools: + - Read + - Write + - Bash + - Grep + - Glob + - Task + - AskUserQuestion +--- + +Open-ended Socratic ideation session. Guides the developer through exploring an idea via +probing questions, optionally spawns research, then routes outputs to the appropriate GSD +artifacts (notes, todos, seeds, research questions, requirements, or new phases). + +Accepts an optional topic argument: `/gsd-explore authentication strategy` + + + +@~/.claude/get-shit-done/workflows/explore.md + + + +Execute the explore workflow from @~/.claude/get-shit-done/workflows/explore.md end-to-end. + diff --git a/get-shit-done/workflows/explore.md b/get-shit-done/workflows/explore.md new file mode 100644 index 00000000..f6afd6f4 --- /dev/null +++ b/get-shit-done/workflows/explore.md @@ -0,0 +1,139 @@ + +Socratic ideation workflow. Guides the developer through exploring an idea via probing questions, +offers mid-conversation research when useful, then routes crystallized outputs to GSD artifacts. + + + +Read all files referenced by the invoking prompt's execution_context before starting. + +@~/.claude/get-shit-done/references/questioning.md +@~/.claude/get-shit-done/references/domain-probes.md + + + +Valid GSD subagent types (use exact names — do not fall back to 'general-purpose'): +- gsd-phase-researcher — Researches specific questions and returns concise findings + + + + +## Step 1: Open the conversation + +If a topic was provided, acknowledge it and begin exploring: +``` +## Explore: {topic} + +Let's think through this together. I'll ask questions to help clarify the idea +before we commit to any artifacts. +``` + +If no topic, ask: +``` +## Explore + +What's on your mind? This could be a feature idea, an architectural question, +a problem you're trying to solve, or something you're not sure about yet. +``` + +## Step 2: Socratic conversation (2-5 exchanges) + +Guide the conversation using principles from `questioning.md` and `domain-probes.md`: + +- Ask **one question at a time** (never a list of questions) +- Questions should probe: constraints, tradeoffs, users, scope, dependencies, risks +- Use domain-specific probes contextually when the topic touches a known domain +- Listen for signals: "or" / "versus" / "tradeoff" indicate competing priorities worth exploring +- Reflect back what you hear to confirm understanding before moving forward + +**Conversation should feel natural, not formulaic.** Avoid rigid sequences. Follow the developer's energy — if they're excited about one aspect, go deeper there. + +## Step 3: Mid-conversation research offer (after 2-3 exchanges) + +If the conversation surfaces factual questions, technology comparisons, or unknowns that research could resolve, offer: + +``` +This touches on [specific question]. Want me to do a quick research pass before we continue? +This would take ~30 seconds and might surface useful context. + +[Yes, research this] / [No, let's keep exploring] +``` + +If yes, spawn a research agent: +``` +Task( + prompt="Quick research: {specific_question}. Return 3-5 key findings, no more than 200 words.", + subagent_type="gsd-phase-researcher" +) +``` + +Share findings and continue the conversation. + +If the topic doesn't warrant research, skip this step entirely. **Don't force it.** + +## Step 4: Crystallize outputs (after 3-6 exchanges) + +When the conversation reaches natural conclusions or the developer signals readiness, propose outputs. Analyze the conversation to identify what was discussed and suggest **up to 4 outputs** from: + +| Type | Destination | When to suggest | +|------|-------------|-----------------| +| Note | `.planning/notes/{slug}.md` | Observations, context, decisions worth remembering | +| Todo | `.planning/todos/pending/{slug}.md` | Concrete actionable tasks identified | +| Seed | `.planning/seeds/{slug}.md` | Forward-looking ideas with trigger conditions | +| Research question | `.planning/research/questions.md` (append) | Open questions that need deeper investigation | +| Requirement | `REQUIREMENTS.md` (append) | Clear requirements that emerged from discussion | +| New phase | `ROADMAP.md` (append) | Scope large enough to warrant its own phase | + +Present suggestions: +``` +Based on our conversation, I'd suggest capturing: + +1. **Note:** "Authentication strategy decisions" — your reasoning about JWT vs sessions +2. **Todo:** "Evaluate Passport.js vs custom middleware" — the comparison you want to do +3. **Seed:** "OAuth2 provider support" — trigger: when user management phase starts + +Create these? You can select specific ones or modify them. + +[Create all] / [Let me pick] / [Skip — just exploring] +``` + +**Never write artifacts without explicit user selection.** + +## Step 5: Write selected outputs + +For each selected output, write the file: + +- **Notes:** Create `.planning/notes/{slug}.md` with frontmatter (title, date, context) +- **Todos:** Create `.planning/todos/pending/{slug}.md` with frontmatter (title, date, priority) +- **Seeds:** Create `.planning/seeds/{slug}.md` with frontmatter (title, trigger_condition, planted_date) +- **Research questions:** Append to `.planning/research/questions.md` +- **Requirements:** Append to `.planning/REQUIREMENTS.md` with next available REQ ID +- **Phases:** Use existing `/gsd-add-phase` command via SlashCommand + +Commit if `commit_docs` is enabled: +```bash +node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs: capture exploration — {topic_slug}" --files {file_list} +``` + +## Step 6: Close + +``` +## Exploration Complete + +**Topic:** {topic} +**Outputs:** {count} artifact(s) created +{list of created files} + +Continue exploring with `/gsd-explore` or start working with `/gsd-next`. +``` + + + + +- [ ] Socratic conversation follows questioning.md principles +- [ ] Questions asked one at a time, not in batches +- [ ] Research offered contextually (not forced) +- [ ] Up to 4 outputs proposed from conversation +- [ ] User explicitly selects which outputs to create +- [ ] Files written to correct destinations +- [ ] Commit respects commit_docs config + diff --git a/tests/explore-command.test.cjs b/tests/explore-command.test.cjs new file mode 100644 index 00000000..a73c1eae --- /dev/null +++ b/tests/explore-command.test.cjs @@ -0,0 +1,72 @@ +const { describe, test } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('fs'); +const path = require('path'); + +describe('explore command', () => { + test('command file exists', () => { + const p = path.join(__dirname, '..', 'commands', 'gsd', 'explore.md'); + assert.ok(fs.existsSync(p), 'commands/gsd/explore.md should exist'); + }); + + test('command file has required frontmatter', () => { + const p = path.join(__dirname, '..', 'commands', 'gsd', 'explore.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok(content.includes('name: gsd:explore'), 'Command must have name frontmatter'); + assert.ok(content.includes('description:'), 'Command must have description frontmatter'); + assert.ok(content.includes('allowed-tools:'), 'Command must have allowed-tools frontmatter'); + }); + + test('workflow file exists', () => { + const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'explore.md'); + assert.ok(fs.existsSync(p), 'workflows/explore.md should exist'); + }); + + test('workflow references questioning.md and domain-probes.md', () => { + const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'explore.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok(content.includes('questioning.md'), 'Workflow must reference questioning.md'); + assert.ok(content.includes('domain-probes.md'), 'Workflow must reference domain-probes.md'); + }); + + test('workflow documents all 6 output types', () => { + const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'explore.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok(content.includes('Note'), 'Workflow must document Note output type'); + assert.ok(content.includes('Todo'), 'Workflow must document Todo output type'); + assert.ok(content.includes('Seed'), 'Workflow must document Seed output type'); + assert.ok(content.includes('Research question'), 'Workflow must document Research question output type'); + assert.ok(content.includes('Requirement'), 'Workflow must document Requirement output type'); + assert.ok(content.includes('New phase') || content.includes('phase'), 'Workflow must document New phase output type'); + }); + + test('workflow enforces one question at a time principle', () => { + const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'explore.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok(content.includes('one question at a time'), 'Workflow must mention "one question at a time" principle'); + }); + + test('workflow requires user confirmation before writing artifacts', () => { + const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'explore.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok( + content.includes('explicit user selection') || content.includes('Never write artifacts without'), + 'Workflow must require user confirmation before writing artifacts' + ); + }); + + test('workflow respects commit_docs config', () => { + const p = path.join(__dirname, '..', 'get-shit-done', 'workflows', 'explore.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok(content.includes('commit_docs'), 'Workflow must respect commit_docs configuration'); + }); + + test('command references the workflow via execution_context', () => { + const p = path.join(__dirname, '..', 'commands', 'gsd', 'explore.md'); + const content = fs.readFileSync(p, 'utf-8'); + assert.ok( + content.includes('workflows/explore.md'), + 'Command must reference workflows/explore.md in execution_context' + ); + }); +});