Hermes-agent
This commit is contained in:
+463
@@ -0,0 +1,463 @@
|
||||
---
|
||||
title: "Code Wiki — Generate wiki docs + Mermaid diagrams for any codebase"
|
||||
sidebar_label: "Code Wiki"
|
||||
description: "Generate wiki docs + Mermaid diagrams for any codebase"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Code Wiki
|
||||
|
||||
Generate wiki docs + Mermaid diagrams for any codebase.
|
||||
|
||||
## Skill metadata
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Optional — install with `hermes skills install official/software-development/code-wiki` |
|
||||
| Path | `optional-skills/software-development/code-wiki` |
|
||||
| Version | `0.1.0` |
|
||||
| Author | Teknium (teknium1), Hermes Agent |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `Documentation`, `Mermaid`, `Architecture`, `Diagrams`, `Wiki`, `Code-Analysis` |
|
||||
| Related skills | [`codebase-inspection`](/docs/user-guide/skills/bundled/github/github-codebase-inspection), [`github-repo-management`](/docs/user-guide/skills/bundled/github/github-github-repo-management) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
:::info
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# Code Wiki Skill
|
||||
|
||||
Generate a comprehensive wiki for any codebase — overview, architecture, per-module deep-dives, Mermaid class and sequence diagrams. Inspired by Google CodeWiki, but works on local repos, private repos, and any language. Uses only existing Hermes tools (`terminal`, `read_file`, `search_files`, `write_file`); no Docker, no external services, no extra dependencies.
|
||||
|
||||
This skill produces **reference documentation** (what/how). It does not produce strategic narrative (why — that's a different skill).
|
||||
|
||||
## When to Use
|
||||
|
||||
- User says "document this codebase", "generate a wiki", "make architecture diagrams"
|
||||
- Onboarding to an unfamiliar repo and wants a structured reference
|
||||
- User points at a GitHub URL and asks for documentation
|
||||
- Need a stable artifact (markdown + Mermaid) that renders on GitHub
|
||||
|
||||
Do NOT use this for:
|
||||
- Single-file or single-function documentation — just answer directly
|
||||
- API reference for one specific endpoint — use `read_file` and answer inline
|
||||
- Strategic "why does this exist" narrative — different skill, different purpose
|
||||
- Codebases the user is actively developing in this session — just answer questions as they come
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- No env vars required.
|
||||
- `git` on PATH for repo SHA tracking and remote clones.
|
||||
- Optional: `pygount` for language-breakdown stats (see the `codebase-inspection` skill).
|
||||
|
||||
## How to Run
|
||||
|
||||
Invoke through the `terminal` tool from the target repo's root, then use `read_file` / `search_files` / `write_file` to produce the wiki. Default output location is `~/.hermes/wikis/<repo-name>/`. Only write into the repo (`docs/wiki/`) when the user explicitly requests it.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Step | Action |
|
||||
|---|---|
|
||||
| 1 | Resolve target — local cwd, given path, or `git clone --depth 50 <url>` to a temp dir |
|
||||
| 2 | Scan structure — `ls`, `find -maxdepth 3`, manifest files, README |
|
||||
| 3 | Pick 8–10 modules to document |
|
||||
| 4 | Write `README.md` (overview + module map) |
|
||||
| 5 | Write `architecture.md` with Mermaid flowchart |
|
||||
| 6 | Write per-module docs in `modules/` |
|
||||
| 7 | Write `diagrams/class-diagram.md` (Mermaid classDiagram) |
|
||||
| 8 | Write `diagrams/sequences.md` (Mermaid sequenceDiagram, 2–4 workflows) |
|
||||
| 9 | Write `getting-started.md` |
|
||||
| 10 | Write `api.md` if applicable, else skip |
|
||||
| 11 | Write `.codewiki-state.json` |
|
||||
| 12 | Report paths to user |
|
||||
|
||||
## Procedure
|
||||
|
||||
### 1. Resolve the target
|
||||
|
||||
For a GitHub URL:
|
||||
|
||||
```bash
|
||||
WIKI_TMP=$(mktemp -d)
|
||||
git clone --depth 50 <url> "$WIKI_TMP/repo"
|
||||
cd "$WIKI_TMP/repo"
|
||||
REPO_SHA=$(git rev-parse HEAD)
|
||||
REPO_NAME=$(basename <url> .git)
|
||||
```
|
||||
|
||||
For a local path (or cwd if none given):
|
||||
|
||||
```bash
|
||||
cd <path>
|
||||
REPO_SHA=$(git rev-parse HEAD 2>/dev/null || echo "uncommitted")
|
||||
REPO_NAME=$(basename "$PWD")
|
||||
```
|
||||
|
||||
Then set the output dir:
|
||||
|
||||
```bash
|
||||
OUTPUT_DIR="$HOME/.hermes/wikis/$REPO_NAME"
|
||||
mkdir -p "$OUTPUT_DIR/modules" "$OUTPUT_DIR/diagrams"
|
||||
```
|
||||
|
||||
### 2. Scan repo structure
|
||||
|
||||
Use the `terminal` tool for the shell work, `read_file` for manifests:
|
||||
|
||||
```bash
|
||||
# Shallow tree first
|
||||
ls -la
|
||||
|
||||
# Deeper tree, noise filtered
|
||||
find . -type d \
|
||||
-not -path '*/\.*' \
|
||||
-not -path '*/node_modules*' \
|
||||
-not -path '*/venv*' \
|
||||
-not -path '*/__pycache__*' \
|
||||
-not -path '*/dist*' \
|
||||
-not -path '*/build*' \
|
||||
-not -path '*/target*' \
|
||||
-maxdepth 3 | sort
|
||||
|
||||
# Language breakdown (skip if pygount unavailable)
|
||||
pygount --format=summary \
|
||||
--folders-to-skip=".git,node_modules,venv,.venv,__pycache__,.cache,dist,build,target" \
|
||||
. 2>/dev/null || true
|
||||
```
|
||||
|
||||
Then `read_file` the relevant manifests (`package.json`, `pyproject.toml`, `setup.py`, `Cargo.toml`, `go.mod`, `pom.xml`, `build.gradle`) and the project README. Use `search_files target='files'` to find them rather than guessing names.
|
||||
|
||||
### 3. Pick modules to document
|
||||
|
||||
Cap initial pass at **8–10 modules**. Heuristics by language:
|
||||
|
||||
- Python: top-level packages (dirs with `__init__.py`), plus subsystem dirs
|
||||
- JS/TS: `src/<subdir>`, top-level workspace dirs
|
||||
- Rust: each crate in a workspace, or top-level `src/<module>` dirs
|
||||
- Go: each top-level package directory
|
||||
- Mixed/unfamiliar: top-level directories that contain source code (not config, not tests)
|
||||
|
||||
For very large repos, prioritize by:
|
||||
1. Imported-from count (a module imported by many is core)
|
||||
2. LOC (bigger modules usually warrant their own doc)
|
||||
3. Mentions in README / top-level docs
|
||||
|
||||
State the module list to the user before generating per-module docs on big repos — gives them a chance to redirect.
|
||||
|
||||
### 4. Write `README.md`
|
||||
|
||||
`read_file` the actual project README plus the top 2–3 entry-point files. Then `write_file`:
|
||||
|
||||
````markdown
|
||||
# <Project Name>
|
||||
|
||||
<One paragraph: what it is and what it's for. Self-contained — don't assume the
|
||||
reader has the source README.>
|
||||
|
||||
## Key Concepts
|
||||
|
||||
- **<Concept 1>** — <one line>
|
||||
- **<Concept 2>** — <one line>
|
||||
|
||||
## Entry Points
|
||||
|
||||
- [`path/to/main.py`](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/<link>) — <what runs when you start it>
|
||||
- [`path/to/cli.py`](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/<link>) — <CLI surface>
|
||||
|
||||
## High-Level Architecture
|
||||
|
||||
<2-3 sentences. Detail goes in architecture.md.>
|
||||
|
||||
See [architecture.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/architecture.md).
|
||||
|
||||
## Module Map
|
||||
|
||||
| Module | Purpose |
|
||||
|---|---|
|
||||
| [`<module>`](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/modules/<module>.md) | <one-line purpose> |
|
||||
|
||||
## Getting Started
|
||||
|
||||
See [getting-started.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/getting-started.md).
|
||||
````
|
||||
|
||||
For link targets in local mode use relative paths. For cloned repos use `https://github.com/<owner>/<repo>/blob/<sha>/<path>` so links survive future commits.
|
||||
|
||||
### 5. Write `architecture.md`
|
||||
|
||||
````markdown
|
||||
# Architecture
|
||||
|
||||
<2-3 paragraphs: shape of the system. What talks to what. Where data enters,
|
||||
where it exits, where state lives.>
|
||||
|
||||
## Components
|
||||
|
||||
- **<Component>** — <1-2 sentences>. See [`modules/<module>.md`](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/modules/<module>.md).
|
||||
|
||||
## System Diagram
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
User([User]) --> Entry[Entry Point]
|
||||
Entry --> Core[Core Engine]
|
||||
Core --> StorageA[(Database)]
|
||||
Core --> ExternalAPI{{External API}}
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
1. **<Step>** — [`<file>`](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/<link>)
|
||||
2. **<Step>** — [`<file>`](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/<link>)
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
- <Anything load-bearing the reader should know>
|
||||
````
|
||||
|
||||
**Mermaid shape semantics:**
|
||||
- `[]` = component
|
||||
- `[()]` = database / storage
|
||||
- `{{}}` = external service
|
||||
- `(())` = entry point or terminal
|
||||
- `-->` = sync call, `-.->` = async/event
|
||||
|
||||
Cap at ~20 nodes per diagram. Split into sub-diagrams if larger.
|
||||
|
||||
### 6. Write per-module docs in `modules/`
|
||||
|
||||
For each selected module, inspect its layout with `ls`, identify 3–5 most important files (by size, by being named `core.py` / `main.py` / `__init__.py`, by being imported a lot), then `read_file` those files (use `offset` / `limit` to read only what you need; prefer `search_files` for specific symbols).
|
||||
|
||||
````markdown
|
||||
# Module: `<module>`
|
||||
|
||||
<1-2 sentence purpose.>
|
||||
|
||||
## Responsibilities
|
||||
|
||||
- <bullet>
|
||||
- <bullet>
|
||||
|
||||
## Key Files
|
||||
|
||||
- [`<module>/<file>`](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/<link>) — <what it does>
|
||||
|
||||
## Public API
|
||||
|
||||
<Functions/classes/constants other code uses. Group related items. Show
|
||||
signatures, not full implementations.>
|
||||
|
||||
## Internal Structure
|
||||
|
||||
<How the module is organized internally. State management.>
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Used by:** <other modules>
|
||||
- **Uses:** <other modules + external libs>
|
||||
|
||||
## Notable Patterns / Gotchas
|
||||
|
||||
- <Anything non-obvious>
|
||||
````
|
||||
|
||||
### 7. Write `diagrams/class-diagram.md`
|
||||
|
||||
Pick the 5–10 most important classes/types. `read_file` them, then write:
|
||||
|
||||
````markdown
|
||||
# Class Diagram
|
||||
|
||||
## Core Types
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Agent {
|
||||
+string name
|
||||
+list~Tool~ tools
|
||||
+chat(message) string
|
||||
}
|
||||
class Tool {
|
||||
<<interface>>
|
||||
+name string
|
||||
+execute(args) any
|
||||
}
|
||||
Agent --> Tool : uses
|
||||
Tool <|-- TerminalTool
|
||||
Tool <|-- WebTool
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
<Anything the diagram can't express — lifecycle, threading, etc.>
|
||||
````
|
||||
|
||||
For languages without classes (Go, C, Rust): use the diagram for struct relationships, or skip class-diagram.md and explain it in prose in architecture.md. Don't force-fit.
|
||||
|
||||
### 8. Write `diagrams/sequences.md`
|
||||
|
||||
Pick 2–4 of the most important workflows. Trace each call path through the code (read entry point, follow function calls), then:
|
||||
|
||||
````markdown
|
||||
# Sequence Diagrams
|
||||
|
||||
## Workflow: <Name>
|
||||
|
||||
<1 sentence describing what this does and when it runs.>
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant CLI
|
||||
participant Agent
|
||||
participant LLM
|
||||
User->>CLI: types message
|
||||
CLI->>Agent: chat(message)
|
||||
Agent->>LLM: API call
|
||||
LLM-->>Agent: response + tool_calls
|
||||
Agent->>Agent: execute tools
|
||||
Agent-->>CLI: final response
|
||||
```
|
||||
|
||||
### Walkthrough
|
||||
|
||||
1. **User input** — [`cli.py:HermesCLI.run_session`](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/<link>)
|
||||
2. **Message dispatch** — [`run_agent.py:AIAgent.chat`](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/<link>)
|
||||
````
|
||||
|
||||
Don't invent participants. Every box must correspond to a real component the reader can find in the code.
|
||||
|
||||
### 9. Write `getting-started.md`
|
||||
|
||||
````markdown
|
||||
# Getting Started
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<From manifest files + README. Be specific — versions if pinned.>
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
<exact commands>
|
||||
```
|
||||
|
||||
## First Run
|
||||
|
||||
```bash
|
||||
<minimum command to see the system do something useful>
|
||||
```
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### <Workflow 1>
|
||||
<commands>
|
||||
|
||||
## Configuration
|
||||
|
||||
- `<config-file>` — <what it controls>
|
||||
- Env var `<VAR>` — <what it controls>
|
||||
|
||||
## Where to Go Next
|
||||
|
||||
- Architecture: [architecture.md](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/architecture.md)
|
||||
- Module reference: [README.md#module-map](https://github.com/NousResearch/hermes-agent/blob/main/optional-skills/software-development/code-wiki/README.md#module-map)
|
||||
````
|
||||
|
||||
### 10. Write `api.md` (skip if not applicable)
|
||||
|
||||
Only write this if the project is a library or API server. If it is:
|
||||
|
||||
- Find the public API surface (`__init__.py` exports, OpenAPI specs, route handlers, exported types)
|
||||
- Document each public entry with signature, parameters, return type, one-line description
|
||||
- Group by category
|
||||
|
||||
### 11. Write the state file
|
||||
|
||||
```bash
|
||||
cat > "$OUTPUT_DIR/.codewiki-state.json" <<EOF
|
||||
{
|
||||
"repo_name": "$REPO_NAME",
|
||||
"source_path": "$PWD",
|
||||
"source_sha": "$REPO_SHA",
|
||||
"generated_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
||||
"generator": "hermes-agent code-wiki skill v0.1.0",
|
||||
"modules_documented": []
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
### 12. Report to user
|
||||
|
||||
State exactly what was generated and where:
|
||||
|
||||
```
|
||||
Generated wiki at ~/.hermes/wikis/<repo-name>/:
|
||||
README.md project overview, module map
|
||||
architecture.md system architecture + flowchart
|
||||
getting-started.md setup, first run, workflows
|
||||
modules/<N files> per-module deep-dives
|
||||
diagrams/architecture.md Mermaid flowchart
|
||||
diagrams/class-diagram.md Mermaid class diagram
|
||||
diagrams/sequences.md Mermaid sequence diagrams
|
||||
```
|
||||
|
||||
If you cloned to a temp dir, remind the user it can be removed (`rm -rf "$WIKI_TMP"`) after they've reviewed the wiki.
|
||||
|
||||
## Scope Control
|
||||
|
||||
Generating a full wiki for a 500K-LOC monorepo is wildly token-expensive. Default to bounded scope:
|
||||
|
||||
- Initial scan: max depth 3 directories
|
||||
- Per-module docs: cap at 10 modules unless user expands scope
|
||||
- Per-file reads: prefer `search_files` for symbols + `read_file` with `offset`/`limit` over full reads
|
||||
- Skip vendored code (`vendor/`, `third_party/`, generated code, `_pb2.py`, `.min.js`)
|
||||
|
||||
If the user says "do the whole thing exhaustively", believe them — but ballpark the cost first: "this repo has ~340 source files, comprehensive coverage will be expensive — confirm?"
|
||||
|
||||
## Re-Run / Update
|
||||
|
||||
If `.codewiki-state.json` already exists at the target path:
|
||||
|
||||
- Read it for previous SHA and module list
|
||||
- If source SHA matches: ask user if they want to regenerate or skip
|
||||
- If SHA differs: offer to regenerate only modules with changed files (`git diff --name-only <old-sha> HEAD`)
|
||||
|
||||
Full incremental-regeneration is a future enhancement — for now, regenerating the whole thing is acceptable.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- **Fabricating components.** Every diagram node and claimed function call must be in the source. `read_file` before writing. The single biggest failure mode for auto-generated docs is plausible-sounding fabrication.
|
||||
- **Generic AI prose.** "This module is responsible for..." is content-free. Say what the module actually does in domain-specific terms.
|
||||
- **Restating code as prose.** A module doc that says "the `process` function processes things by calling `process_item` on each item" is worse than just linking to the function.
|
||||
- **Mermaid > 50 nodes.** They don't render legibly. Split them.
|
||||
- **Documenting tests, generated code, or vendored deps as if they were product code.** Skip them.
|
||||
- **In-repo output without asking.** Default is `~/.hermes/wikis/`. Only write into the repo when the user explicitly requests it.
|
||||
- **Mermaid special chars need quotes:** `A["Tool / Agent"]` not `A[Tool / Agent]`. `<br>` for line breaks inside a node.
|
||||
- **Nested code fences in SKILL.md.** When writing a markdown example that contains a Mermaid block, use 4-backtick outer fences so the 3-backtick inner ` ```mermaid ` doesn't close the outer. (This SKILL.md does it.)
|
||||
- **classDiagram generics** render as `~T~` (e.g. `List~Tool~`), not `<T>`.
|
||||
- **GitHub Mermaid theme is fixed** — don't include `%%{init: ...}%%` blocks; they're stripped on render.
|
||||
|
||||
## Verification
|
||||
|
||||
After writing, verify:
|
||||
|
||||
1. **Mermaid blocks balance** — opens equal closes per file:
|
||||
```bash
|
||||
for f in "$OUTPUT_DIR"/diagrams/*.md "$OUTPUT_DIR"/architecture.md; do
|
||||
opens=$(grep -c '^```mermaid' "$f")
|
||||
total=$(grep -c '^```' "$f")
|
||||
echo "$f: $opens mermaid blocks, $total total fences (expect total = opens*2)"
|
||||
done
|
||||
```
|
||||
2. **All expected files exist** —
|
||||
```bash
|
||||
ls "$OUTPUT_DIR"/{README.md,architecture.md,getting-started.md,.codewiki-state.json} \
|
||||
"$OUTPUT_DIR"/modules/ "$OUTPUT_DIR"/diagrams/
|
||||
```
|
||||
3. **Module count matches what you intended** — `ls "$OUTPUT_DIR/modules" | wc -l` should equal the number of modules you committed to in Step 3.
|
||||
4. **No fabricated paths** — sanity-check 2–3 source links resolve to real files.
|
||||
+531
@@ -0,0 +1,531 @@
|
||||
---
|
||||
title: "Rest Graphql Debug — Debug REST/GraphQL APIs: status codes, auth, schemas, repro"
|
||||
sidebar_label: "Rest Graphql Debug"
|
||||
description: "Debug REST/GraphQL APIs: status codes, auth, schemas, repro"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Rest Graphql Debug
|
||||
|
||||
Debug REST/GraphQL APIs: status codes, auth, schemas, repro.
|
||||
|
||||
## Skill metadata
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Optional — install with `hermes skills install official/software-development/rest-graphql-debug` |
|
||||
| Path | `optional-skills/software-development/rest-graphql-debug` |
|
||||
| Version | `1.2.0` |
|
||||
| Author | eren-karakus0 |
|
||||
| License | MIT |
|
||||
| Tags | `api`, `rest`, `graphql`, `http`, `debugging`, `testing`, `curl`, `integration` |
|
||||
| Related skills | [`systematic-debugging`](/docs/user-guide/skills/bundled/software-development/software-development-systematic-debugging), [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
:::info
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# API Testing & Debugging
|
||||
|
||||
Drive REST and GraphQL diagnosis through Hermes tools — `terminal` for `curl`, `execute_code` for Python `requests`, `web_extract` for vendor docs. Isolate the failing layer before guessing at the fix.
|
||||
|
||||
## When to Use
|
||||
|
||||
- API returns unexpected status or body
|
||||
- Auth fails (401/403 after token refresh, OAuth, API key)
|
||||
- Works in Postman but fails in code
|
||||
- Webhook / callback integration debugging
|
||||
- Building or reviewing API integration tests
|
||||
- Rate limiting or pagination issues
|
||||
|
||||
Skip for UI rendering, DB query tuning, or DNS/firewall infra (escalate).
|
||||
|
||||
## Core Principle
|
||||
|
||||
**Isolate the layer, then fix.** A 200 OK can hide broken data. A 500 can mask a one-character auth typo. Walk the chain in order; never skip a step.
|
||||
|
||||
```
|
||||
1. Connectivity → can we reach the host at all?
|
||||
1.5 Timeouts → connect-slow vs read-slow?
|
||||
2. TLS/SSL → cert valid and trusted?
|
||||
3. Auth → credentials correct and unexpired?
|
||||
4. Request format → payload shape match server expectations?
|
||||
5. Response parse → does our code accept what came back?
|
||||
6. Semantics → does the data mean what we assume?
|
||||
```
|
||||
|
||||
## 5-Minute Quickstart
|
||||
|
||||
### REST via terminal
|
||||
|
||||
```python
|
||||
# Verbose request/response exchange
|
||||
terminal('curl -v https://api.example.com/users/1')
|
||||
|
||||
# POST with JSON
|
||||
terminal("""curl -X POST https://api.example.com/users \\
|
||||
-H 'Content-Type: application/json' \\
|
||||
-H "Authorization: Bearer $TOKEN" \\
|
||||
-d '{"name":"test","email":"test@example.com"}'""")
|
||||
|
||||
# Headers only
|
||||
terminal('curl -sI https://api.example.com/health')
|
||||
|
||||
# Pretty-print JSON
|
||||
terminal('curl -s https://api.example.com/users | python3 -m json.tool')
|
||||
```
|
||||
|
||||
### GraphQL via terminal
|
||||
|
||||
```python
|
||||
terminal("""curl -X POST https://api.example.com/graphql \\
|
||||
-H 'Content-Type: application/json' \\
|
||||
-H "Authorization: Bearer $TOKEN" \\
|
||||
-d '{"query":"{ user(id: 1) { name email } }"}'""")
|
||||
```
|
||||
|
||||
**GraphQL gotcha:** servers often return HTTP 200 even when the query failed. Always inspect the `errors` field regardless of status code:
|
||||
|
||||
```python
|
||||
execute_code('''
|
||||
import os, requests
|
||||
resp = requests.post(
|
||||
"https://api.example.com/graphql",
|
||||
json={"query": "{ user(id: 1) { name email } }"},
|
||||
headers={"Authorization": f"Bearer {os.environ['TOKEN']}"},
|
||||
timeout=10,
|
||||
)
|
||||
data = resp.json()
|
||||
if data.get("errors"):
|
||||
for err in data["errors"]:
|
||||
print(f"GraphQL error: {err['message']} (path: {err.get('path')})")
|
||||
print(data.get("data"))
|
||||
''')
|
||||
```
|
||||
|
||||
### Python (requests) via execute_code
|
||||
|
||||
```python
|
||||
execute_code('''
|
||||
import requests
|
||||
resp = requests.get(
|
||||
"https://api.example.com/users/1",
|
||||
headers={"Authorization": "Bearer <TOKEN>"},
|
||||
timeout=(3.05, 30), # (connect, read)
|
||||
)
|
||||
print(resp.status_code, dict(resp.headers))
|
||||
print(resp.text[:500])
|
||||
''')
|
||||
```
|
||||
|
||||
## Layered Debug Flow
|
||||
|
||||
### Step 1 — Connectivity
|
||||
|
||||
```python
|
||||
terminal('nslookup api.example.com')
|
||||
terminal('curl -v --connect-timeout 5 https://api.example.com/health')
|
||||
```
|
||||
|
||||
Failures: DNS not resolving, firewall, VPN required, proxy missing.
|
||||
|
||||
### Step 1.5 — Timeouts
|
||||
|
||||
Distinguish *can't reach* from *reaches but slow*:
|
||||
|
||||
```python
|
||||
terminal('''curl -w "dns:%{time_namelookup}s connect:%{time_connect}s tls:%{time_appconnect}s ttfb:%{time_starttransfer}s total:%{time_total}s\\n" \\
|
||||
-o /dev/null -s https://api.example.com/endpoint''')
|
||||
```
|
||||
|
||||
In Python, always pass a tuple timeout — `requests` has no default and will hang forever:
|
||||
|
||||
```python
|
||||
execute_code('''
|
||||
import requests
|
||||
from requests.exceptions import ConnectTimeout, ReadTimeout
|
||||
try:
|
||||
requests.get(url, timeout=(3.05, 30))
|
||||
except ConnectTimeout:
|
||||
print("Cannot reach host — DNS, firewall, VPN")
|
||||
except ReadTimeout:
|
||||
print("Connected but server is slow")
|
||||
''')
|
||||
```
|
||||
|
||||
Diagnosis: high `time_connect` is network/firewall; high `time_starttransfer` with low `time_connect` is a slow server.
|
||||
|
||||
### Step 2 — TLS/SSL
|
||||
|
||||
```python
|
||||
terminal('curl -vI https://api.example.com 2>&1 | grep -E "SSL|subject|expire|issuer"')
|
||||
```
|
||||
|
||||
Failures: expired cert, self-signed, hostname mismatch, missing CA bundle. Use `-k` only for ad-hoc debug, never in code.
|
||||
|
||||
### Step 3 — Authentication
|
||||
|
||||
```python
|
||||
# Token validity check
|
||||
terminal('curl -s -o /dev/null -w "%{http_code}\\n" -H "Authorization: Bearer $TOKEN" https://api.example.com/me')
|
||||
|
||||
# Decode JWT exp claim — handles base64url padding correctly
|
||||
execute_code('''
|
||||
import json, base64, os
|
||||
tok = os.environ["TOKEN"]
|
||||
payload = tok.split(".")[1]
|
||||
payload += "=" * (-len(payload) % 4)
|
||||
print(json.dumps(json.loads(base64.urlsafe_b64decode(payload)), indent=2))
|
||||
''')
|
||||
```
|
||||
|
||||
Checklist:
|
||||
- Token expired? (`exp` claim in JWT)
|
||||
- Right scheme? Bearer vs Basic vs Token vs `X-Api-Key`
|
||||
- Right environment? Staging key on prod is a classic
|
||||
- API key in header vs query param (`?api_key=…`)?
|
||||
|
||||
### Step 4 — Request Format
|
||||
|
||||
```python
|
||||
terminal("""curl -v -X POST https://api.example.com/endpoint \\
|
||||
-H 'Content-Type: application/json' \\
|
||||
-d '{"key":"value"}' 2>&1""")
|
||||
```
|
||||
|
||||
**Content-Type / body mismatch — the silent 415/400:**
|
||||
|
||||
```python
|
||||
# WRONG — data= sends form-encoded, header lies
|
||||
requests.post(url, data='{"k":"v"}', headers={"Content-Type": "application/json"})
|
||||
|
||||
# RIGHT — json= auto-sets header AND serializes
|
||||
requests.post(url, json={"k": "v"})
|
||||
|
||||
# WRONG — Accept says XML, code calls .json()
|
||||
requests.get(url, headers={"Accept": "text/xml"})
|
||||
|
||||
# RIGHT — let requests build multipart with boundary
|
||||
requests.post(url, files={"file": open("doc.pdf", "rb")})
|
||||
```
|
||||
|
||||
Common: form-encoded vs JSON, missing required fields, wrong HTTP method, unencoded query params.
|
||||
|
||||
### Step 5 — Response Parsing
|
||||
|
||||
Always inspect content-type before calling `.json()`:
|
||||
|
||||
```python
|
||||
execute_code('''
|
||||
import requests
|
||||
resp = requests.post(url, json=payload, timeout=10)
|
||||
print(f"status={resp.status_code}")
|
||||
print(f"headers={dict(resp.headers)}")
|
||||
ct = resp.headers.get("Content-Type", "")
|
||||
if "application/json" in ct:
|
||||
print(resp.json())
|
||||
else:
|
||||
print(f"unexpected content-type {ct!r}, body={resp.text[:500]!r}")
|
||||
''')
|
||||
```
|
||||
|
||||
Failures: HTML error page where JSON expected, empty body, wrong charset.
|
||||
|
||||
### Step 6 — Semantic Validation
|
||||
|
||||
Parsed cleanly — but is the data *correct*?
|
||||
|
||||
- Does `"status": "active"` mean what your code thinks?
|
||||
- ID in response matches the one requested?
|
||||
- Timestamps in expected timezone?
|
||||
- Pagination returning all results, or just page 1?
|
||||
|
||||
## HTTP Status Playbook
|
||||
|
||||
### 401 Unauthorized — credentials missing or invalid
|
||||
|
||||
1. `Authorization` header actually present? (`curl -v` to confirm)
|
||||
2. Token correct and unexpired?
|
||||
3. Right auth scheme? (`Bearer` vs `Basic` vs `Token`)
|
||||
4. Some APIs use query param (`?api_key=…`) instead of header.
|
||||
|
||||
### 403 Forbidden — authenticated but not authorized
|
||||
|
||||
1. Token has the required scopes/permissions?
|
||||
2. Resource owned by a different account?
|
||||
3. IP allowlist blocking you?
|
||||
4. CORS in browser? (check `Access-Control-Allow-Origin`)
|
||||
|
||||
### 404 Not Found — resource doesn't exist or URL is wrong
|
||||
|
||||
1. Path correct? (trailing slash, typo, version prefix)
|
||||
2. Resource ID exists?
|
||||
3. Right API version (`/v1/` vs `/v2/`)?
|
||||
4. Right base URL (staging vs prod)?
|
||||
|
||||
### 409 Conflict — state collision
|
||||
|
||||
1. Resource already exists (duplicate create)?
|
||||
2. Stale `ETag` / `If-Match`?
|
||||
3. Concurrent modification by another process?
|
||||
|
||||
### 422 Unprocessable Entity — valid JSON, invalid data
|
||||
|
||||
The error body usually names the bad fields. Check:
|
||||
- Field types (string vs int, date format)
|
||||
- Required vs optional
|
||||
- Enum values inside the allowed set
|
||||
|
||||
### 429 Too Many Requests — rate limited
|
||||
|
||||
Check `Retry-After` and `X-RateLimit-*` headers. Exponential backoff:
|
||||
|
||||
```python
|
||||
execute_code('''
|
||||
import time, requests
|
||||
|
||||
def with_backoff(method, url, **kwargs):
|
||||
for attempt in range(5):
|
||||
resp = requests.request(method, url, **kwargs)
|
||||
if resp.status_code != 429:
|
||||
return resp
|
||||
wait = int(resp.headers.get("Retry-After", 2 ** attempt))
|
||||
time.sleep(wait)
|
||||
return resp
|
||||
''')
|
||||
```
|
||||
|
||||
### 5xx — server-side, usually not your fault
|
||||
|
||||
- **500** — server bug. Capture correlation ID, file with provider.
|
||||
- **502** — upstream down. Backoff + retry.
|
||||
- **503** — overloaded / maintenance. Check status page.
|
||||
- **504** — upstream timeout. Reduce payload or raise timeout.
|
||||
|
||||
For all 5xx: backoff with jitter, alert on persistence.
|
||||
|
||||
## Pagination & Idempotency
|
||||
|
||||
**Pagination.** Verify you're getting *all* results. Look for `next_cursor`, `next_page`, `total_count`. Two patterns:
|
||||
- Offset (`?limit=100&offset=200`) — simple, can skip items if data shifts.
|
||||
- Cursor (`?cursor=abc123`) — preferred for live or large datasets.
|
||||
|
||||
**Idempotency.** For non-idempotent operations (POST), send `Idempotency-Key: <uuid>` so retries don't double-charge / double-create. Mandatory for payments and orders.
|
||||
|
||||
## Contract Validation
|
||||
|
||||
Catch schema drift before it hits production:
|
||||
|
||||
```python
|
||||
execute_code('''
|
||||
import requests
|
||||
|
||||
def validate_user(data: dict) -> list[str]:
|
||||
errors = []
|
||||
required = {"id": int, "email": str, "created_at": str}
|
||||
for field, expected in required.items():
|
||||
if field not in data:
|
||||
errors.append(f"missing field: {field}")
|
||||
elif not isinstance(data[field], expected):
|
||||
errors.append(f"{field}: want {expected.__name__}, got {type(data[field]).__name__}")
|
||||
return errors
|
||||
|
||||
resp = requests.get(f"{BASE}/users/1", headers=HEADERS, timeout=10)
|
||||
issues = validate_user(resp.json())
|
||||
if issues:
|
||||
print(f"contract violations: {issues}")
|
||||
''')
|
||||
```
|
||||
|
||||
Run after API upgrades, when integrating new third parties, or in CI smoke tests.
|
||||
|
||||
## Correlation IDs
|
||||
|
||||
Always capture the provider's request ID — fastest path to vendor support:
|
||||
|
||||
```python
|
||||
execute_code('''
|
||||
import requests
|
||||
resp = requests.post(url, json=payload, headers=headers, timeout=10)
|
||||
request_id = (
|
||||
resp.headers.get("X-Request-Id")
|
||||
or resp.headers.get("X-Trace-Id")
|
||||
or resp.headers.get("CF-Ray") # Cloudflare
|
||||
)
|
||||
if resp.status_code >= 400:
|
||||
print(f"failed status={resp.status_code} req_id={request_id} ts={resp.headers.get('Date')}")
|
||||
''')
|
||||
```
|
||||
|
||||
**Vendor bug-report template:**
|
||||
|
||||
```
|
||||
Endpoint: POST /api/v1/orders
|
||||
Request ID: req_abc123xyz
|
||||
Timestamp: 2026-03-17T14:30:00Z
|
||||
Status: 500
|
||||
Expected: 201 with order object
|
||||
Actual: 500 {"error":"internal server error"}
|
||||
Repro: curl -X POST … (auth: <REDACTED>)
|
||||
```
|
||||
|
||||
## Regression Test Template
|
||||
|
||||
Drop this into `tests/` and run via `terminal('pytest tests/test_api_smoke.py -v')`:
|
||||
|
||||
```python
|
||||
import os, requests, pytest
|
||||
|
||||
BASE_URL = os.environ.get("API_BASE_URL", "https://api.example.com")
|
||||
TOKEN = os.environ.get("API_TOKEN", "")
|
||||
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
|
||||
|
||||
class TestAPISmoke:
|
||||
def test_health(self):
|
||||
resp = requests.get(f"{BASE_URL}/health", timeout=5)
|
||||
assert resp.status_code == 200
|
||||
|
||||
def test_list_users_returns_array(self):
|
||||
resp = requests.get(f"{BASE_URL}/users", headers=HEADERS, timeout=10)
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert isinstance(data.get("data", data), list)
|
||||
|
||||
def test_get_user_required_fields(self):
|
||||
resp = requests.get(f"{BASE_URL}/users/1", headers=HEADERS, timeout=10)
|
||||
assert resp.status_code in (200, 404)
|
||||
if resp.status_code == 200:
|
||||
user = resp.json()
|
||||
assert "id" in user and "email" in user
|
||||
|
||||
def test_invalid_auth_returns_401(self):
|
||||
resp = requests.get(
|
||||
f"{BASE_URL}/users",
|
||||
headers={"Authorization": "Bearer invalid-token"},
|
||||
timeout=10,
|
||||
)
|
||||
assert resp.status_code == 401
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
### Token handling
|
||||
- Never log full tokens. Redact: `Bearer <REDACTED>`.
|
||||
- Never hardcode tokens in scripts. Read from env (`os.environ["API_TOKEN"]`) or `~/.hermes/.env`.
|
||||
- Rotate immediately if a token surfaces in logs, error messages, or git history.
|
||||
|
||||
### Safe logging
|
||||
|
||||
```python
|
||||
def redact_auth(headers: dict) -> dict:
|
||||
sensitive = {"authorization", "x-api-key", "cookie", "set-cookie"}
|
||||
return {k: ("<REDACTED>" if k.lower() in sensitive else v) for k, v in headers.items()}
|
||||
```
|
||||
|
||||
### Leak checklist
|
||||
|
||||
- [ ] **Credentials in URLs.** API keys in query strings end up in server logs, browser history, referrer headers — use headers.
|
||||
- [ ] **PII in error responses.** `404 on /users/123` shouldn't reveal whether the user exists (enumeration).
|
||||
- [ ] **Stack traces in prod.** 500s shouldn't leak file paths, framework versions.
|
||||
- [ ] **Internal hostnames/IPs.** `10.x.x.x`, `internal-api.corp.local` in error bodies.
|
||||
- [ ] **Tokens echoed back.** Some APIs include the auth token in error details. Verify they don't.
|
||||
- [ ] **Verbose `Server` / `X-Powered-By`.** Stack-info leaks. Note for security review.
|
||||
|
||||
## Hermes Tool Patterns
|
||||
|
||||
### terminal — for curl, dig, openssl
|
||||
|
||||
```python
|
||||
terminal('curl -sI https://api.example.com')
|
||||
terminal('openssl s_client -connect api.example.com:443 -servername api.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates')
|
||||
```
|
||||
|
||||
### execute_code — for multi-step Python flows
|
||||
|
||||
When debugging spans auth → fetch → paginate → validate, use `execute_code`. Variables persist for the script, results print to stdout, no risk of token spam in your context:
|
||||
|
||||
```python
|
||||
execute_code('''
|
||||
import os, requests
|
||||
|
||||
token = os.environ["API_TOKEN"]
|
||||
base = "https://api.example.com"
|
||||
H = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
# 1. auth
|
||||
me = requests.get(f"{base}/me", headers=H, timeout=10)
|
||||
print(f"auth {me.status_code}")
|
||||
|
||||
# 2. paginate
|
||||
all_users, cursor = [], None
|
||||
while True:
|
||||
params = {"cursor": cursor} if cursor else {}
|
||||
r = requests.get(f"{base}/users", headers=H, params=params, timeout=10)
|
||||
body = r.json()
|
||||
all_users.extend(body["data"])
|
||||
cursor = body.get("next_cursor")
|
||||
if not cursor:
|
||||
break
|
||||
print(f"users={len(all_users)}")
|
||||
''')
|
||||
```
|
||||
|
||||
### web_extract — for vendor API docs
|
||||
|
||||
Pull the spec for the endpoint you're debugging instead of guessing:
|
||||
|
||||
```python
|
||||
web_extract(urls=["https://docs.example.com/api/v1/users"])
|
||||
```
|
||||
|
||||
### delegate_task — for full CRUD test sweeps
|
||||
|
||||
```python
|
||||
delegate_task(
|
||||
goal="Test all CRUD endpoints for /api/v1/users",
|
||||
context="""
|
||||
Follow the rest-graphql-debug skill (optional-skills/software-development/rest-graphql-debug).
|
||||
Base URL: https://api.example.com
|
||||
Auth: Bearer token from API_TOKEN env var.
|
||||
|
||||
For each verb (POST, GET, PATCH, DELETE):
|
||||
- happy path: assert status + response schema
|
||||
- error cases: 400, 404, 422
|
||||
- log a repro curl for any failure (redact tokens)
|
||||
|
||||
Output: pass/fail per endpoint + correlation IDs for failures.
|
||||
""",
|
||||
toolsets=["terminal", "file"],
|
||||
)
|
||||
```
|
||||
|
||||
## Output Format
|
||||
|
||||
When reporting findings:
|
||||
|
||||
```
|
||||
## Finding
|
||||
Endpoint: POST /api/v1/users
|
||||
Status: 422 Unprocessable Entity
|
||||
Req ID: req_abc123xyz
|
||||
|
||||
## Repro
|
||||
curl -X POST https://api.example.com/api/v1/users \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer <REDACTED>' \
|
||||
-d '{"name":"test"}'
|
||||
|
||||
## Root Cause
|
||||
Missing required field `email`. Server validation rejects before processing.
|
||||
|
||||
## Fix
|
||||
-d '{"name":"test","email":"test@example.com"}'
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- `systematic-debugging` — once the failing API layer is isolated, root-cause your code
|
||||
- `test-driven-development` — write the regression test before shipping the fix
|
||||
+370
@@ -0,0 +1,370 @@
|
||||
---
|
||||
title: "Subagent Driven Development — Execute plans via delegate_task subagents (2-stage review)"
|
||||
sidebar_label: "Subagent Driven Development"
|
||||
description: "Execute plans via delegate_task subagents (2-stage review)"
|
||||
---
|
||||
|
||||
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
|
||||
|
||||
# Subagent Driven Development
|
||||
|
||||
Execute plans via delegate_task subagents (2-stage review).
|
||||
|
||||
## Skill metadata
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Source | Optional — install with `hermes skills install official/software-development/subagent-driven-development` |
|
||||
| Path | `optional-skills/software-development/subagent-driven-development` |
|
||||
| Version | `1.1.0` |
|
||||
| Author | Hermes Agent (adapted from obra/superpowers) |
|
||||
| License | MIT |
|
||||
| Platforms | linux, macos, windows |
|
||||
| Tags | `delegation`, `subagent`, `implementation`, `workflow`, `parallel` |
|
||||
| Related skills | [`plan`](/docs/user-guide/skills/bundled/software-development/software-development-plan), [`requesting-code-review`](/docs/user-guide/skills/bundled/software-development/software-development-requesting-code-review), [`test-driven-development`](/docs/user-guide/skills/bundled/software-development/software-development-test-driven-development) |
|
||||
|
||||
## Reference: full SKILL.md
|
||||
|
||||
:::info
|
||||
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
|
||||
:::
|
||||
|
||||
# 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 the `plan` skill or user requirements)
|
||||
- Tasks are mostly independent
|
||||
- Quality and spec compliance are important
|
||||
- You want automated review between tasks
|
||||
|
||||
**vs. manual execution:**
|
||||
- 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)
|
||||
- Skip scene-setting context (subagent needs to understand where the task fits)
|
||||
- Ignore subagent questions (answer before letting them proceed)
|
||||
- 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
|
||||
|
||||
## 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 plan
|
||||
|
||||
This skill EXECUTES plans created by the `plan` skill:
|
||||
1. User requirements → plan → 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.
|
||||
|
||||
Both references adapted from gsd-build/get-shit-done (MIT © 2025 Lex Christopherson).
|
||||
Reference in New Issue
Block a user