Import 8 skills from mattpocock/skills, adapt for Fénix workflow
Imported skills: - edit-article: article restructuring & prose editing - git-guardrails: dangerous git command blocking (adapted: documents both settings.json deny/ask rules and PreToolUse hook approach) - grill-me: stress-test plans via relentless interview - improve-codebase-architecture: deep module refactors (adapted: Gitea/Org output) - request-refactor-plan: tiny-commit refactor RFCs (adapted: Gitea/Org output) - tdd: red-green-refactor vertical slices (with reference docs) - triage-issue: bug investigation + TDD fix plan (adapted: Gitea/BUGS.org support) - write-a-skill: scaffold new Claude Code skills Adaptations from originals: - GitHub-only → GitHub/Gitea/Org-file output options - git-guardrails rewritten to align with existing settings.json deny rules Also: updated README.md (21 skills, 3 categories, attribution), added META-TASKS.org for import tracking. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0d99968038
commit
2a8a0ef1f5
|
|
@ -0,0 +1,41 @@
|
||||||
|
#+TITLE: fenix-skills — Import & Refactor Tasks
|
||||||
|
#+DATE: 2026-03-19
|
||||||
|
|
||||||
|
* DONE Import skills from mattpocock/skills
|
||||||
|
CLOSED: [2026-03-19]
|
||||||
|
Source: =~/Emacs/skills__mattpocock/=
|
||||||
|
|
||||||
|
** DONE Import edit-article
|
||||||
|
- Copied to =skills/edit-article/=
|
||||||
|
- Direct import, no adaptation needed
|
||||||
|
|
||||||
|
** DONE Import git-guardrails-claude-code → adapted for Fénix setup
|
||||||
|
- Copied to =skills/git-guardrails/= (renamed from git-guardrails-claude-code)
|
||||||
|
- Adapted: documents both settings.json deny/ask rules AND PreToolUse hook approach
|
||||||
|
- Aligned with existing ~/.claude/settings.json deny rules
|
||||||
|
- Includes recommended additions to ask rules
|
||||||
|
|
||||||
|
** DONE Import tdd
|
||||||
|
- Copied to =skills/tdd/= with all reference docs (tests.md, mocking.md, etc.)
|
||||||
|
- Language-agnostic, works with Python/PHP/JS
|
||||||
|
|
||||||
|
** DONE Import triage-issue → adapted for Gitea/BUGS.org
|
||||||
|
- Adapted: supports GitHub (gh), Gitea (tea), and BUGS.org output
|
||||||
|
- Defaults to BUGS.org if project has one
|
||||||
|
|
||||||
|
** DONE Import improve-codebase-architecture → adapted for Gitea/Org
|
||||||
|
- Adapted: supports GitHub, Gitea, and Org-file output
|
||||||
|
|
||||||
|
** DONE Import request-refactor-plan → adapted for Gitea/Org
|
||||||
|
- Adapted: supports GitHub, Gitea, and Org-file output
|
||||||
|
|
||||||
|
** DONE Evaluate additional skills
|
||||||
|
- IMPORTED: triage-issue, improve-codebase-architecture, request-refactor-plan
|
||||||
|
- SKIPPED: setup-pre-commit (npm-centric), prd-to-issues (GitHub-centric)
|
||||||
|
- SKIPPED: scaffold-exercises (coupled to ai-hero-cli), prd-to-plan (low priority)
|
||||||
|
|
||||||
|
* DONE Refactor README.md
|
||||||
|
CLOSED: [2026-03-19]
|
||||||
|
- Updated skills inventory with all 21 skills
|
||||||
|
- Organized into 3 categories: Emacs, Development Workflow, Content & Productivity
|
||||||
|
- Documented attribution and adaptations from mattpocock originals
|
||||||
58
README.md
58
README.md
|
|
@ -1,7 +1,7 @@
|
||||||
# Fenix Skills — Claude Code Plugin
|
# Fenix Skills — Claude Code Plugin
|
||||||
|
|
||||||
Custom Claude Code skills for Fénix's workflow.
|
Custom Claude Code skills for Fénix's workflow.
|
||||||
Includes all [xenodium/emacs-skills](https://github.com/xenodium/emacs-skills) (forked & rebranded) plus Fénix's own productivity tools.
|
Includes [xenodium/emacs-skills](https://github.com/xenodium/emacs-skills) (forked & rebranded), selected [mattpocock/skills](https://github.com/mattpocock/skills) (adapted), plus Fénix's own tools.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -11,25 +11,35 @@ Includes all [xenodium/emacs-skills](https://github.com/xenodium/emacs-skills) (
|
||||||
~/Emacs/fenix-skills/
|
~/Emacs/fenix-skills/
|
||||||
├── .claude-plugin/
|
├── .claude-plugin/
|
||||||
│ └── marketplace.json # Plugin manifest
|
│ └── marketplace.json # Plugin manifest
|
||||||
|
├── META-TASKS.org # Import/refactor task tracking
|
||||||
├── README.md
|
├── README.md
|
||||||
└── skills/
|
└── skills/
|
||||||
├── d2/ # /d2 — Create D2 diagrams
|
├── d2/ # /d2 — Create D2 diagrams
|
||||||
├── describe/ # /describe — Emacs describe-* lookups
|
├── describe/ # /describe — Emacs describe-* lookups
|
||||||
├── dired/ # /dired — Open files in dired buffer
|
├── dired/ # /dired — Open files in dired buffer
|
||||||
|
├── edit-article/ # /edit-article — Restructure & tighten article prose
|
||||||
├── emacsclient/ # (auto) Always use emacsclient, not emacs
|
├── emacsclient/ # (auto) Always use emacsclient, not emacs
|
||||||
|
├── emacs-svg-maps/ # (auto) SVG map editing in Emacs
|
||||||
├── extract-pdf-pages/ # /extract-pdf-pages — Extract page ranges with pdftk
|
├── extract-pdf-pages/ # /extract-pdf-pages — Extract page ranges with pdftk
|
||||||
├── file-links/ # (auto) Format file refs as markdown #L links
|
├── file-links/ # (auto) Format file refs as markdown #L links
|
||||||
|
├── git-guardrails/ # /git-guardrails — Block dangerous git commands
|
||||||
├── gnuplot/ # /gnuplot — Plot data with gnuplot
|
├── gnuplot/ # /gnuplot — Plot data with gnuplot
|
||||||
|
├── grill-me/ # /grill-me — Stress-test a plan via relentless interview
|
||||||
├── highlight/ # /highlight — Highlight regions in Emacs
|
├── highlight/ # /highlight — Highlight regions in Emacs
|
||||||
|
├── improve-codebase-architecture/ # /improve-codebase-architecture — Deep module refactors
|
||||||
├── mermaid/ # /mermaid — Create Mermaid diagrams
|
├── mermaid/ # /mermaid — Create Mermaid diagrams
|
||||||
├── open/ # /open — Open files in Emacs buffers
|
├── open/ # /open — Open files in Emacs buffers
|
||||||
├── plantuml/ # /plantuml — Create PlantUML diagrams
|
├── plantuml/ # /plantuml — Create PlantUML diagrams
|
||||||
└── select/ # /select — Select regions in Emacs
|
├── request-refactor-plan/ # /request-refactor-plan — Tiny-commit refactor RFCs
|
||||||
|
├── select/ # /select — Select (mark) regions in Emacs
|
||||||
|
├── tdd/ # /tdd — Test-driven development (red-green-refactor)
|
||||||
|
├── triage-issue/ # /triage-issue — Bug investigation + TDD fix plan
|
||||||
|
└── write-a-skill/ # /write-a-skill — Scaffold new Claude Code skills
|
||||||
```
|
```
|
||||||
|
|
||||||
## Registration
|
## Registration
|
||||||
|
|
||||||
Registered in `~/.claude/settings.json` as:
|
Registered in `~/.claude/settings.json` as a local marketplace:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"extraKnownMarketplaces": {
|
"extraKnownMarketplaces": {
|
||||||
|
|
@ -48,18 +58,17 @@ Registered in `~/.claude/settings.json` as:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Skills Reference
|
||||||
|
|
||||||
All slash-command skills are available **system-wide** in any Claude Code session:
|
### Emacs Integration
|
||||||
|
|
||||||
| Skill | Invocation | Description |
|
| **Skill** | **Invocation** | **Description** |
|
||||||
|:---|:---:|:---|
|
|:---|:---:|:---|
|
||||||
| **d2** | `/d2` | Create diagrams with D2 |
|
| **d2** | `/d2` | Create diagrams with D2 |
|
||||||
| **describe** | `/describe` | Look up Emacs docs (functions, variables, keys) |
|
| **describe** | `/describe` | Look up Emacs docs (functions, variables, keys) |
|
||||||
| **dired** | `/dired` | Open recent files in Emacs dired buffer |
|
| **dired** | `/dired` | Open recent files in Emacs dired buffer |
|
||||||
| **emacsclient** | _(auto)_ | Always prefer `emacsclient` over `emacs` |
|
| **emacsclient** | _(auto)_ | Always prefer `emacsclient` over `emacs` |
|
||||||
| **extract-pdf-pages** | `/extract-pdf-pages` | Extract page range from PDF via `pdftk` |
|
| **emacs-svg-maps** | _(auto)_ | SVG map editing workflows (nxml, EWW, Inkscape) |
|
||||||
| **file-links** | _(auto)_ | Format file references as `file.py#L42` links |
|
|
||||||
| **gnuplot** | `/gnuplot` | Plot data with gnuplot |
|
| **gnuplot** | `/gnuplot` | Plot data with gnuplot |
|
||||||
| **highlight** | `/highlight` | Highlight line regions in Emacs buffers |
|
| **highlight** | `/highlight` | Highlight line regions in Emacs buffers |
|
||||||
| **mermaid** | `/mermaid` | Create Mermaid diagrams |
|
| **mermaid** | `/mermaid` | Create Mermaid diagrams |
|
||||||
|
|
@ -67,13 +76,42 @@ All slash-command skills are available **system-wide** in any Claude Code sessio
|
||||||
| **plantuml** | `/plantuml` | Create PlantUML diagrams |
|
| **plantuml** | `/plantuml` | Create PlantUML diagrams |
|
||||||
| **select** | `/select` | Select (mark) regions in Emacs buffers |
|
| **select** | `/select` | Select (mark) regions in Emacs buffers |
|
||||||
|
|
||||||
## Origin
|
### Development Workflow
|
||||||
|
|
||||||
|
| **Skill** | **Invocation** | **Description** |
|
||||||
|
|:---|:---:|:---|
|
||||||
|
| **tdd** | `/tdd` | Test-driven development — red-green-refactor vertical slices |
|
||||||
|
| **triage-issue** | `/triage-issue` | Investigate bug, find root cause, create TDD fix plan |
|
||||||
|
| **git-guardrails** | `/git-guardrails` | Block dangerous git commands (push, reset --hard, etc.) |
|
||||||
|
| **improve-codebase-architecture** | `/improve-codebase-architecture` | Find shallow modules, propose deep-module refactors |
|
||||||
|
| **request-refactor-plan** | `/request-refactor-plan` | Plan refactors as tiny safe commits via interview |
|
||||||
|
| **grill-me** | `/grill-me` | Stress-test a design/plan via relentless questioning |
|
||||||
|
|
||||||
|
### Content & Productivity
|
||||||
|
|
||||||
|
| **Skill** | **Invocation** | **Description** |
|
||||||
|
|:---|:---:|:---|
|
||||||
|
| **edit-article** | `/edit-article` | Restructure sections, improve clarity, tighten prose |
|
||||||
|
| **extract-pdf-pages** | `/extract-pdf-pages` | Extract page range from PDF via `pdftk` |
|
||||||
|
| **file-links** | _(auto)_ | Format file references as `file.py#L42` links |
|
||||||
|
| **write-a-skill** | `/write-a-skill` | Scaffold new Claude Code skills |
|
||||||
|
|
||||||
|
## Origin & Attribution
|
||||||
|
|
||||||
- **Emacs skills** (d2, describe, dired, emacsclient, file-links, gnuplot, highlight, mermaid, open, plantuml, select) — forked from [xenodium/emacs-skills](https://github.com/xenodium/emacs-skills) by Alvaro Ramirez
|
- **Emacs skills** (d2, describe, dired, emacsclient, file-links, gnuplot, highlight, mermaid, open, plantuml, select) — forked from [xenodium/emacs-skills](https://github.com/xenodium/emacs-skills) by Alvaro Ramirez
|
||||||
- **extract-pdf-pages** — original, requires `pdftk` (`apt install pdftk`)
|
- **Development workflow skills** (tdd, triage-issue, git-guardrails, improve-codebase-architecture, request-refactor-plan, grill-me, edit-article, write-a-skill) — adapted from [mattpocock/skills](https://github.com/mattpocock/skills) by Matt Pocock
|
||||||
|
- **emacs-svg-maps**, **extract-pdf-pages** — original by Fénix
|
||||||
|
|
||||||
|
### Adaptations from mattpocock originals
|
||||||
|
|
||||||
|
- **git-guardrails**: Rewritten to document both `settings.json` deny/ask rules (Fénix's approach) and PreToolUse hook scripts
|
||||||
|
- **triage-issue**: Added Gitea (`tea`) and BUGS.org support alongside GitHub (`gh`)
|
||||||
|
- **improve-codebase-architecture**: Added Gitea and Org-file output options
|
||||||
|
- **request-refactor-plan**: Added Gitea and Org-file output options
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- GNU Emacs with running server daemon (`emacsclient` accessible)
|
- GNU Emacs with running server daemon (`emacsclient` accessible)
|
||||||
- `pdftk` for PDF extraction skill
|
- `pdftk` for PDF extraction skill
|
||||||
|
- `gh` CLI for GitHub issue creation (optional — Gitea/Org alternatives available)
|
||||||
- Claude Code with plugins enabled
|
- Claude Code with plugins enabled
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
name: edit-article
|
||||||
|
description: Edit and improve articles by restructuring sections, improving clarity, and tightening prose. Use when user wants to edit, revise, or improve an article draft.
|
||||||
|
---
|
||||||
|
|
||||||
|
1. First, divide the article into sections based on its headings. Think about the main points you want to make during those sections.
|
||||||
|
|
||||||
|
Consider that information is a directed acyclic graph, and that pieces of information can depend on other pieces of information. Make sure that the order of the sections and their contents respects these dependencies.
|
||||||
|
|
||||||
|
Confirm the sections with the user.
|
||||||
|
|
||||||
|
2. For each section:
|
||||||
|
|
||||||
|
2a. Rewrite the section to improve clarity, coherence, and flow. Use maximum 240 characters per paragraph.
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
---
|
||||||
|
name: git-guardrails
|
||||||
|
description: Set up git safety guardrails for Claude Code — block dangerous commands (push, reset --hard, clean, branch -D, checkout .) via settings.json deny/ask rules or PreToolUse hooks. Use when user wants to prevent destructive git operations or review their git safety setup.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Git Guardrails for Claude Code
|
||||||
|
|
||||||
|
Prevent Claude from executing destructive git commands. Two enforcement strategies available — choose one or combine both.
|
||||||
|
|
||||||
|
## What Gets Blocked
|
||||||
|
|
||||||
|
- `git push` (all variants including `--force`)
|
||||||
|
- `git push --force` (force push — data loss risk)
|
||||||
|
- `git reset --hard` (discards uncommitted work)
|
||||||
|
- `git clean -f` / `git clean -fd` (deletes untracked files)
|
||||||
|
- `git branch -D` (force-delete branch)
|
||||||
|
- `git checkout .` / `git restore .` (discards all working changes)
|
||||||
|
- `rm -rf /*` / `sudo rm` (filesystem destruction)
|
||||||
|
|
||||||
|
## Strategy A: settings.json deny/ask rules (Fénix default)
|
||||||
|
|
||||||
|
This is the simpler approach — no scripts needed. Rules go in `~/.claude/settings.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"deny": [
|
||||||
|
"Bash(rm -rf /*)",
|
||||||
|
"Bash(sudo rm:*)",
|
||||||
|
"Bash(git reset --hard:*)",
|
||||||
|
"Bash(git push --force:*)"
|
||||||
|
],
|
||||||
|
"ask": [
|
||||||
|
"Bash(git push:*)",
|
||||||
|
"Bash(git clean:*)",
|
||||||
|
"Bash(git branch -D:*)",
|
||||||
|
"Bash(git checkout .:*)",
|
||||||
|
"Bash(git restore .:*)",
|
||||||
|
"Bash(pkill:*)",
|
||||||
|
"Bash(kill:*)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**deny** = hard block, Claude cannot execute even if asked.
|
||||||
|
**ask** = Claude must get user confirmation before executing.
|
||||||
|
|
||||||
|
### When to use
|
||||||
|
- Simple setups, single machine
|
||||||
|
- When you want some commands to be confirmable (ask) rather than fully blocked (deny)
|
||||||
|
- Already configured in `~/.claude/settings.json` — just merge the rules
|
||||||
|
|
||||||
|
## Strategy B: PreToolUse hook script
|
||||||
|
|
||||||
|
A shell script that intercepts Bash tool calls and blocks dangerous patterns before execution. More flexible — can use regex, log attempts, etc.
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
1. Copy the bundled script:
|
||||||
|
```bash
|
||||||
|
cp scripts/block-dangerous-git.sh ~/.claude/hooks/block-dangerous-git.sh
|
||||||
|
chmod +x ~/.claude/hooks/block-dangerous-git.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Add to `~/.claude/settings.json`:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"PreToolUse": [
|
||||||
|
{
|
||||||
|
"matcher": "Bash",
|
||||||
|
"hooks": [
|
||||||
|
{
|
||||||
|
"type": "command",
|
||||||
|
"command": "~/.claude/hooks/block-dangerous-git.sh"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### When to use
|
||||||
|
- When you need regex-based pattern matching
|
||||||
|
- When you want to log blocked attempts
|
||||||
|
- When deny/ask rules are too coarse
|
||||||
|
|
||||||
|
## Verify
|
||||||
|
|
||||||
|
Test the hook script:
|
||||||
|
```bash
|
||||||
|
echo '{"tool_input":{"command":"git push origin main"}}' | ~/.claude/hooks/block-dangerous-git.sh
|
||||||
|
```
|
||||||
|
Should exit code 2 and print BLOCKED to stderr.
|
||||||
|
|
||||||
|
## Fénix's current setup
|
||||||
|
|
||||||
|
Already configured in `~/.claude/settings.json`:
|
||||||
|
- **deny**: `rm -rf /*`, `sudo rm`, `git reset --hard`, `git push --force`
|
||||||
|
- **ask**: `pkill`, `kill`, `ssh`
|
||||||
|
- **CLAUDE.md**: Documents git permissions (read freely, write when asked, destructive = confirm first)
|
||||||
|
|
||||||
|
### Recommended additions to ask rules
|
||||||
|
Consider adding these to the `ask` array if not already present:
|
||||||
|
- `Bash(git clean:*)` — prevents accidental deletion of untracked files
|
||||||
|
- `Bash(git branch -D:*)` — prevents force-deleting branches
|
||||||
|
- `Bash(git checkout .:*)` — prevents discarding all working changes
|
||||||
|
- `Bash(git restore .:*)` — same as above, modern syntax
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
Adapted from [mattpocock/skills](https://github.com/mattpocock/skills) `git-guardrails-claude-code`.
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
INPUT=$(cat)
|
||||||
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command')
|
||||||
|
|
||||||
|
DANGEROUS_PATTERNS=(
|
||||||
|
"git push"
|
||||||
|
"git reset --hard"
|
||||||
|
"git clean -fd"
|
||||||
|
"git clean -f"
|
||||||
|
"git branch -D"
|
||||||
|
"git checkout \."
|
||||||
|
"git restore \."
|
||||||
|
"push --force"
|
||||||
|
"reset --hard"
|
||||||
|
)
|
||||||
|
|
||||||
|
for pattern in "${DANGEROUS_PATTERNS[@]}"; do
|
||||||
|
if echo "$COMMAND" | grep -qE "$pattern"; then
|
||||||
|
echo "BLOCKED: '$COMMAND' matches dangerous pattern '$pattern'. The user has prevented you from doing this." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: grill-me
|
||||||
|
description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
|
||||||
|
---
|
||||||
|
|
||||||
|
Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one.
|
||||||
|
|
||||||
|
If a question can be answered by exploring the codebase, explore the codebase instead.
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Reference
|
||||||
|
|
||||||
|
## Dependency Categories
|
||||||
|
|
||||||
|
When assessing a candidate for deepening, classify its dependencies:
|
||||||
|
|
||||||
|
### 1. In-process
|
||||||
|
|
||||||
|
Pure computation, in-memory state, no I/O. Always deepenable — just merge the modules and test directly.
|
||||||
|
|
||||||
|
### 2. Local-substitutable
|
||||||
|
|
||||||
|
Dependencies that have local test stand-ins (e.g., PGLite for Postgres, in-memory filesystem). Deepenable if the test substitute exists. The deepened module is tested with the local stand-in running in the test suite.
|
||||||
|
|
||||||
|
### 3. Remote but owned (Ports & Adapters)
|
||||||
|
|
||||||
|
Your own services across a network boundary (microservices, internal APIs). Define a port (interface) at the module boundary. The deep module owns the logic; the transport is injected. Tests use an in-memory adapter. Production uses the real HTTP/gRPC/queue adapter.
|
||||||
|
|
||||||
|
Recommendation shape: "Define a shared interface (port), implement an HTTP adapter for production and an in-memory adapter for testing, so the logic can be tested as one deep module even though it's deployed across a network boundary."
|
||||||
|
|
||||||
|
### 4. True external (Mock)
|
||||||
|
|
||||||
|
Third-party services (Stripe, Twilio, etc.) you don't control. Mock at the boundary. The deepened module takes the external dependency as an injected port, and tests provide a mock implementation.
|
||||||
|
|
||||||
|
## Testing Strategy
|
||||||
|
|
||||||
|
The core principle: **replace, don't layer.**
|
||||||
|
|
||||||
|
- Old unit tests on shallow modules are waste once boundary tests exist — delete them
|
||||||
|
- Write new tests at the deepened module's interface boundary
|
||||||
|
- Tests assert on observable outcomes through the public interface, not internal state
|
||||||
|
- Tests should survive internal refactors — they describe behavior, not implementation
|
||||||
|
|
||||||
|
## Issue Template
|
||||||
|
|
||||||
|
<issue-template>
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
Describe the architectural friction:
|
||||||
|
|
||||||
|
- Which modules are shallow and tightly coupled
|
||||||
|
- What integration risk exists in the seams between them
|
||||||
|
- Why this makes the codebase harder to navigate and maintain
|
||||||
|
|
||||||
|
## Proposed Interface
|
||||||
|
|
||||||
|
The chosen interface design:
|
||||||
|
|
||||||
|
- Interface signature (types, methods, params)
|
||||||
|
- Usage example showing how callers use it
|
||||||
|
- What complexity it hides internally
|
||||||
|
|
||||||
|
## Dependency Strategy
|
||||||
|
|
||||||
|
Which category applies and how dependencies are handled:
|
||||||
|
|
||||||
|
- **In-process**: merged directly
|
||||||
|
- **Local-substitutable**: tested with [specific stand-in]
|
||||||
|
- **Ports & adapters**: port definition, production adapter, test adapter
|
||||||
|
- **Mock**: mock boundary for external services
|
||||||
|
|
||||||
|
## Testing Strategy
|
||||||
|
|
||||||
|
- **New boundary tests to write**: describe the behaviors to verify at the interface
|
||||||
|
- **Old tests to delete**: list the shallow module tests that become redundant
|
||||||
|
- **Test environment needs**: any local stand-ins or adapters required
|
||||||
|
|
||||||
|
## Implementation Recommendations
|
||||||
|
|
||||||
|
Durable architectural guidance that is NOT coupled to current file paths:
|
||||||
|
|
||||||
|
- What the module should own (responsibilities)
|
||||||
|
- What it should hide (implementation details)
|
||||||
|
- What it should expose (the interface contract)
|
||||||
|
- How callers should migrate to the new interface
|
||||||
|
|
||||||
|
</issue-template>
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
---
|
||||||
|
name: improve-codebase-architecture
|
||||||
|
description: Explore a codebase to find opportunities for architectural improvement, focusing on making the codebase more testable by deepening shallow modules. Use when user wants to improve architecture, find refactoring opportunities, consolidate tightly-coupled modules, or make a codebase more AI-navigable.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Improve Codebase Architecture
|
||||||
|
|
||||||
|
Explore a codebase like an AI would, surface architectural friction, discover opportunities for improving testability, and propose module-deepening refactors as GitHub issue RFCs.
|
||||||
|
|
||||||
|
A **deep module** (John Ousterhout, "A Philosophy of Software Design") has a small interface hiding a large implementation. Deep modules are more testable, more AI-navigable, and let you test at the boundary instead of inside.
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
### 1. Explore the codebase
|
||||||
|
|
||||||
|
Use the Agent tool with subagent_type=Explore to navigate the codebase naturally. Do NOT follow rigid heuristics — explore organically and note where you experience friction:
|
||||||
|
|
||||||
|
- Where does understanding one concept require bouncing between many small files?
|
||||||
|
- Where are modules so shallow that the interface is nearly as complex as the implementation?
|
||||||
|
- Where have pure functions been extracted just for testability, but the real bugs hide in how they're called?
|
||||||
|
- Where do tightly-coupled modules create integration risk in the seams between them?
|
||||||
|
- Which parts of the codebase are untested, or hard to test?
|
||||||
|
|
||||||
|
The friction you encounter IS the signal.
|
||||||
|
|
||||||
|
### 2. Present candidates
|
||||||
|
|
||||||
|
Present a numbered list of deepening opportunities. For each candidate, show:
|
||||||
|
|
||||||
|
- **Cluster**: Which modules/concepts are involved
|
||||||
|
- **Why they're coupled**: Shared types, call patterns, co-ownership of a concept
|
||||||
|
- **Dependency category**: See [REFERENCE.md](REFERENCE.md) for the four categories
|
||||||
|
- **Test impact**: What existing tests would be replaced by boundary tests
|
||||||
|
|
||||||
|
Do NOT propose interfaces yet. Ask the user: "Which of these would you like to explore?"
|
||||||
|
|
||||||
|
### 3. User picks a candidate
|
||||||
|
|
||||||
|
### 4. Frame the problem space
|
||||||
|
|
||||||
|
Before spawning sub-agents, write a user-facing explanation of the problem space for the chosen candidate:
|
||||||
|
|
||||||
|
- The constraints any new interface would need to satisfy
|
||||||
|
- The dependencies it would need to rely on
|
||||||
|
- A rough illustrative code sketch to make the constraints concrete — this is not a proposal, just a way to ground the constraints
|
||||||
|
|
||||||
|
Show this to the user, then immediately proceed to Step 5. The user reads and thinks about the problem while the sub-agents work in parallel.
|
||||||
|
|
||||||
|
### 5. Design multiple interfaces
|
||||||
|
|
||||||
|
Spawn 3+ sub-agents in parallel using the Agent tool. Each must produce a **radically different** interface for the deepened module.
|
||||||
|
|
||||||
|
Prompt each sub-agent with a separate technical brief (file paths, coupling details, dependency category, what's being hidden). This brief is independent of the user-facing explanation in Step 4. Give each agent a different design constraint:
|
||||||
|
|
||||||
|
- Agent 1: "Minimize the interface — aim for 1-3 entry points max"
|
||||||
|
- Agent 2: "Maximize flexibility — support many use cases and extension"
|
||||||
|
- Agent 3: "Optimize for the most common caller — make the default case trivial"
|
||||||
|
- Agent 4 (if applicable): "Design around the ports & adapters pattern for cross-boundary dependencies"
|
||||||
|
|
||||||
|
Each sub-agent outputs:
|
||||||
|
|
||||||
|
1. Interface signature (types, methods, params)
|
||||||
|
2. Usage example showing how callers use it
|
||||||
|
3. What complexity it hides internally
|
||||||
|
4. Dependency strategy (how deps are handled — see [REFERENCE.md](REFERENCE.md))
|
||||||
|
5. Trade-offs
|
||||||
|
|
||||||
|
Present designs sequentially, then compare them in prose.
|
||||||
|
|
||||||
|
After comparing, give your own recommendation: which design you think is strongest and why. If elements from different designs would combine well, propose a hybrid. Be opinionated — the user wants a strong read, not just a menu.
|
||||||
|
|
||||||
|
### 6. User picks an interface (or accepts recommendation)
|
||||||
|
|
||||||
|
### 7. Create issue
|
||||||
|
|
||||||
|
Ask the user where to file the RFC:
|
||||||
|
- **GitHub/Gitea**: Use `gh issue create` or `tea issue create` with the template in [REFERENCE.md](REFERENCE.md)
|
||||||
|
- **Org file**: Write to the project's planning file (TASKS.org, TODO.org, etc.)
|
||||||
|
|
||||||
|
Do NOT ask the user to review before creating — just create it and share the URL or file path.
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
---
|
||||||
|
name: request-refactor-plan
|
||||||
|
description: Create a detailed refactor plan with tiny commits via user interview, then file it as a GitHub issue. Use when user wants to plan a refactor, create a refactoring RFC, or break a refactor into safe incremental steps.
|
||||||
|
---
|
||||||
|
|
||||||
|
This skill will be invoked when the user wants to create a refactor request. You should go through the steps below. You may skip steps if you don't consider them necessary.
|
||||||
|
|
||||||
|
1. Ask the user for a long, detailed description of the problem they want to solve and any potential ideas for solutions.
|
||||||
|
|
||||||
|
2. Explore the repo to verify their assertions and understand the current state of the codebase.
|
||||||
|
|
||||||
|
3. Ask whether they have considered other options, and present other options to them.
|
||||||
|
|
||||||
|
4. Interview the user about the implementation. Be extremely detailed and thorough.
|
||||||
|
|
||||||
|
5. Hammer out the exact scope of the implementation. Work out what you plan to change and what you plan not to change.
|
||||||
|
|
||||||
|
6. Look in the codebase to check for test coverage of this area of the codebase. If there is insufficient test coverage, ask the user what their plans for testing are.
|
||||||
|
|
||||||
|
7. Break the implementation into a plan of tiny commits. Remember Martin Fowler's advice to "make each refactoring step as small as possible, so that you can always see the program working."
|
||||||
|
|
||||||
|
8. Create the refactor plan. Ask the user where to file it:
|
||||||
|
- **GitHub/Gitea**: Use `gh issue create` or `tea issue create`
|
||||||
|
- **Org file**: Write to the project's planning file (TASKS.org, TODO.org, etc.)
|
||||||
|
|
||||||
|
Use the following template for the issue/entry description:
|
||||||
|
|
||||||
|
<refactor-plan-template>
|
||||||
|
|
||||||
|
## Problem Statement
|
||||||
|
|
||||||
|
The problem that the developer is facing, from the developer's perspective.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
The solution to the problem, from the developer's perspective.
|
||||||
|
|
||||||
|
## Commits
|
||||||
|
|
||||||
|
A LONG, detailed implementation plan. Write the plan in plain English, breaking down the implementation into the tiniest commits possible. Each commit should leave the codebase in a working state.
|
||||||
|
|
||||||
|
## Decision Document
|
||||||
|
|
||||||
|
A list of implementation decisions that were made. This can include:
|
||||||
|
|
||||||
|
- The modules that will be built/modified
|
||||||
|
- The interfaces of those modules that will be modified
|
||||||
|
- Technical clarifications from the developer
|
||||||
|
- Architectural decisions
|
||||||
|
- Schema changes
|
||||||
|
- API contracts
|
||||||
|
- Specific interactions
|
||||||
|
|
||||||
|
Do NOT include specific file paths or code snippets. They may end up being outdated very quickly.
|
||||||
|
|
||||||
|
## Testing Decisions
|
||||||
|
|
||||||
|
A list of testing decisions that were made. Include:
|
||||||
|
|
||||||
|
- A description of what makes a good test (only test external behavior, not implementation details)
|
||||||
|
- Which modules will be tested
|
||||||
|
- Prior art for the tests (i.e. similar types of tests in the codebase)
|
||||||
|
|
||||||
|
## Out of Scope
|
||||||
|
|
||||||
|
A description of the things that are out of scope for this refactor.
|
||||||
|
|
||||||
|
## Further Notes (optional)
|
||||||
|
|
||||||
|
Any further notes about the refactor.
|
||||||
|
|
||||||
|
</refactor-plan-template>
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
---
|
||||||
|
name: tdd
|
||||||
|
description: Test-driven development with red-green-refactor loop. Use when user wants to build features or fix bugs using TDD, mentions "red-green-refactor", wants integration tests, or asks for test-first development.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Test-Driven Development
|
||||||
|
|
||||||
|
## Philosophy
|
||||||
|
|
||||||
|
**Core principle**: Tests should verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't.
|
||||||
|
|
||||||
|
**Good tests** are integration-style: they exercise real code paths through public APIs. They describe _what_ the system does, not _how_ it does it. A good test reads like a specification - "user can checkout with valid cart" tells you exactly what capability exists. These tests survive refactors because they don't care about internal structure.
|
||||||
|
|
||||||
|
**Bad tests** are coupled to implementation. They mock internal collaborators, test private methods, or verify through external means (like querying a database directly instead of using the interface). The warning sign: your test breaks when you refactor, but behavior hasn't changed. If you rename an internal function and tests fail, those tests were testing implementation, not behavior.
|
||||||
|
|
||||||
|
See [tests.md](tests.md) for examples and [mocking.md](mocking.md) for mocking guidelines.
|
||||||
|
|
||||||
|
## Anti-Pattern: Horizontal Slices
|
||||||
|
|
||||||
|
**DO NOT write all tests first, then all implementation.** This is "horizontal slicing" - treating RED as "write all tests" and GREEN as "write all code."
|
||||||
|
|
||||||
|
This produces **crap tests**:
|
||||||
|
|
||||||
|
- Tests written in bulk test _imagined_ behavior, not _actual_ behavior
|
||||||
|
- You end up testing the _shape_ of things (data structures, function signatures) rather than user-facing behavior
|
||||||
|
- Tests become insensitive to real changes - they pass when behavior breaks, fail when behavior is fine
|
||||||
|
- You outrun your headlights, committing to test structure before understanding the implementation
|
||||||
|
|
||||||
|
**Correct approach**: Vertical slices via tracer bullets. One test → one implementation → repeat. Each test responds to what you learned from the previous cycle. Because you just wrote the code, you know exactly what behavior matters and how to verify it.
|
||||||
|
|
||||||
|
```
|
||||||
|
WRONG (horizontal):
|
||||||
|
RED: test1, test2, test3, test4, test5
|
||||||
|
GREEN: impl1, impl2, impl3, impl4, impl5
|
||||||
|
|
||||||
|
RIGHT (vertical):
|
||||||
|
RED→GREEN: test1→impl1
|
||||||
|
RED→GREEN: test2→impl2
|
||||||
|
RED→GREEN: test3→impl3
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
### 1. Planning
|
||||||
|
|
||||||
|
Before writing any code:
|
||||||
|
|
||||||
|
- [ ] Confirm with user what interface changes are needed
|
||||||
|
- [ ] Confirm with user which behaviors to test (prioritize)
|
||||||
|
- [ ] Identify opportunities for [deep modules](deep-modules.md) (small interface, deep implementation)
|
||||||
|
- [ ] Design interfaces for [testability](interface-design.md)
|
||||||
|
- [ ] List the behaviors to test (not implementation steps)
|
||||||
|
- [ ] Get user approval on the plan
|
||||||
|
|
||||||
|
Ask: "What should the public interface look like? Which behaviors are most important to test?"
|
||||||
|
|
||||||
|
**You can't test everything.** Confirm with the user exactly which behaviors matter most. Focus testing effort on critical paths and complex logic, not every possible edge case.
|
||||||
|
|
||||||
|
### 2. Tracer Bullet
|
||||||
|
|
||||||
|
Write ONE test that confirms ONE thing about the system:
|
||||||
|
|
||||||
|
```
|
||||||
|
RED: Write test for first behavior → test fails
|
||||||
|
GREEN: Write minimal code to pass → test passes
|
||||||
|
```
|
||||||
|
|
||||||
|
This is your tracer bullet - proves the path works end-to-end.
|
||||||
|
|
||||||
|
### 3. Incremental Loop
|
||||||
|
|
||||||
|
For each remaining behavior:
|
||||||
|
|
||||||
|
```
|
||||||
|
RED: Write next test → fails
|
||||||
|
GREEN: Minimal code to pass → passes
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- One test at a time
|
||||||
|
- Only enough code to pass current test
|
||||||
|
- Don't anticipate future tests
|
||||||
|
- Keep tests focused on observable behavior
|
||||||
|
|
||||||
|
### 4. Refactor
|
||||||
|
|
||||||
|
After all tests pass, look for [refactor candidates](refactoring.md):
|
||||||
|
|
||||||
|
- [ ] Extract duplication
|
||||||
|
- [ ] Deepen modules (move complexity behind simple interfaces)
|
||||||
|
- [ ] Apply SOLID principles where natural
|
||||||
|
- [ ] Consider what new code reveals about existing code
|
||||||
|
- [ ] Run tests after each refactor step
|
||||||
|
|
||||||
|
**Never refactor while RED.** Get to GREEN first.
|
||||||
|
|
||||||
|
## Checklist Per Cycle
|
||||||
|
|
||||||
|
```
|
||||||
|
[ ] Test describes behavior, not implementation
|
||||||
|
[ ] Test uses public interface only
|
||||||
|
[ ] Test would survive internal refactor
|
||||||
|
[ ] Code is minimal for this test
|
||||||
|
[ ] No speculative features added
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Deep Modules
|
||||||
|
|
||||||
|
From "A Philosophy of Software Design":
|
||||||
|
|
||||||
|
**Deep module** = small interface + lots of implementation
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────┐
|
||||||
|
│ Small Interface │ ← Few methods, simple params
|
||||||
|
├─────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ Deep Implementation│ ← Complex logic hidden
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**Shallow module** = large interface + little implementation (avoid)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────┐
|
||||||
|
│ Large Interface │ ← Many methods, complex params
|
||||||
|
├─────────────────────────────────┤
|
||||||
|
│ Thin Implementation │ ← Just passes through
|
||||||
|
└─────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
When designing interfaces, ask:
|
||||||
|
|
||||||
|
- Can I reduce the number of methods?
|
||||||
|
- Can I simplify the parameters?
|
||||||
|
- Can I hide more complexity inside?
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Interface Design for Testability
|
||||||
|
|
||||||
|
Good interfaces make testing natural:
|
||||||
|
|
||||||
|
1. **Accept dependencies, don't create them**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Testable
|
||||||
|
function processOrder(order, paymentGateway) {}
|
||||||
|
|
||||||
|
// Hard to test
|
||||||
|
function processOrder(order) {
|
||||||
|
const gateway = new StripeGateway();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Return results, don't produce side effects**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Testable
|
||||||
|
function calculateDiscount(cart): Discount {}
|
||||||
|
|
||||||
|
// Hard to test
|
||||||
|
function applyDiscount(cart): void {
|
||||||
|
cart.total -= discount;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Small surface area**
|
||||||
|
- Fewer methods = fewer tests needed
|
||||||
|
- Fewer params = simpler test setup
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
# When to Mock
|
||||||
|
|
||||||
|
Mock at **system boundaries** only:
|
||||||
|
|
||||||
|
- External APIs (payment, email, etc.)
|
||||||
|
- Databases (sometimes - prefer test DB)
|
||||||
|
- Time/randomness
|
||||||
|
- File system (sometimes)
|
||||||
|
|
||||||
|
Don't mock:
|
||||||
|
|
||||||
|
- Your own classes/modules
|
||||||
|
- Internal collaborators
|
||||||
|
- Anything you control
|
||||||
|
|
||||||
|
## Designing for Mockability
|
||||||
|
|
||||||
|
At system boundaries, design interfaces that are easy to mock:
|
||||||
|
|
||||||
|
**1. Use dependency injection**
|
||||||
|
|
||||||
|
Pass external dependencies in rather than creating them internally:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Easy to mock
|
||||||
|
function processPayment(order, paymentClient) {
|
||||||
|
return paymentClient.charge(order.total);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hard to mock
|
||||||
|
function processPayment(order) {
|
||||||
|
const client = new StripeClient(process.env.STRIPE_KEY);
|
||||||
|
return client.charge(order.total);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Prefer SDK-style interfaces over generic fetchers**
|
||||||
|
|
||||||
|
Create specific functions for each external operation instead of one generic function with conditional logic:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// GOOD: Each function is independently mockable
|
||||||
|
const api = {
|
||||||
|
getUser: (id) => fetch(`/users/${id}`),
|
||||||
|
getOrders: (userId) => fetch(`/users/${userId}/orders`),
|
||||||
|
createOrder: (data) => fetch('/orders', { method: 'POST', body: data }),
|
||||||
|
};
|
||||||
|
|
||||||
|
// BAD: Mocking requires conditional logic inside the mock
|
||||||
|
const api = {
|
||||||
|
fetch: (endpoint, options) => fetch(endpoint, options),
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The SDK approach means:
|
||||||
|
- Each mock returns one specific shape
|
||||||
|
- No conditional logic in test setup
|
||||||
|
- Easier to see which endpoints a test exercises
|
||||||
|
- Type safety per endpoint
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Refactor Candidates
|
||||||
|
|
||||||
|
After TDD cycle, look for:
|
||||||
|
|
||||||
|
- **Duplication** → Extract function/class
|
||||||
|
- **Long methods** → Break into private helpers (keep tests on public interface)
|
||||||
|
- **Shallow modules** → Combine or deepen
|
||||||
|
- **Feature envy** → Move logic to where data lives
|
||||||
|
- **Primitive obsession** → Introduce value objects
|
||||||
|
- **Existing code** the new code reveals as problematic
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
# Good and Bad Tests
|
||||||
|
|
||||||
|
## Good Tests
|
||||||
|
|
||||||
|
**Integration-style**: Test through real interfaces, not mocks of internal parts.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// GOOD: Tests observable behavior
|
||||||
|
test("user can checkout with valid cart", async () => {
|
||||||
|
const cart = createCart();
|
||||||
|
cart.add(product);
|
||||||
|
const result = await checkout(cart, paymentMethod);
|
||||||
|
expect(result.status).toBe("confirmed");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Characteristics:
|
||||||
|
|
||||||
|
- Tests behavior users/callers care about
|
||||||
|
- Uses public API only
|
||||||
|
- Survives internal refactors
|
||||||
|
- Describes WHAT, not HOW
|
||||||
|
- One logical assertion per test
|
||||||
|
|
||||||
|
## Bad Tests
|
||||||
|
|
||||||
|
**Implementation-detail tests**: Coupled to internal structure.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// BAD: Tests implementation details
|
||||||
|
test("checkout calls paymentService.process", async () => {
|
||||||
|
const mockPayment = jest.mock(paymentService);
|
||||||
|
await checkout(cart, payment);
|
||||||
|
expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Red flags:
|
||||||
|
|
||||||
|
- Mocking internal collaborators
|
||||||
|
- Testing private methods
|
||||||
|
- Asserting on call counts/order
|
||||||
|
- Test breaks when refactoring without behavior change
|
||||||
|
- Test name describes HOW not WHAT
|
||||||
|
- Verifying through external means instead of interface
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// BAD: Bypasses interface to verify
|
||||||
|
test("createUser saves to database", async () => {
|
||||||
|
await createUser({ name: "Alice" });
|
||||||
|
const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]);
|
||||||
|
expect(row).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
// GOOD: Verifies through interface
|
||||||
|
test("createUser makes user retrievable", async () => {
|
||||||
|
const user = await createUser({ name: "Alice" });
|
||||||
|
const retrieved = await getUser(user.id);
|
||||||
|
expect(retrieved.name).toBe("Alice");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
---
|
||||||
|
name: triage-issue
|
||||||
|
description: Triage a bug or issue by exploring the codebase to find root cause, then create an issue (GitHub/Gitea) or BUGS.org entry with a TDD-based fix plan. Use when user reports a bug, wants to file an issue, mentions "triage", or wants to investigate and plan a fix for a problem.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Triage Issue
|
||||||
|
|
||||||
|
Investigate a reported problem, find its root cause, and create a GitHub issue with a TDD fix plan. This is a mostly hands-off workflow - minimize questions to the user.
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
### 1. Capture the problem
|
||||||
|
|
||||||
|
Get a brief description of the issue from the user. If they haven't provided one, ask ONE question: "What's the problem you're seeing?"
|
||||||
|
|
||||||
|
Do NOT ask follow-up questions yet. Start investigating immediately.
|
||||||
|
|
||||||
|
### 2. Explore and diagnose
|
||||||
|
|
||||||
|
Use the Agent tool with subagent_type=Explore to deeply investigate the codebase. Your goal is to find:
|
||||||
|
|
||||||
|
- **Where** the bug manifests (entry points, UI, API responses)
|
||||||
|
- **What** code path is involved (trace the flow)
|
||||||
|
- **Why** it fails (the root cause, not just the symptom)
|
||||||
|
- **What** related code exists (similar patterns, tests, adjacent modules)
|
||||||
|
|
||||||
|
Look at:
|
||||||
|
- Related source files and their dependencies
|
||||||
|
- Existing tests (what's tested, what's missing)
|
||||||
|
- Recent changes to affected files (`git log` on relevant files)
|
||||||
|
- Error handling in the code path
|
||||||
|
- Similar patterns elsewhere in the codebase that work correctly
|
||||||
|
|
||||||
|
### 3. Identify the fix approach
|
||||||
|
|
||||||
|
Based on your investigation, determine:
|
||||||
|
|
||||||
|
- The minimal change needed to fix the root cause
|
||||||
|
- Which modules/interfaces are affected
|
||||||
|
- What behaviors need to be verified via tests
|
||||||
|
- Whether this is a regression, missing feature, or design flaw
|
||||||
|
|
||||||
|
### 4. Design TDD fix plan
|
||||||
|
|
||||||
|
Create a concrete, ordered list of RED-GREEN cycles. Each cycle is one vertical slice:
|
||||||
|
|
||||||
|
- **RED**: Describe a specific test that captures the broken/missing behavior
|
||||||
|
- **GREEN**: Describe the minimal code change to make that test pass
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
- Tests verify behavior through public interfaces, not implementation details
|
||||||
|
- One test at a time, vertical slices (NOT all tests first, then all code)
|
||||||
|
- Each test should survive internal refactors
|
||||||
|
- Include a final refactor step if needed
|
||||||
|
- **Durability**: Only suggest fixes that would survive radical codebase changes. Describe behaviors and contracts, not internal structure. Tests assert on observable outcomes (API responses, UI state, user-visible effects), not internal state. A good suggestion reads like a spec; a bad one reads like a diff.
|
||||||
|
|
||||||
|
### 5. Create the issue
|
||||||
|
|
||||||
|
Ask the user where to file the issue:
|
||||||
|
- **GitHub/Gitea**: Use `gh issue create` or `tea issue create` with the template below
|
||||||
|
- **BUGS.org**: Append to the project's BUGS.org file following the `~/.claude/bugs_convention.md` format
|
||||||
|
- If the project has a BUGS.org, default to that; otherwise use the git forge
|
||||||
|
|
||||||
|
<issue-template>
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
A clear description of the bug or issue, including:
|
||||||
|
- What happens (actual behavior)
|
||||||
|
- What should happen (expected behavior)
|
||||||
|
- How to reproduce (if applicable)
|
||||||
|
|
||||||
|
## Root Cause Analysis
|
||||||
|
|
||||||
|
Describe what you found during investigation:
|
||||||
|
- The code path involved
|
||||||
|
- Why the current code fails
|
||||||
|
- Any contributing factors
|
||||||
|
|
||||||
|
Do NOT include specific file paths, line numbers, or implementation details that couple to current code layout. Describe modules, behaviors, and contracts instead. The issue should remain useful even after major refactors.
|
||||||
|
|
||||||
|
## TDD Fix Plan
|
||||||
|
|
||||||
|
A numbered list of RED-GREEN cycles:
|
||||||
|
|
||||||
|
1. **RED**: Write a test that [describes expected behavior]
|
||||||
|
**GREEN**: [Minimal change to make it pass]
|
||||||
|
|
||||||
|
2. **RED**: Write a test that [describes next behavior]
|
||||||
|
**GREEN**: [Minimal change to make it pass]
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
**REFACTOR**: [Any cleanup needed after all tests pass]
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] Criterion 1
|
||||||
|
- [ ] Criterion 2
|
||||||
|
- [ ] All new tests pass
|
||||||
|
- [ ] Existing tests still pass
|
||||||
|
|
||||||
|
</issue-template>
|
||||||
|
|
||||||
|
After creating the issue, print the issue URL and a one-line summary of the root cause.
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
---
|
||||||
|
name: write-a-skill
|
||||||
|
description: Create new agent skills with proper structure, progressive disclosure, and bundled resources. Use when user wants to create, write, or build a new skill.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Writing Skills
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
1. **Gather requirements** - ask user about:
|
||||||
|
- What task/domain does the skill cover?
|
||||||
|
- What specific use cases should it handle?
|
||||||
|
- Does it need executable scripts or just instructions?
|
||||||
|
- Any reference materials to include?
|
||||||
|
|
||||||
|
2. **Draft the skill** - create:
|
||||||
|
- SKILL.md with concise instructions
|
||||||
|
- Additional reference files if content exceeds 500 lines
|
||||||
|
- Utility scripts if deterministic operations needed
|
||||||
|
|
||||||
|
3. **Review with user** - present draft and ask:
|
||||||
|
- Does this cover your use cases?
|
||||||
|
- Anything missing or unclear?
|
||||||
|
- Should any section be more/less detailed?
|
||||||
|
|
||||||
|
## Skill Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
skill-name/
|
||||||
|
├── SKILL.md # Main instructions (required)
|
||||||
|
├── REFERENCE.md # Detailed docs (if needed)
|
||||||
|
├── EXAMPLES.md # Usage examples (if needed)
|
||||||
|
└── scripts/ # Utility scripts (if needed)
|
||||||
|
└── helper.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## SKILL.md Template
|
||||||
|
|
||||||
|
```md
|
||||||
|
---
|
||||||
|
name: skill-name
|
||||||
|
description: Brief description of capability. Use when [specific triggers].
|
||||||
|
---
|
||||||
|
|
||||||
|
# Skill Name
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
[Minimal working example]
|
||||||
|
|
||||||
|
## Workflows
|
||||||
|
|
||||||
|
[Step-by-step processes with checklists for complex tasks]
|
||||||
|
|
||||||
|
## Advanced features
|
||||||
|
|
||||||
|
[Link to separate files: See [REFERENCE.md](REFERENCE.md)]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Description Requirements
|
||||||
|
|
||||||
|
The description is **the only thing your agent sees** when deciding which skill to load. It's surfaced in the system prompt alongside all other installed skills. Your agent reads these descriptions and picks the relevant skill based on the user's request.
|
||||||
|
|
||||||
|
**Goal**: Give your agent just enough info to know:
|
||||||
|
|
||||||
|
1. What capability this skill provides
|
||||||
|
2. When/why to trigger it (specific keywords, contexts, file types)
|
||||||
|
|
||||||
|
**Format**:
|
||||||
|
|
||||||
|
- Max 1024 chars
|
||||||
|
- Write in third person
|
||||||
|
- First sentence: what it does
|
||||||
|
- Second sentence: "Use when [specific triggers]"
|
||||||
|
|
||||||
|
**Good example**:
|
||||||
|
|
||||||
|
```
|
||||||
|
Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when user mentions PDFs, forms, or document extraction.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bad example**:
|
||||||
|
|
||||||
|
```
|
||||||
|
Helps with documents.
|
||||||
|
```
|
||||||
|
|
||||||
|
The bad example gives your agent no way to distinguish this from other document skills.
|
||||||
|
|
||||||
|
## When to Add Scripts
|
||||||
|
|
||||||
|
Add utility scripts when:
|
||||||
|
|
||||||
|
- Operation is deterministic (validation, formatting)
|
||||||
|
- Same code would be generated repeatedly
|
||||||
|
- Errors need explicit handling
|
||||||
|
|
||||||
|
Scripts save tokens and improve reliability vs generated code.
|
||||||
|
|
||||||
|
## When to Split Files
|
||||||
|
|
||||||
|
Split into separate files when:
|
||||||
|
|
||||||
|
- SKILL.md exceeds 100 lines
|
||||||
|
- Content has distinct domains (finance vs sales schemas)
|
||||||
|
- Advanced features are rarely needed
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
|
||||||
|
After drafting, verify:
|
||||||
|
|
||||||
|
- [ ] Description includes triggers ("Use when...")
|
||||||
|
- [ ] SKILL.md under 100 lines
|
||||||
|
- [ ] No time-sensitive info
|
||||||
|
- [ ] Consistent terminology
|
||||||
|
- [ ] Concrete examples included
|
||||||
|
- [ ] References one level deep
|
||||||
Loading…
Reference in New Issue