405 lines
19 KiB
Markdown
405 lines
19 KiB
Markdown
---
|
||
name: subagent-driven-development
|
||
description: "Execute plans via delegate_task subagents (2-stage review)."
|
||
version: 1.1.0
|
||
author: Hermes Agent (adapted from obra/superpowers)
|
||
license: MIT
|
||
platforms: [linux, macos, windows]
|
||
metadata:
|
||
hermes:
|
||
tags: [delegation, subagent, implementation, workflow, parallel]
|
||
related_skills: [writing-plans, requesting-code-review, test-driven-development]
|
||
---
|
||
|
||
# Subagent-Driven Development
|
||
|
||
## Overview
|
||
|
||
Execute implementation plans by dispatching fresh subagents per task with systematic two-stage review.
|
||
|
||
**Core principle:** Fresh subagent per task + two-stage review (spec then quality) = high quality, fast iteration.
|
||
|
||
## When to Use
|
||
|
||
Use this skill when:
|
||
- You have an implementation plan (from writing-plans skill or user requirements)
|
||
- Tasks are mostly independent
|
||
- Quality and spec compliance are important
|
||
- You want automated review between tasks
|
||
|
||
**Parallel fan-out preference:** When the user explicitly asks to delegate or the task involves building multiple independent pages/components (scaffolding, page builds, rewrites), use **parallel fan-out** (`delegate_task` with `tasks` array, up to 3 concurrent). Dispatch all independent pieces at once — no need for sequential 2-stage review on every single task. Follow up manually on anything the subagents didn't complete. The user prefers speed to perfect review discipline for bulk codegen.
|
||
|
||
**When NOT to use subagents — direct execution is better when:**
|
||
• The plan contains **exact, copy-pasteable code** for every file (mechanical extraction / file-creation tasks). A subagent that receives fully specified code and just has to write it adds delegation overhead with zero decision-making value.
|
||
• The task is a **pure refactor** that moves existing code between files without changing behavior. Writing the files yourself is faster, you keep awareness of structural interdependencies, and there's nothing for a reviewer to evaluate (spec = "move verbatim").
|
||
• You have already read all the files and know the exact state. Spinning up a subagent means re-explaining context they'd need to re-read anyway.
|
||
|
||
**Decision rule:** When the plan's task description includes the full file contents (`write_file`, `patch` snippets), execute directly. Reserve subagents for tasks where the plan gives a *spec* and expects the implementer to *design and write* code — that's where the review cycle adds value.
|
||
|
||
**vs. manual execution when subagents ARE the right tool:**
|
||
- Fresh context per task (no confusion from accumulated state)
|
||
- Automated review process catches issues early
|
||
- Consistent quality checks across all tasks
|
||
- Subagents can ask questions before starting work
|
||
|
||
## The Process
|
||
|
||
### 1. Read and Parse Plan
|
||
|
||
Read the plan file. Extract ALL tasks with their full text and context upfront. Create a todo list:
|
||
|
||
```python
|
||
# Read the plan
|
||
read_file("docs/plans/feature-plan.md")
|
||
|
||
# Create todo list with all tasks
|
||
todo([
|
||
{"id": "task-1", "content": "Create User model with email field", "status": "pending"},
|
||
{"id": "task-2", "content": "Add password hashing utility", "status": "pending"},
|
||
{"id": "task-3", "content": "Create login endpoint", "status": "pending"},
|
||
])
|
||
```
|
||
|
||
**Key:** Read the plan ONCE. Extract everything. Don't make subagents read the plan file — provide the full task text directly in context.
|
||
|
||
### 2. Per-Task Workflow
|
||
|
||
For EACH task in the plan:
|
||
|
||
#### Step 1: Dispatch Implementer Subagent
|
||
|
||
Use `delegate_task` with complete context:
|
||
|
||
```python
|
||
delegate_task(
|
||
goal="Implement Task 1: Create User model with email and password_hash fields",
|
||
context="""
|
||
TASK FROM PLAN:
|
||
- Create: src/models/user.py
|
||
- Add User class with email (str) and password_hash (str) fields
|
||
- Use bcrypt for password hashing
|
||
- Include __repr__ for debugging
|
||
|
||
FOLLOW TDD:
|
||
1. Write failing test in tests/models/test_user.py
|
||
2. Run: pytest tests/models/test_user.py -v (verify FAIL)
|
||
3. Write minimal implementation
|
||
4. Run: pytest tests/models/test_user.py -v (verify PASS)
|
||
5. Run: pytest tests/ -q (verify no regressions)
|
||
6. Commit: git add -A && git commit -m "feat: add User model with password hashing"
|
||
|
||
PROJECT CONTEXT:
|
||
- Python 3.11, Flask app in src/app.py
|
||
- Existing models in src/models/
|
||
- Tests use pytest, run from project root
|
||
- bcrypt already in requirements.txt
|
||
""",
|
||
toolsets=['terminal', 'file']
|
||
)
|
||
```
|
||
|
||
#### Step 2: Dispatch Spec Compliance Reviewer
|
||
|
||
After the implementer completes, verify against the original spec:
|
||
|
||
```python
|
||
delegate_task(
|
||
goal="Review if implementation matches the spec from the plan",
|
||
context="""
|
||
ORIGINAL TASK SPEC:
|
||
- Create src/models/user.py with User class
|
||
- Fields: email (str), password_hash (str)
|
||
- Use bcrypt for password hashing
|
||
- Include __repr__
|
||
|
||
CHECK:
|
||
- [ ] All requirements from spec implemented?
|
||
- [ ] File paths match spec?
|
||
- [ ] Function signatures match spec?
|
||
- [ ] Behavior matches expected?
|
||
- [ ] Nothing extra added (no scope creep)?
|
||
|
||
OUTPUT: PASS or list of specific spec gaps to fix.
|
||
""",
|
||
toolsets=['file']
|
||
)
|
||
```
|
||
|
||
**If spec issues found:** Fix gaps, then re-run spec review. Continue only when spec-compliant.
|
||
|
||
#### Step 3: Dispatch Code Quality Reviewer
|
||
|
||
After spec compliance passes:
|
||
|
||
```python
|
||
delegate_task(
|
||
goal="Review code quality for Task 1 implementation",
|
||
context="""
|
||
FILES TO REVIEW:
|
||
- src/models/user.py
|
||
- tests/models/test_user.py
|
||
|
||
CHECK:
|
||
- [ ] Follows project conventions and style?
|
||
- [ ] Proper error handling?
|
||
- [ ] Clear variable/function names?
|
||
- [ ] Adequate test coverage?
|
||
- [ ] No obvious bugs or missed edge cases?
|
||
- [ ] No security issues?
|
||
|
||
OUTPUT FORMAT:
|
||
- Critical Issues: [must fix before proceeding]
|
||
- Important Issues: [should fix]
|
||
- Minor Issues: [optional]
|
||
- Verdict: APPROVED or REQUEST_CHANGES
|
||
""",
|
||
toolsets=['file']
|
||
)
|
||
```
|
||
|
||
**If quality issues found:** Fix issues, re-review. Continue only when approved.
|
||
|
||
#### Step 4: Mark Complete
|
||
|
||
```python
|
||
todo([{"id": "task-1", "content": "Create User model with email field", "status": "completed"}], merge=True)
|
||
```
|
||
|
||
### 3. Final Review
|
||
|
||
After ALL tasks are complete, dispatch a final integration reviewer:
|
||
|
||
```python
|
||
delegate_task(
|
||
goal="Review the entire implementation for consistency and integration issues",
|
||
context="""
|
||
All tasks from the plan are complete. Review the full implementation:
|
||
- Do all components work together?
|
||
- Any inconsistencies between tasks?
|
||
- All tests passing?
|
||
- Ready for merge?
|
||
""",
|
||
toolsets=['terminal', 'file']
|
||
)
|
||
```
|
||
|
||
### 4. Verify and Commit
|
||
|
||
```bash
|
||
# Run full test suite
|
||
pytest tests/ -q
|
||
|
||
# Review all changes
|
||
git diff --stat
|
||
|
||
# Final commit if needed
|
||
git add -A && git commit -m "feat: complete [feature name] implementation"
|
||
```
|
||
|
||
## Task Granularity
|
||
|
||
**Each task = 2-5 minutes of focused work.**
|
||
|
||
**Too big:**
|
||
- "Implement user authentication system"
|
||
|
||
**Right size:**
|
||
- "Create User model with email and password fields"
|
||
- "Add password hashing function"
|
||
- "Create login endpoint"
|
||
- "Add JWT token generation"
|
||
- "Create registration endpoint"
|
||
|
||
## Red Flags — Never Do These
|
||
|
||
- Start implementation without a plan
|
||
- Skip reviews (spec compliance OR code quality)
|
||
- Proceed with unfixed critical/important issues
|
||
- Dispatch multiple implementation subagents for tasks that touch the same files
|
||
- Make subagent read the plan file (provide full text in context instead)
|
||
- Never skip scene-setting context (subagent needs to understand where the task fits)
|
||
- IGNORE subagent questions (answer before letting them proceed)
|
||
- Wait for ALL subagents in a parallel batch before testing/reviewing — React pages often share imports; a missing page import in App.tsx breaks the build
|
||
- After parallel fan-out completes: check for React context providers. Subagents may use hooks like `useToast()` that require a provider wrapper. If any page crashes (blank screen), check if `<ToastProvider>` wraps the routes. **Before dispatching**, scan the task specs for hooks that need providers (useToast, useAuth, useTheme) and include a reminder in each subagent's context to either use them safely or note the required wrapper
|
||
- After parallel fan-out where one subagent creates a library module (like `ai.ts`) and another consumes it (like `QuoteGenerator.tsx`), verify that function signatures match between the two. Subagents don't share context, so their exported/imported interfaces can drift. Check the actual call sites against the actual function signatures before building
|
||
- When the project uses `React.lazy()` for code splitting, import errors in lazy-loaded chunks surface as blank screens with empty console errors. Use eager imports first to isolate the failing module, then switch back to lazy once verified
|
||
- Accept "close enough" on spec compliance
|
||
- Skip review loops (reviewer found issues → implementer fixes → review again)
|
||
- Let implementer self-review replace actual review (both are needed)
|
||
- **Start code quality review before spec compliance is PASS** (wrong order)
|
||
- Move to next task while either review has open issues
|
||
- **Trust subagent generated UI buttons have wired handlers** — always verify interactive elements (buttons, links, forms) have onClick/onSubmit handlers after subagent work. Subagents frequently generate `<button>` elements with no action attached.
|
||
|
||
## Common Subagent Output Defects to Catch
|
||
|
||
Subagents produce code that compiles cleanly (TypeScript passes, bundler accepts it) but is functionally broken. After parallel fan-outs, scan for these common defects:
|
||
|
||
### Missing interactive handlers
|
||
Buttons, links, and form elements rendered in the DOM but with no `onClick`/`onSubmit` handler attached. The element appears on screen but clicking does nothing. **Check:** grep each new page file for `<button` and verify every interactive button has an `onClick` or `type="submit"`.
|
||
|
||
### Hardcoded mock/fallback responses
|
||
Subagents sometimes build "smart fallbacks" (simulated responses, canned data, mock delays) instead of calling the real API endpoint. **Check:** grep for keywords like `setTimeout`, `Math.random`, `fallback`, `simulate`, or hardcoded response objects. If the task spec says "call API X", the implementation must call API X — not simulate it.
|
||
|
||
### Function signature drift between modules
|
||
When subagent A creates a library and subagent B consumes it, the exported function signatures often don't match the call sites. `aiWriteExplanation(name, reason)` vs `aiWriteExplanation({serviceName, recommendation})`. **Check:** for each imported function in consumer files, verify the actual call argument shapes match the exported parameter types.
|
||
|
||
### Dependency stealth
|
||
Subagents add imports to `package.json` (`tesseract.js`, chart libraries, etc.) and use them in code without the package actually being installed. TypeScript may not catch this if the module isn't directly imported at compile time (e.g., dynamic `import()`). **Check:** compare new imports against `package.json` dependencies.
|
||
|
||
### React nested-component re‑mount (input focus loss)
|
||
Subagents define child components as nested functions inside parent components. When the parent re‑renders (e.g., due to a zustand store update from typing in an input), React destroys and recreates the nested component because its function identity changed — causing inputs to lose focus on every keystroke. **Symptom:** typing one character dismisses focus; the user must click the field again for each keypress. **Fix:** extract the nested component to a file‑level `const Component = memo(function Component({...}) {...})` with stable props. Pass callbacks as individual props rather than capturing parent closure variables.
|
||
|
||
**Variant: duplicate definitions (shadowing).** When a subagent adds a new feature to an existing file, it may create BOTH:
|
||
1. A **standalone** (prop-based) component **outside** the parent component function, AND
|
||
2. An **inline** (closure-based) component **inside** the parent component function
|
||
|
||
The inline definition **shadows** the proper standalone one because JavaScript scope resolution finds the inner binding first. The inner component is recreated every render (destroying focus), while the outer one is never used. **Diagnosis:** Search for `function ComponentName(` — if two definitions exist (one inside the parent component, one outside), delete the inline one. **Prevention:** when adding a feature to a file that already has standalone components, check whether the parent component ALSO contains an inline version that shadows the outer one.
|
||
|
||
### tsc clean ≠ build clean
|
||
TypeScript `--noEmit` passing does not guarantee the bundler (Vite/Rolldown, webpack) will succeed. Bundlers enforce module resolution, circular imports, and chunk splitting that tsc ignores. After type-checking, always run the actual build command.
|
||
|
||
### JSX fragment conversion during component extraction
|
||
When extracting JSX that uses fragment shorthand (`<>...</>`) into a named component and converting to `<Fragment key={...}>`, the brace/paren structure around the return expression often changes because the fragment shorthand doesn't carry a `key` prop but a moved `<Fragment>` needs one. **Common failure:** leaving the original closing pattern (`));` or `);`) unchanged when the Fragment's structural role changed.
|
||
|
||
**Root cause:** The original `<>...</>` sits directly inside `return ( ... )` and the closing `)` is obvious. After converting to `<Fragment key={expr}>`, the Fragment's open tag may introduce an extra nesting level or change how the return expression relates to the arrow function body. The old closing `);` may need to become just `);` (one paren fewer/more) depending on whether the fragment is the single child or wraps multiple elements.
|
||
|
||
**Prevention:** After extracting any JSX block that involved `<>...</>`, trace the return path: `return ( <Fragment> ... </Fragment> )` should close with `);` then `})}` for a block-arrow `.map()`. Count parens explicitly. The `;` ends the return statement, the `}` closes the arrow body, the `)` closes `.map()`, and the `}` closes the JSX expression.
|
||
|
||
## Handling Issues
|
||
|
||
### If Subagent Asks Questions
|
||
|
||
- Answer clearly and completely
|
||
- Provide additional context if needed
|
||
- Don't rush them into implementation
|
||
|
||
### If Reviewer Finds Issues
|
||
|
||
- Implementer subagent (or a new one) fixes them
|
||
- Reviewer reviews again
|
||
- Repeat until approved
|
||
- Don't skip the re-review
|
||
|
||
### If Subagent Fails a Task
|
||
|
||
- Dispatch a new fix subagent with specific instructions about what went wrong
|
||
- Don't try to fix manually in the controller session (context pollution)
|
||
|
||
## Efficiency Notes
|
||
|
||
**Why fresh subagent per task:**
|
||
- Prevents context pollution from accumulated state
|
||
- Each subagent gets clean, focused context
|
||
- No confusion from prior tasks' code or reasoning
|
||
|
||
**Why two-stage review:**
|
||
- Spec review catches under/over-building early
|
||
- Quality review ensures the implementation is well-built
|
||
- Catches issues before they compound across tasks
|
||
|
||
**Cost trade-off:**
|
||
- More subagent invocations (implementer + 2 reviewers per task)
|
||
- But catches issues early (cheaper than debugging compounded problems later)
|
||
|
||
## Integration with Other Skills
|
||
|
||
### With writing-plans
|
||
|
||
This skill EXECUTES plans created by the writing-plans skill:
|
||
1. User requirements → writing-plans → implementation plan
|
||
2. Implementation plan → subagent-driven-development → working code
|
||
|
||
### With test-driven-development
|
||
|
||
Implementer subagents should follow TDD:
|
||
1. Write failing test first
|
||
2. Implement minimal code
|
||
3. Verify test passes
|
||
4. Commit
|
||
|
||
Include TDD instructions in every implementer context.
|
||
|
||
### With requesting-code-review
|
||
|
||
The two-stage review process IS the code review. For final integration review, use the requesting-code-review skill's review dimensions.
|
||
|
||
### With systematic-debugging
|
||
|
||
If a subagent encounters bugs during implementation:
|
||
1. Follow systematic-debugging process
|
||
2. Find root cause before fixing
|
||
3. Write regression test
|
||
4. Resume implementation
|
||
|
||
## Example Workflow
|
||
|
||
```
|
||
[Read plan: docs/plans/auth-feature.md]
|
||
[Create todo list with 5 tasks]
|
||
|
||
--- Task 1: Create User model ---
|
||
[Dispatch implementer subagent]
|
||
Implementer: "Should email be unique?"
|
||
You: "Yes, email must be unique"
|
||
Implementer: Implemented, 3/3 tests passing, committed.
|
||
|
||
[Dispatch spec reviewer]
|
||
Spec reviewer: ✅ PASS — all requirements met
|
||
|
||
[Dispatch quality reviewer]
|
||
Quality reviewer: ✅ APPROVED — clean code, good tests
|
||
|
||
[Mark Task 1 complete]
|
||
|
||
--- Task 2: Password hashing ---
|
||
[Dispatch implementer subagent]
|
||
Implementer: No questions, implemented, 5/5 tests passing.
|
||
|
||
[Dispatch spec reviewer]
|
||
Spec reviewer: ❌ Missing: password strength validation (spec says "min 8 chars")
|
||
|
||
[Implementer fixes]
|
||
Implementer: Added validation, 7/7 tests passing.
|
||
|
||
[Dispatch spec reviewer again]
|
||
Spec reviewer: ✅ PASS
|
||
|
||
[Dispatch quality reviewer]
|
||
Quality reviewer: Important: Magic number 8, extract to constant
|
||
Implementer: Extracted MIN_PASSWORD_LENGTH constant
|
||
Quality reviewer: ✅ APPROVED
|
||
|
||
[Mark Task 2 complete]
|
||
|
||
... (continue for all tasks)
|
||
|
||
[After all tasks: dispatch final integration reviewer]
|
||
[Run full test suite: all passing]
|
||
[Done!]
|
||
```
|
||
|
||
## Remember
|
||
|
||
```
|
||
Fresh subagent per task
|
||
Two-stage review every time
|
||
Spec compliance FIRST
|
||
Code quality SECOND
|
||
Never skip reviews
|
||
Catch issues early
|
||
```
|
||
|
||
**Quality is not an accident. It's the result of systematic process.**
|
||
|
||
## Further reading (load when relevant)
|
||
|
||
When the orchestration involves significant context usage, long review loops, or complex validation checkpoints, load these references for the specific discipline:
|
||
|
||
- **`references/context-budget-discipline.md`** — Four-tier context degradation model (PEAK / GOOD / DEGRADING / POOR), read-depth rules that scale with context window size, and early warning signs of silent degradation. Load when a run will clearly consume significant context (multi-phase plans, many subagents, large artifacts).
|
||
- **`references/gates-taxonomy.md`** — The four canonical gate types (Pre-flight, Revision, Escalation, Abort) with behavior, recovery, and examples. Load when designing or reviewing any workflow that has validation checkpoints — use the vocabulary explicitly so each gate has defined entry, failure behavior, and resumption rules.
|
||
- **`references/pocketbase-proxy-pitfalls.md`** — PocketBase SDK path construction trap (double `/api`), Python http.server query string behavior, and admin auth endpoint differences across versions. Load when debugging PocketBase proxy 404 errors or setting up a local SPA dev server that proxies to PocketBase.
|
||
- **`references/spa-proxy-server.md`** — Template and pitfalls for a Python HTTP proxy server that serves a SPA's static dist/ while proxying API paths to a backend on a different port. Load when you need to serve a local build for browser testing and the SPA's relative API paths need to reach a backend like PocketBase.
|
||
- **`references/pocketbase-sequencing-pitfalls.md`** — PB migrations must be applied before frontend code that queries new collections can work. Load when dispatching subagents that write both PB migrations and frontend UI in the same batch — apply migrations first, then dispatch frontend subagents.
|
||
|
||
Both references adapted from gsd-build/get-shit-done (MIT © 2025 Lex Christopherson).
|