Test-driven development with Result types. Red-green-refactor cycles using vitest-mock-extended, explicit deps mocking, and Result assertions.
Executes strict red-green-refactor-verify TDD cycles. Triggers when you request new functions or features, guiding you through writing failing Result type tests, minimal implementations, pattern refactoring, and full verification.
/plugin marketplace add jagreehal/jagreehal-claude-skills/plugin install jagreehal-claude-skills@jagreehal-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Strict red-green-refactor with Result types and dependency injection.
USER REQUEST
│
▼
┌─────────┐
│ RED │ ◄─── Write failing test
└────┬────┘
│ test fails correctly
▼
┌─────────┐
│ GREEN │ ◄─── Minimum code to pass
└────┬────┘
│ test passes
▼
┌─────────┐
│REFACTOR │ ◄─── Improve design, keep green
└────┬────┘
│ still passes
▼
┌─────────┐
│ VERIFY │ ◄─── Full suite + lint + build
└─────────┘
Every message announces state:
[RED] Writing test for getUser returning NOT_FOUND...
[GREEN] Test passes. Checking if refactor needed...
[REFACTOR] Extracting deps type. Running test...
[VERIFY] Running full suite...
import { describe, it, expect } from 'vitest';
import { mock } from 'vitest-mock-extended';
import { getUser, type GetUserDeps } from './get-user';
describe('getUser', () => {
it('returns err NOT_FOUND when user does not exist', async () => {
// Arrange: mock deps
const deps = mock<GetUserDeps>();
deps.db.findUser.mockResolvedValue(null);
// Act
const result = await getUser({ userId: '123' }, deps);
// Assert Result type
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error).toBe('NOT_FOUND');
}
});
});
mock<DepsType>() for typed mocksMEANINGFUL (proceed to GREEN):
- "expected err('NOT_FOUND') but got ok(user)"
- "expected 404 but got 200"
SETUP (fix before proceeding):
- "Cannot find module './get-user'"
- "Property 'findUser' does not exist on type"
- "TypeError: deps.db is undefined"
Error: expected result.ok to be false, got true
WRONG: Implement full validation, logging, error handling
RIGHT: Return err('NOT_FOUND') when user is null
// First test: expects err('NOT_FOUND')
// Minimum implementation:
if (!user) return err('NOT_FOUND');
return ok(user);
// Second test: expects ok(user) with specific fields
// Generalize only when forced by multiple tests
| Pattern | Check |
|---|---|
| fn(args, deps) | Is deps type explicit and minimal? |
| Result types | Are all error cases typed? |
| Validation | Is Zod at boundary only? |
| Naming | Are names domain-specific, not generic? |
// BEFORE: inline deps type
async function getUser(
args: { userId: string },
deps: { db: Database; logger: Logger }
)
// AFTER: extracted type
type GetUserDeps = { db: Database; logger: Logger };
async function getUser(
args: { userId: string },
deps: GetUserDeps
)
Skip refactoring when:
Never skip refactor when:
Before completing, run ALL:
npm test # Full test suite
npm run lint # ESLint passes
npm run typecheck # tsc --noEmit passes
npm run build # Build succeeds (if applicable)
any leaks, no as castsit('returns ok with user when found', async () => {
const mockUser = { id: '123', name: 'Alice' };
const deps = mock<GetUserDeps>();
deps.db.findUser.mockResolvedValue(mockUser);
const result = await getUser({ userId: '123' }, deps);
expect(result.ok).toBe(true);
if (result.ok) {
expect(result.value).toEqual(mockUser);
}
});
it('returns err NOT_FOUND when user missing', async () => {
const deps = mock<GetUserDeps>();
deps.db.findUser.mockResolvedValue(null);
const result = await getUser({ userId: '123' }, deps);
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error).toBe('NOT_FOUND');
}
});
it('returns err DB_ERROR on database failure', async () => {
const deps = mock<GetUserDeps>();
deps.db.findUser.mockRejectedValue(new Error('Connection failed'));
const result = await getUser({ userId: '123' }, deps);
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error).toBe('DB_ERROR');
}
});
Test fails? Fix IMPLEMENTATION, not test.
VIOLATION: Changing expect(result.error).toBe('NOT_FOUND')
to expect(result.error).toBe('ERROR')
because implementation returns 'ERROR'
CORRECT: Change implementation to return 'NOT_FOUND'
VIOLATION: Write test → Write full implementation → Skip refactor
CORRECT: RED → GREEN (minimum) → REFACTOR → VERIFY
// WRONG: vi.mock creates brittle path coupling
vi.mock('../infra/database', () => ({ db: mockDb }));
// CORRECT: Inject deps, mock with vitest-mock-extended
const deps = mock<GetUserDeps>();
deps.db.findUser.mockResolvedValue(mockUser);
| State | Action | Exit Condition |
|---|---|---|
| RED | Write failing test | Test fails meaningfully |
| GREEN | Minimum implementation | Test passes |
| REFACTOR | Apply patterns | Tests still pass |
| VERIFY | Full suite + lint + build | All green |
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.