一键导入
use-case-tdd
Scaffold a new use case with TDD RED-GREEN-REFACTOR cycle, DI registration, and test file
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Scaffold a new use case with TDD RED-GREEN-REFACTOR cycle, DI registration, and test file
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Show CI/CD pipeline status for current branch with job details and failure diagnostics
Cross-validate documentation and artifacts across the codebase for consistency, conflicts, and contradictions. Use when users ask to "cross-validate", "validate docs", "check documentation consistency", "audit documentation", or find conflicts/contradictions in docs. Supports automatic fixing with "validate and fix" argument. Runs parallel subagents for efficient validation across categories (domain-models, agent-system, tech-stack, architecture, cli-commands). Part of the ShipIT autonomous SDLC platform — https://github.com/jrmatherly/shipit
React Flow (@xyflow/react) for workflow visualization with custom nodes and edges. Use when building graph visualizations, creating custom workflow nodes, implementing edge labels, or controlling viewport. Triggers on ReactFlow, @xyflow/react, Handle, NodeProps, EdgeProps, useReactFlow, fitView.
Diagnose semantic-release and npm publish failures from the latest CI release job
Provides complete shadcn/ui component library patterns including installation, configuration, and implementation of accessible React components. Use when setting up shadcn/ui, installing components, building forms with React Hook Form and Zod, customizing themes with Tailwind CSS, or implementing UI patterns like buttons, dialogs, dropdowns, tables, and complex form layouts.
Use when ready to commit, push, and create a PR with CI verification. Triggers include "commit and pr", "push pr", "create pr", "ship it", or when implementation is complete and needs CI validation. Watches CI and auto-fixes failures. Part of the ShipIT autonomous SDLC platform — https://github.com/jrmatherly/shipit
| name | use-case-tdd |
| description | Scaffold a new use case with TDD RED-GREEN-REFACTOR cycle, DI registration, and test file |
| user_invocable | true |
Scaffold a new use case class following strict TDD discipline: write the failing test first, then implement minimally, then refactor.
Before starting, identify:
CreateFeature, ListAgentRuns)| Item | Convention | Example |
|---|---|---|
| Use case file | kebab-case.ts | create-feature.ts |
| Use case class | PascalCaseUseCase | CreateFeatureUseCase |
| Test file | kebab-case.test.ts | create-feature.test.ts |
| Use case dir | packages/core/src/application/use-cases/ | — |
| Test dir | tests/unit/application/use-cases/ | — |
| DI token | Interface name string | 'IFeatureRepository' |
Create the test file before the implementation:
// tests/unit/application/use-cases/create-feature.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { CreateFeatureUseCase } from '@/application/use-cases/create-feature';
import type { IFeatureRepository } from '@/application/ports/output/repositories/feature-repository.interface';
describe('CreateFeatureUseCase', () => {
let useCase: CreateFeatureUseCase;
let mockFeatureRepo: IFeatureRepository;
beforeEach(() => {
mockFeatureRepo = {
create: vi.fn().mockResolvedValue(undefined),
findById: vi.fn().mockResolvedValue(null),
findByIds: vi.fn().mockResolvedValue([]),
list: vi.fn().mockResolvedValue([]),
listActive: vi.fn().mockResolvedValue([]),
update: vi.fn().mockResolvedValue(undefined),
delete: vi.fn().mockResolvedValue(undefined),
};
useCase = new CreateFeatureUseCase(mockFeatureRepo);
});
describe('execute', () => {
it('should create a feature with valid input', async () => {
const input = { name: 'my-feature', repoPath: '/tmp/repo' };
await useCase.execute(input);
expect(mockFeatureRepo.create).toHaveBeenCalledWith(
expect.objectContaining({ name: 'my-feature' }),
);
});
it('should throw if name is empty', async () => {
const input = { name: '', repoPath: '/tmp/repo' };
await expect(useCase.execute(input)).rejects.toThrow();
});
it('should throw if feature already exists', async () => {
mockFeatureRepo.findById.mockResolvedValue({ id: '1', name: 'existing' });
const input = { name: 'existing', repoPath: '/tmp/repo' };
await expect(useCase.execute(input)).rejects.toThrow();
});
});
});
Run the test — it MUST fail (the use case doesn't exist yet):
pnpm test:single tests/unit/application/use-cases/create-feature.test.ts
Confirm you see import/compilation errors. This is RED.
Create the use case with just enough code to pass all tests:
// packages/core/src/application/use-cases/create-feature.ts
import { injectable, inject } from 'tsyringe';
import type { IFeatureRepository } from '../ports/output/repositories/feature-repository.interface';
export interface CreateFeatureInput {
name: string;
repoPath: string;
}
@injectable()
export class CreateFeatureUseCase {
constructor(
@inject('IFeatureRepository')
private readonly featureRepository: IFeatureRepository,
) {}
async execute(input: CreateFeatureInput): Promise<void> {
if (!input.name) {
throw new Error('Feature name is required');
}
const existing = await this.featureRepository.findById(input.name);
if (existing) {
throw new Error(`Feature "${input.name}" already exists`);
}
await this.featureRepository.create({
name: input.name,
repoPath: input.repoPath,
});
}
}
Run the test again — all tests MUST pass:
pnpm test:single tests/unit/application/use-cases/create-feature.test.ts
This is GREEN.
Add the binding in packages/core/src/infrastructure/di/container.ts:
import { CreateFeatureUseCase } from '@/application/use-cases/create-feature';
container.register(CreateFeatureUseCase, { useClass: CreateFeatureUseCase });
Use cases are typically registered as themselves (not behind an interface) since they're the API boundary.
Now clean up:
/mock-factorypnpm test:single tests/unit/application/use-cases/create-feature.test.ts # Tests pass
pnpm typecheck # Types clean
pnpm lint:fix # Lint clean
@injectable() and @inject() decoratorspnpm typecheck passes