ワンクリックで
tdd
Enforce test-driven development with RED→GREEN→REFACTOR cycle and coverage validation
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Enforce test-driven development with RED→GREEN→REFACTOR cycle and coverage validation
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Run an HQ-issued Slack bot — arm a per-bot @-mention watcher that spawns an autonomous Claude worker per mention. Pass the bot's slug (e.g. `hassaan`), a scope flag (`-c <company-slug>` or `--personal`), and optionally a workspace (`-w <slack-team-domain>`; auto-derived for `--personal` from SLACK_CREDENTIALS_JSON). The watcher resolves scope/workspace before personUid, using the sole local cache entry or an exact selected-vault bot-token namespace match; pass `-u <prs_…>` to override. It verifies and injects scoped `ANTHROPIC_API_KEY` into detached workers, handles the one-time bypass-permissions gate, resolves `<personUid>/HQ_SLACK_BOT_TOKEN_<NAME>_<WORKSPACE>`, infers the creator's Slack user_id (used as a DM gate), enumerates channels, and dispatches workers. Workers respond in-thread, ignore DMs from non-creators, and never call AskUserQuestion.
Surface architectural friction and propose deepening opportunities — turn shallow modules into deep ones for better testability and AI-navigability. Output: ranked candidate list with deletion-test outcome, leverage/locality scoring, file refs. Never edits code directly; presents candidates and walks the user through grilling-style design decisions for picked candidates. Use when the codebase is hard to change, when /diagnose hands off "no good test seam," or when planning a refactor wave.
Shared vocabulary and discipline for designing deep modules (a lot of behaviour behind a small interface, at a clean seam). Use when designing module boundaries or interfaces, or when another skill needs the deep-module vocabulary. Triggers on "deep module", "interface design", "design it twice".
Disciplined diagnosis loop for hard bugs, performance regressions, and intermittent failures. Build a deterministic feedback loop FIRST, then reproduce → hypothesise (3-5 ranked) → instrument (one variable at a time, tagged probes) → fix at the correct seam → cleanup + post-mortem. Use when the dominant problem is "I cannot reliably reproduce or measure this." For bugs that reproduce reliably with unknown root cause, use /investigate instead.
Actively build and sharpen a project's domain model — challenge fuzzy or overloaded terms against a glossary, stress-test with edge cases, and maintain CONTEXT.md as the source of truth for a ubiquitous language. Use when the user wants to pin down domain terminology, resolve a naming conflict, define a ubiquitous language, or when another skill needs to produce or sharpen the domain model. Triggers on "what should we call this", "domain model", "ubiquitous language", "define these terms", "update CONTEXT.md".
Break a plan, spec, or conversation into tracer-bullet vertical-slice tickets, each declaring its blocking edges (dependency order). Use when you have a plan/spec/PRD and need it decomposed into independently-executable tickets. Triggers on "break into tickets", "slice this into tasks", "vertical slices", "tracer bullets".
| name | tdd |
| description | Enforce test-driven development with RED→GREEN→REFACTOR cycle and coverage validation |
| allowed-tools | Read, Write, Edit, Bash, Glob, Grep |
Develop a feature using strict test-driven development: write failing tests first, implement minimal code, refactor, and verify coverage.
What a good test is: tests verify behavior through public interfaces, read like a specification, and survive refactors.
Task description: $ARGUMENTS
RED → GREEN → REFACTOR → REPEAT
A seam is the public boundary you test at: the interface where you observe behavior without reaching inside. Tests live at seams, never against internals.
Test only at pre-agreed seams. Before writing any test, write down the seams under test and confirm them with the user. No test is written at an unconfirmed seam. You can't test everything — agreeing the seams up front is how testing effort lands on the critical paths and complex logic instead of every edge case.
Ask: "What's the public interface, and which seams should we test?"
Auto-detect the test framework and package manager from the project:
Package managers (check in priority order):
bun.lockb → bun testpnpm-lock.yaml → pnpm testyarn.lock → yarn testpackage-lock.json → npm testCargo.lock → cargo testgo.mod → go test ./...Test frameworks (infer from project files):
package.json with jest → Jest (Node/TypeScript)package.json with vitest → Vitest (Vite-based)pyproject.toml or requirements.txt → pytest (Python)go.mod → Go's testing packageCargo.toml → Rust's built-in test frameworkIf no framework detected: Ask the user which test framework and runner to use. Do not proceed without a confirmed test runner.
Store the detected runner as {TEST_CMD} (e.g., bun test, pnpm test, pytest) and use it for all subsequent test commands in this workflow.
Report detected framework and package manager to the user before proceeding.
Create the function/class definition with empty implementation:
Example (TypeScript):
/**
* Validates an email address format.
* @param email - The email string to validate
* @returns true if email is valid, false otherwise
* @throws Error if email is null/undefined
*/
export function validateEmail(email: string): boolean {
throw new Error('Not implemented');
}
Read <repo>/CONTEXT.md if present so test names and interface vocabulary match the project's domain language (ties into /domain-modeling).
Write comprehensive test suite BEFORE implementation:
Test types to include:
Requirements:
Example test structure (Jest/Vitest):
describe('validateEmail', () => {
describe('happy path', () => {
it('accepts valid email addresses', () => {
expect(validateEmail('user@example.com')).toBe(true);
expect(validateEmail('test.name+tag@domain.co.uk')).toBe(true);
});
});
describe('edge cases', () => {
it('rejects empty string', () => {
expect(validateEmail('')).toBe(false);
});
it('rejects email without @', () => {
expect(validateEmail('invalidemail.com')).toBe(false);
});
it('rejects email without domain', () => {
expect(validateEmail('user@')).toBe(false);
});
it('rejects email with spaces', () => {
expect(validateEmail('user @example.com')).toBe(false);
});
it('handles special characters', () => {
expect(validateEmail('user+tag@example.com')).toBe(true);
expect(validateEmail('user.name@sub.domain.com')).toBe(true);
});
});
describe('error conditions', () => {
it('throws error if email is null', () => {
expect(() => validateEmail(null as any)).toThrow();
});
it('throws error if email is undefined', () => {
expect(() => validateEmail(undefined as any)).toThrow();
});
it('rejects excessively long email', () => {
const longEmail = 'a'.repeat(255) + '@example.com';
expect(validateEmail(longEmail)).toBe(false);
});
});
});
Run tests and verify RED:
{TEST_CMD} # Use the detected test runner from Step 1
# Expected: ALL tests FAIL (red output)
# If ANY test passes, you haven't written the test correctly — fix it before proceeding
Write only the minimum code needed to pass the tests:
Example minimal implementation:
export function validateEmail(email: string): boolean {
if (email === null || email === undefined) {
throw new Error('Email cannot be null or undefined');
}
if (email.length === 0 || email.length > 254) {
return false;
}
// Basic email regex pattern
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
Run tests and verify GREEN:
{TEST_CMD} # Use the detected test runner from Step 1
# Expected: ALL tests PASS (green output)
Improve code quality while keeping tests green:
Requirements:
/review rather than expanding this cycle.Example refactored implementation:
const EMAIL_MAX_LENGTH = 254;
const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
/**
* Validates an email address format following RFC 5321 basic rules.
* @param email - The email string to validate
* @returns true if email matches expected format, false otherwise
* @throws Error if email is null or undefined
*/
export function validateEmail(email: string): boolean {
if (email == null) {
throw new Error('Email cannot be null or undefined');
}
if (email.length === 0 || email.length > EMAIL_MAX_LENGTH) {
return false;
}
return EMAIL_PATTERN.test(email);
}
Run tests after EACH refactoring step:
{TEST_CMD} # Use the detected test runner from Step 1
# Expected: ALL tests still PASS (green output)
# Refactor one concern at a time. Stop when code is clean and readable.
Check code coverage and add tests for any uncovered paths:
Coverage requirements by code type:
| Code Type | Minimum Coverage |
|---|---|
| Standard application code | 80% |
| Financial calculations | 100% |
| Authentication/authorization | 100% |
| Security-critical code | 100% |
| Encryption/decryption | 100% |
Run coverage check:
# Jest
npm test -- --coverage
# Vitest
npx vitest run --coverage
# pytest
pytest --cov=. --cov-report=term-missing
# Go
go test -cover ./...
# Rust
cargo tarpaulin --out Html
Acceptance criteria:
If coverage is below target:
$ npm test
FAIL src/email-validator.test.ts
validateEmail
happy path
✕ accepts valid email addresses (0ms)
✕ accepts variation formats (1ms)
edge cases
✕ rejects empty string (0ms)
✕ rejects email without @ (1ms)
✕ rejects email without domain (0ms)
✕ rejects email with spaces (0ms)
✕ handles special characters (1ms)
error conditions
✕ throws error if email is null (0ms)
✕ throws error if email is undefined (0ms)
✕ rejects excessively long email (0ms)
Tests: 0 passed, 10 failed, 10 total
$ npm test
PASS src/email-validator.test.ts
validateEmail
happy path
✓ accepts valid email addresses (2ms)
✓ accepts variation formats (1ms)
edge cases
✓ rejects empty string (0ms)
✓ rejects email without @ (0ms)
✓ rejects email without domain (1ms)
✓ rejects email with spaces (0ms)
✓ handles special characters (1ms)
error conditions
✓ throws error if email is null (0ms)
✓ throws error if email is undefined (0ms)
✓ rejects excessively long email (0ms)
Tests: 10 passed, 10 total (18ms)
$ npm test -- --coverage
------------|----------|----------|----------|----------|-------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered |
------------|----------|----------|----------|----------|-------------|
All files | 100 | 100 | 100 | 100 | |
email-...ts | 100 | 100 | 100 | 100 | |
------------|----------|----------|----------|----------|-------------|
beforeAll side effects)xit() or .skip — fix the test or remove itexpect(add(a, b)).toBe(a + b), or a snapshot derived by hand the same way) — it passes by construction and can never disagree with the code. Expected values must come from an independent source of truth (a known-good literal, a worked example, the spec).# Run all tests
npm test
# Run tests in watch mode
npm test -- --watch
# Run coverage
npm test -- --coverage
# Run specific test file
npm test email-validator.test.ts
# Run all tests
npx vitest run
# Run tests in watch mode
npx vitest
# Run coverage
npx vitest run --coverage
# Run specific test file
npx vitest email-validator.test.ts
# Run all tests
pytest
# Run tests in watch mode
pytest --lf (runs last-failed)
# Run coverage
pytest --cov=. --cov-report=term-missing
# Run specific test file
pytest tests/test_email_validator.py
# Run all tests
go test ./...
# Run with verbose output
go test -v ./...
# Run coverage
go test -cover ./...
# Run specific test
go test -run TestValidateEmail ./...
# Run all tests
cargo test
# Run tests in release mode
cargo test --release
# Run with coverage (requires tarpaulin)
cargo tarpaulin --out Html
# Run specific test
cargo test validate_email
After completing the TDD workflow, verify: