19 KiB
name, description, version, author, license, platforms, metadata
| name | description | version | author | license | platforms | metadata | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| subagent-driven-development | Execute plans via delegate_task subagents (2-stage review). | 1.1.0 | Hermes Agent (adapted from obra/superpowers) | MIT |
|
|
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:
# 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:
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:
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:
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
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:
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
# 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 (likeQuoteGenerator.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:
- A standalone (prop-based) component outside the parent component function, AND
- 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:
- User requirements → writing-plans → implementation plan
- Implementation plan → subagent-driven-development → working code
With test-driven-development
Implementer subagents should follow TDD:
- Write failing test first
- Implement minimal code
- Verify test passes
- 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:
- Follow systematic-debugging process
- Find root cause before fixing
- Write regression test
- 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).