mirror of
https://github.com/obra/superpowers.git
synced 2026-05-11 03:29:04 +08:00
tests: remove subagent-driven-dev fixtures (covered by drill sdd-go-fractals + sdd-svelte-todo)
The bash test had ZERO output assertions — it just ran claude -p
and printed token usage. Drill's scenarios are strictly more
rigorous:
go-fractals: skill-called SDD + tool-called Agent + go test ./...
passes + cmd/fractals/main.go exists + >=4 commits + LLM criteria
verifying real SDD workflow.
svelte-todo: skill-called SDD + tool-called Agent + npm test passes
+ playwright e2e passes + package.json + svelte.config.js or
vite.config.ts + >=4 commits + LLM criteria.
design.md and plan.md are byte-identical between bash fixtures and
drill fixtures (evals/fixtures/sdd-{go-fractals,svelte-todo}/).
Drill's setup helper (scaffold_sdd_*) forces git init -b main
(stricter than bash's reliance on init.defaultBranch). The
.claude/settings.local.json from bash scaffold.sh is unnecessary
for drill since permissions are managed via backend YAML.
Subagent verification: SAFE TO DELETE for both.
This commit is contained in:
committed by
Drew Ritter
parent
f10cddac0d
commit
c0a65f1b4d
@@ -1,81 +0,0 @@
|
|||||||
# Go Fractals CLI - Design
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
A command-line tool that generates ASCII art fractals. Supports two fractal types with configurable output.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Sierpinski triangle
|
|
||||||
fractals sierpinski --size 32 --depth 5
|
|
||||||
|
|
||||||
# Mandelbrot set
|
|
||||||
fractals mandelbrot --width 80 --height 24 --iterations 100
|
|
||||||
|
|
||||||
# Custom character
|
|
||||||
fractals sierpinski --size 16 --char '#'
|
|
||||||
|
|
||||||
# Help
|
|
||||||
fractals --help
|
|
||||||
fractals sierpinski --help
|
|
||||||
```
|
|
||||||
|
|
||||||
## Commands
|
|
||||||
|
|
||||||
### `sierpinski`
|
|
||||||
|
|
||||||
Generates a Sierpinski triangle using recursive subdivision.
|
|
||||||
|
|
||||||
Flags:
|
|
||||||
- `--size` (default: 32) - Width of the triangle base in characters
|
|
||||||
- `--depth` (default: 5) - Recursion depth
|
|
||||||
- `--char` (default: '*') - Character to use for filled points
|
|
||||||
|
|
||||||
Output: Triangle printed to stdout, one line per row.
|
|
||||||
|
|
||||||
### `mandelbrot`
|
|
||||||
|
|
||||||
Renders the Mandelbrot set as ASCII art. Maps iteration count to characters.
|
|
||||||
|
|
||||||
Flags:
|
|
||||||
- `--width` (default: 80) - Output width in characters
|
|
||||||
- `--height` (default: 24) - Output height in characters
|
|
||||||
- `--iterations` (default: 100) - Maximum iterations for escape calculation
|
|
||||||
- `--char` (default: gradient) - Single character, or omit for gradient " .:-=+*#%@"
|
|
||||||
|
|
||||||
Output: Rectangle printed to stdout.
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
cmd/
|
|
||||||
fractals/
|
|
||||||
main.go # Entry point, CLI setup
|
|
||||||
internal/
|
|
||||||
sierpinski/
|
|
||||||
sierpinski.go # Algorithm
|
|
||||||
sierpinski_test.go
|
|
||||||
mandelbrot/
|
|
||||||
mandelbrot.go # Algorithm
|
|
||||||
mandelbrot_test.go
|
|
||||||
cli/
|
|
||||||
root.go # Root command, help
|
|
||||||
sierpinski.go # Sierpinski subcommand
|
|
||||||
mandelbrot.go # Mandelbrot subcommand
|
|
||||||
```
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
- Go 1.21+
|
|
||||||
- `github.com/spf13/cobra` for CLI
|
|
||||||
|
|
||||||
## Acceptance Criteria
|
|
||||||
|
|
||||||
1. `fractals --help` shows usage
|
|
||||||
2. `fractals sierpinski` outputs a recognizable triangle
|
|
||||||
3. `fractals mandelbrot` outputs a recognizable Mandelbrot set
|
|
||||||
4. `--size`, `--width`, `--height`, `--depth`, `--iterations` flags work
|
|
||||||
5. `--char` customizes output character
|
|
||||||
6. Invalid inputs produce clear error messages
|
|
||||||
7. All tests pass
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
# Go Fractals CLI - Implementation Plan
|
|
||||||
|
|
||||||
Execute this plan using the `superpowers:subagent-driven-development` skill.
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
Building a CLI tool that generates ASCII fractals. See `design.md` for full specification.
|
|
||||||
|
|
||||||
## Tasks
|
|
||||||
|
|
||||||
### Task 1: Project Setup
|
|
||||||
|
|
||||||
Create the Go module and directory structure.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Initialize `go.mod` with module name `github.com/superpowers-test/fractals`
|
|
||||||
- Create directory structure: `cmd/fractals/`, `internal/sierpinski/`, `internal/mandelbrot/`, `internal/cli/`
|
|
||||||
- Create minimal `cmd/fractals/main.go` that prints "fractals cli"
|
|
||||||
- Add `github.com/spf13/cobra` dependency
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `go build ./cmd/fractals` succeeds
|
|
||||||
- `./fractals` prints "fractals cli"
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 2: CLI Framework with Help
|
|
||||||
|
|
||||||
Set up Cobra root command with help output.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `internal/cli/root.go` with root command
|
|
||||||
- Configure help text showing available subcommands
|
|
||||||
- Wire root command into `main.go`
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `./fractals --help` shows usage with "sierpinski" and "mandelbrot" listed as available commands
|
|
||||||
- `./fractals` (no args) shows help
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 3: Sierpinski Algorithm
|
|
||||||
|
|
||||||
Implement the Sierpinski triangle generation algorithm.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `internal/sierpinski/sierpinski.go`
|
|
||||||
- Implement `Generate(size, depth int, char rune) []string` that returns lines of the triangle
|
|
||||||
- Use recursive midpoint subdivision algorithm
|
|
||||||
- Create `internal/sierpinski/sierpinski_test.go` with tests:
|
|
||||||
- Small triangle (size=4, depth=2) matches expected output
|
|
||||||
- Size=1 returns single character
|
|
||||||
- Depth=0 returns filled triangle
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `go test ./internal/sierpinski/...` passes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 4: Sierpinski CLI Integration
|
|
||||||
|
|
||||||
Wire the Sierpinski algorithm to a CLI subcommand.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `internal/cli/sierpinski.go` with `sierpinski` subcommand
|
|
||||||
- Add flags: `--size` (default 32), `--depth` (default 5), `--char` (default '*')
|
|
||||||
- Call `sierpinski.Generate()` and print result to stdout
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `./fractals sierpinski` outputs a triangle
|
|
||||||
- `./fractals sierpinski --size 16 --depth 3` outputs smaller triangle
|
|
||||||
- `./fractals sierpinski --help` shows flag documentation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 5: Mandelbrot Algorithm
|
|
||||||
|
|
||||||
Implement the Mandelbrot set ASCII renderer.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `internal/mandelbrot/mandelbrot.go`
|
|
||||||
- Implement `Render(width, height, maxIter int, char string) []string`
|
|
||||||
- Map complex plane region (-2.5 to 1.0 real, -1.0 to 1.0 imaginary) to output dimensions
|
|
||||||
- Map iteration count to character gradient " .:-=+*#%@" (or single char if provided)
|
|
||||||
- Create `internal/mandelbrot/mandelbrot_test.go` with tests:
|
|
||||||
- Output dimensions match requested width/height
|
|
||||||
- Known point inside set (0,0) maps to max-iteration character
|
|
||||||
- Known point outside set (2,0) maps to low-iteration character
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `go test ./internal/mandelbrot/...` passes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 6: Mandelbrot CLI Integration
|
|
||||||
|
|
||||||
Wire the Mandelbrot algorithm to a CLI subcommand.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `internal/cli/mandelbrot.go` with `mandelbrot` subcommand
|
|
||||||
- Add flags: `--width` (default 80), `--height` (default 24), `--iterations` (default 100), `--char` (default "")
|
|
||||||
- Call `mandelbrot.Render()` and print result to stdout
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `./fractals mandelbrot` outputs recognizable Mandelbrot set
|
|
||||||
- `./fractals mandelbrot --width 40 --height 12` outputs smaller version
|
|
||||||
- `./fractals mandelbrot --help` shows flag documentation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 7: Character Set Configuration
|
|
||||||
|
|
||||||
Ensure `--char` flag works consistently across both commands.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Verify Sierpinski `--char` flag passes character to algorithm
|
|
||||||
- For Mandelbrot, `--char` should use single character instead of gradient
|
|
||||||
- Add tests for custom character output
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `./fractals sierpinski --char '#'` uses '#' character
|
|
||||||
- `./fractals mandelbrot --char '.'` uses '.' for all filled points
|
|
||||||
- Tests pass
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 8: Input Validation and Error Handling
|
|
||||||
|
|
||||||
Add validation for invalid inputs.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Sierpinski: size must be > 0, depth must be >= 0
|
|
||||||
- Mandelbrot: width/height must be > 0, iterations must be > 0
|
|
||||||
- Return clear error messages for invalid inputs
|
|
||||||
- Add tests for error cases
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `./fractals sierpinski --size 0` prints error, exits non-zero
|
|
||||||
- `./fractals mandelbrot --width -1` prints error, exits non-zero
|
|
||||||
- Error messages are clear and helpful
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 9: Integration Tests
|
|
||||||
|
|
||||||
Add integration tests that invoke the CLI.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `cmd/fractals/main_test.go` or `test/integration_test.go`
|
|
||||||
- Test full CLI invocation for both commands
|
|
||||||
- Verify output format and exit codes
|
|
||||||
- Test error cases return non-zero exit
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `go test ./...` passes all tests including integration tests
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 10: README
|
|
||||||
|
|
||||||
Document usage and examples.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `README.md` with:
|
|
||||||
- Project description
|
|
||||||
- Installation: `go install ./cmd/fractals`
|
|
||||||
- Usage examples for both commands
|
|
||||||
- Example output (small samples)
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- README accurately describes the tool
|
|
||||||
- Examples in README actually work
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Scaffold the Go Fractals test project
|
|
||||||
# Usage: ./scaffold.sh /path/to/target/directory
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
TARGET_DIR="${1:?Usage: $0 <target-directory>}"
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
||||||
|
|
||||||
# Create target directory
|
|
||||||
mkdir -p "$TARGET_DIR"
|
|
||||||
cd "$TARGET_DIR"
|
|
||||||
|
|
||||||
# Initialize git repo
|
|
||||||
git init
|
|
||||||
|
|
||||||
# Copy design and plan
|
|
||||||
cp "$SCRIPT_DIR/design.md" .
|
|
||||||
cp "$SCRIPT_DIR/plan.md" .
|
|
||||||
|
|
||||||
# Create .claude settings to allow reads/writes in this directory
|
|
||||||
mkdir -p .claude
|
|
||||||
cat > .claude/settings.local.json << 'SETTINGS'
|
|
||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"Read(**)",
|
|
||||||
"Edit(**)",
|
|
||||||
"Write(**)",
|
|
||||||
"Bash(go:*)",
|
|
||||||
"Bash(mkdir:*)",
|
|
||||||
"Bash(git:*)"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SETTINGS
|
|
||||||
|
|
||||||
# Create initial commit
|
|
||||||
git add .
|
|
||||||
git commit -m "Initial project setup with design and plan"
|
|
||||||
|
|
||||||
echo "Scaffolded Go Fractals project at: $TARGET_DIR"
|
|
||||||
echo ""
|
|
||||||
echo "To run the test:"
|
|
||||||
echo " claude -p \"Execute this plan using superpowers:subagent-driven-development. Plan: $TARGET_DIR/plan.md\" --plugin-dir /path/to/superpowers"
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Run a subagent-driven-development test
|
|
||||||
# Usage: ./run-test.sh <test-name> [--plugin-dir <path>]
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# ./run-test.sh go-fractals
|
|
||||||
# ./run-test.sh svelte-todo --plugin-dir /path/to/superpowers
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
||||||
TEST_NAME="${1:?Usage: $0 <test-name> [--plugin-dir <path>]}"
|
|
||||||
shift
|
|
||||||
|
|
||||||
# Parse optional arguments
|
|
||||||
PLUGIN_DIR=""
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case $1 in
|
|
||||||
--plugin-dir)
|
|
||||||
PLUGIN_DIR="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown option: $1"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# Default plugin dir to parent of tests directory
|
|
||||||
if [[ -z "$PLUGIN_DIR" ]]; then
|
|
||||||
PLUGIN_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Verify test exists
|
|
||||||
TEST_DIR="$SCRIPT_DIR/$TEST_NAME"
|
|
||||||
if [[ ! -d "$TEST_DIR" ]]; then
|
|
||||||
echo "Error: Test '$TEST_NAME' not found at $TEST_DIR"
|
|
||||||
echo "Available tests:"
|
|
||||||
ls -1 "$SCRIPT_DIR" | grep -v '\.sh$' | grep -v '\.md$'
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create timestamped output directory
|
|
||||||
TIMESTAMP=$(date +%s)
|
|
||||||
OUTPUT_BASE="/tmp/superpowers-tests/$TIMESTAMP/subagent-driven-development"
|
|
||||||
OUTPUT_DIR="$OUTPUT_BASE/$TEST_NAME"
|
|
||||||
mkdir -p "$OUTPUT_DIR"
|
|
||||||
|
|
||||||
echo "=== Subagent-Driven Development Test ==="
|
|
||||||
echo "Test: $TEST_NAME"
|
|
||||||
echo "Output: $OUTPUT_DIR"
|
|
||||||
echo "Plugin: $PLUGIN_DIR"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Scaffold the project
|
|
||||||
echo ">>> Scaffolding project..."
|
|
||||||
"$TEST_DIR/scaffold.sh" "$OUTPUT_DIR/project"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Prepare the prompt
|
|
||||||
PLAN_PATH="$OUTPUT_DIR/project/plan.md"
|
|
||||||
PROMPT="Execute this plan using superpowers:subagent-driven-development. The plan is at: $PLAN_PATH"
|
|
||||||
|
|
||||||
# Run Claude with JSON output for token tracking
|
|
||||||
LOG_FILE="$OUTPUT_DIR/claude-output.json"
|
|
||||||
echo ">>> Running Claude..."
|
|
||||||
echo "Prompt: $PROMPT"
|
|
||||||
echo "Log file: $LOG_FILE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Run claude and capture output
|
|
||||||
# Using stream-json to get token usage stats
|
|
||||||
# --dangerously-skip-permissions for automated testing (subagents don't inherit parent settings)
|
|
||||||
cd "$OUTPUT_DIR/project"
|
|
||||||
claude -p "$PROMPT" \
|
|
||||||
--plugin-dir "$PLUGIN_DIR" \
|
|
||||||
--dangerously-skip-permissions \
|
|
||||||
--output-format stream-json \
|
|
||||||
--verbose \
|
|
||||||
> "$LOG_FILE" 2>&1 || true
|
|
||||||
|
|
||||||
# Extract final stats
|
|
||||||
echo ""
|
|
||||||
echo ">>> Test complete"
|
|
||||||
echo "Project directory: $OUTPUT_DIR/project"
|
|
||||||
echo "Claude log: $LOG_FILE"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Show token usage if available
|
|
||||||
if command -v jq &> /dev/null; then
|
|
||||||
echo ">>> Token usage:"
|
|
||||||
# Extract usage from the last message with usage info
|
|
||||||
jq -s '[.[] | select(.type == "result")] | last | .usage' "$LOG_FILE" 2>/dev/null || echo "(could not parse usage)"
|
|
||||||
echo ""
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ">>> Next steps:"
|
|
||||||
echo "1. Review the project: cd $OUTPUT_DIR/project"
|
|
||||||
echo "2. Review Claude's log: less $LOG_FILE"
|
|
||||||
echo "3. Check if tests pass:"
|
|
||||||
if [[ "$TEST_NAME" == "go-fractals" ]]; then
|
|
||||||
echo " cd $OUTPUT_DIR/project && go test ./..."
|
|
||||||
elif [[ "$TEST_NAME" == "svelte-todo" ]]; then
|
|
||||||
echo " cd $OUTPUT_DIR/project && npm test && npx playwright test"
|
|
||||||
fi
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
# Svelte Todo List - Design
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
A simple todo list application built with Svelte. Supports creating, completing, and deleting todos with localStorage persistence.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Add new todos
|
|
||||||
- Mark todos as complete/incomplete
|
|
||||||
- Delete todos
|
|
||||||
- Filter by: All / Active / Completed
|
|
||||||
- Clear all completed todos
|
|
||||||
- Persist to localStorage
|
|
||||||
- Show count of remaining items
|
|
||||||
|
|
||||||
## User Interface
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────┐
|
|
||||||
│ Svelte Todos │
|
|
||||||
├─────────────────────────────────────────┤
|
|
||||||
│ [________________________] [Add] │
|
|
||||||
├─────────────────────────────────────────┤
|
|
||||||
│ [ ] Buy groceries [x] │
|
|
||||||
│ [✓] Walk the dog [x] │
|
|
||||||
│ [ ] Write code [x] │
|
|
||||||
├─────────────────────────────────────────┤
|
|
||||||
│ 2 items left │
|
|
||||||
│ [All] [Active] [Completed] [Clear ✓] │
|
|
||||||
└─────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
## Components
|
|
||||||
|
|
||||||
```
|
|
||||||
src/
|
|
||||||
App.svelte # Main app, state management
|
|
||||||
lib/
|
|
||||||
TodoInput.svelte # Text input + Add button
|
|
||||||
TodoList.svelte # List container
|
|
||||||
TodoItem.svelte # Single todo with checkbox, text, delete
|
|
||||||
FilterBar.svelte # Filter buttons + clear completed
|
|
||||||
store.ts # Svelte store for todos
|
|
||||||
storage.ts # localStorage persistence
|
|
||||||
```
|
|
||||||
|
|
||||||
## Data Model
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
interface Todo {
|
|
||||||
id: string; // UUID
|
|
||||||
text: string; // Todo text
|
|
||||||
completed: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Filter = 'all' | 'active' | 'completed';
|
|
||||||
```
|
|
||||||
|
|
||||||
## Acceptance Criteria
|
|
||||||
|
|
||||||
1. Can add a todo by typing and pressing Enter or clicking Add
|
|
||||||
2. Can toggle todo completion by clicking checkbox
|
|
||||||
3. Can delete a todo by clicking X button
|
|
||||||
4. Filter buttons show correct subset of todos
|
|
||||||
5. "X items left" shows count of incomplete todos
|
|
||||||
6. "Clear completed" removes all completed todos
|
|
||||||
7. Todos persist across page refresh (localStorage)
|
|
||||||
8. Empty state shows helpful message
|
|
||||||
9. All tests pass
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
# Svelte Todo List - Implementation Plan
|
|
||||||
|
|
||||||
Execute this plan using the `superpowers:subagent-driven-development` skill.
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
Building a todo list app with Svelte. See `design.md` for full specification.
|
|
||||||
|
|
||||||
## Tasks
|
|
||||||
|
|
||||||
### Task 1: Project Setup
|
|
||||||
|
|
||||||
Create the Svelte project with Vite.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Run `npm create vite@latest . -- --template svelte-ts`
|
|
||||||
- Install dependencies with `npm install`
|
|
||||||
- Verify dev server works
|
|
||||||
- Clean up default Vite template content from App.svelte
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `npm run dev` starts server
|
|
||||||
- App shows minimal "Svelte Todos" heading
|
|
||||||
- `npm run build` succeeds
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 2: Todo Store
|
|
||||||
|
|
||||||
Create the Svelte store for todo state management.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `src/lib/store.ts`
|
|
||||||
- Define `Todo` interface with id, text, completed
|
|
||||||
- Create writable store with initial empty array
|
|
||||||
- Export functions: `addTodo(text)`, `toggleTodo(id)`, `deleteTodo(id)`, `clearCompleted()`
|
|
||||||
- Create `src/lib/store.test.ts` with tests for each function
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- Tests pass: `npm run test` (install vitest if needed)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 3: localStorage Persistence
|
|
||||||
|
|
||||||
Add persistence layer for todos.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `src/lib/storage.ts`
|
|
||||||
- Implement `loadTodos(): Todo[]` and `saveTodos(todos: Todo[])`
|
|
||||||
- Handle JSON parse errors gracefully (return empty array)
|
|
||||||
- Integrate with store: load on init, save on change
|
|
||||||
- Add tests for load/save/error handling
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- Tests pass
|
|
||||||
- Manual test: add todo, refresh page, todo persists
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 4: TodoInput Component
|
|
||||||
|
|
||||||
Create the input component for adding todos.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `src/lib/TodoInput.svelte`
|
|
||||||
- Text input bound to local state
|
|
||||||
- Add button calls `addTodo()` and clears input
|
|
||||||
- Enter key also submits
|
|
||||||
- Disable Add button when input is empty
|
|
||||||
- Add component tests
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- Tests pass
|
|
||||||
- Component renders input and button
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 5: TodoItem Component
|
|
||||||
|
|
||||||
Create the single todo item component.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `src/lib/TodoItem.svelte`
|
|
||||||
- Props: `todo: Todo`
|
|
||||||
- Checkbox toggles completion (calls `toggleTodo`)
|
|
||||||
- Text with strikethrough when completed
|
|
||||||
- Delete button (X) calls `deleteTodo`
|
|
||||||
- Add component tests
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- Tests pass
|
|
||||||
- Component renders checkbox, text, delete button
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 6: TodoList Component
|
|
||||||
|
|
||||||
Create the list container component.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `src/lib/TodoList.svelte`
|
|
||||||
- Props: `todos: Todo[]`
|
|
||||||
- Renders TodoItem for each todo
|
|
||||||
- Shows "No todos yet" when empty
|
|
||||||
- Add component tests
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- Tests pass
|
|
||||||
- Component renders list of TodoItems
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 7: FilterBar Component
|
|
||||||
|
|
||||||
Create the filter and status bar component.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `src/lib/FilterBar.svelte`
|
|
||||||
- Props: `todos: Todo[]`, `filter: Filter`, `onFilterChange: (f: Filter) => void`
|
|
||||||
- Show count: "X items left" (incomplete count)
|
|
||||||
- Three filter buttons: All, Active, Completed
|
|
||||||
- Active filter is visually highlighted
|
|
||||||
- "Clear completed" button (hidden when no completed todos)
|
|
||||||
- Add component tests
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- Tests pass
|
|
||||||
- Component renders count, filters, clear button
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 8: App Integration
|
|
||||||
|
|
||||||
Wire all components together in App.svelte.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Import all components and store
|
|
||||||
- Add filter state (default: 'all')
|
|
||||||
- Compute filtered todos based on filter state
|
|
||||||
- Render: heading, TodoInput, TodoList, FilterBar
|
|
||||||
- Pass appropriate props to each component
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- App renders all components
|
|
||||||
- Adding todos works
|
|
||||||
- Toggling works
|
|
||||||
- Deleting works
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 9: Filter Functionality
|
|
||||||
|
|
||||||
Ensure filtering works end-to-end.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Verify filter buttons change displayed todos
|
|
||||||
- 'all' shows all todos
|
|
||||||
- 'active' shows only incomplete todos
|
|
||||||
- 'completed' shows only completed todos
|
|
||||||
- Clear completed removes completed todos and resets filter if needed
|
|
||||||
- Add integration tests
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- Filter tests pass
|
|
||||||
- Manual verification of all filter states
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 10: Styling and Polish
|
|
||||||
|
|
||||||
Add CSS styling for usability.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Style the app to match the design mockup
|
|
||||||
- Completed todos have strikethrough and muted color
|
|
||||||
- Active filter button is highlighted
|
|
||||||
- Input has focus styles
|
|
||||||
- Delete button appears on hover (or always on mobile)
|
|
||||||
- Responsive layout
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- App is visually usable
|
|
||||||
- Styles don't break functionality
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 11: End-to-End Tests
|
|
||||||
|
|
||||||
Add Playwright tests for full user flows.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Install Playwright: `npm init playwright@latest`
|
|
||||||
- Create `tests/todo.spec.ts`
|
|
||||||
- Test flows:
|
|
||||||
- Add a todo
|
|
||||||
- Complete a todo
|
|
||||||
- Delete a todo
|
|
||||||
- Filter todos
|
|
||||||
- Clear completed
|
|
||||||
- Persistence (add, reload, verify)
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- `npx playwright test` passes
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Task 12: README
|
|
||||||
|
|
||||||
Document the project.
|
|
||||||
|
|
||||||
**Do:**
|
|
||||||
- Create `README.md` with:
|
|
||||||
- Project description
|
|
||||||
- Setup: `npm install`
|
|
||||||
- Development: `npm run dev`
|
|
||||||
- Testing: `npm test` and `npx playwright test`
|
|
||||||
- Build: `npm run build`
|
|
||||||
|
|
||||||
**Verify:**
|
|
||||||
- README accurately describes the project
|
|
||||||
- Instructions work
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Scaffold the Svelte Todo test project
|
|
||||||
# Usage: ./scaffold.sh /path/to/target/directory
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
TARGET_DIR="${1:?Usage: $0 <target-directory>}"
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
||||||
|
|
||||||
# Create target directory
|
|
||||||
mkdir -p "$TARGET_DIR"
|
|
||||||
cd "$TARGET_DIR"
|
|
||||||
|
|
||||||
# Initialize git repo
|
|
||||||
git init
|
|
||||||
|
|
||||||
# Copy design and plan
|
|
||||||
cp "$SCRIPT_DIR/design.md" .
|
|
||||||
cp "$SCRIPT_DIR/plan.md" .
|
|
||||||
|
|
||||||
# Create .claude settings to allow reads/writes in this directory
|
|
||||||
mkdir -p .claude
|
|
||||||
cat > .claude/settings.local.json << 'SETTINGS'
|
|
||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"allow": [
|
|
||||||
"Read(**)",
|
|
||||||
"Edit(**)",
|
|
||||||
"Write(**)",
|
|
||||||
"Bash(npm:*)",
|
|
||||||
"Bash(npx:*)",
|
|
||||||
"Bash(mkdir:*)",
|
|
||||||
"Bash(git:*)"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SETTINGS
|
|
||||||
|
|
||||||
# Create initial commit
|
|
||||||
git add .
|
|
||||||
git commit -m "Initial project setup with design and plan"
|
|
||||||
|
|
||||||
echo "Scaffolded Svelte Todo project at: $TARGET_DIR"
|
|
||||||
echo ""
|
|
||||||
echo "To run the test:"
|
|
||||||
echo " claude -p \"Execute this plan using superpowers:subagent-driven-development. Plan: $TARGET_DIR/plan.md\" --plugin-dir /path/to/superpowers"
|
|
||||||
Reference in New Issue
Block a user