const agentDefinition = {
id: "test-driven-developer",
displayName: "Test-Driven Developer",
publisher: "emmanuelm",
version: "0.0.1",
model: "anthropic/claude-4-sonnet-20250522",
reasoningOptions: {
effort: "medium",
enabled: true
},
toolNames: [
"read_files",
"write_file",
"find_files",
"code_search",
"run_terminal_command",
"add_message",
"spawn_agents",
"end_turn"
],
spawnableAgents: [
"codebuff/reviewer@0.0.1"
],
inputSchema: {
params: {
type: "object",
required: [],
properties: {
srcDir: {
type: "string",
description: "Source directory (default: src/)"
},
testDir: {
type: "string",
description: "Directory for tests (default: tests/)"
},
verifyWithReviewer: {
type: "boolean",
description: "Spawn a reviewer subagent to check for overfitting (default: true)"
}
},
additionalProperties: false
},
prompt: {
type: "string",
description: "Feature or change to implement using strict test-driven development"
}
},
includeMessageHistory: true,
outputMode: "last_message",
spawnerPrompt: `Spawn to drive a TDD workflow: write tests first, confirm they fail, commit tests, implement code, iterate until green, optionally review for overfitting, then commit implementation.`,
systemPrompt: `You are a disciplined engineer practicing strict test-driven development. Use the project's package manager and test runner. Always write tests first, ensure they fail, then implement the minimal code to pass without changing the tests, iterating until all tests pass.`,
instructionsPrompt: `Follow this TDD loop:
(1) Write tests only (use your project's test framework, e.g., bun:test, vitest, jest), no implementation;
(2) Run tests via the appropriate command (e.g., bun test, bun run test, pnpm test, yarn test, npm test) and confirm failures;
(3) Commit tests;
(4) Implement minimal code to pass tests without modifying tests;
(5) Iterate running tests and updating code until green;
(6) Optionally verify with an independent reviewer;
(7) Commit implementation.`,
stepPrompt: `Stay in the TDD loop. Tests must not be modified after committing them. Use the appropriate test command for the project. Prefer small, focused commits.`,
handleSteps: function* ({ prompt, params }) {
const testDir = params?.testDir || "tests", srcDir = params?.srcDir || "src", verifyWithReviewer = typeof params?.verifyWithReviewer === "boolean" ? params?.verifyWithReviewer : !0;
yield {
toolName: "add_message",
input: {
role: "assistant",
content: `We are using strict TDD for: "${prompt}". First, write tests only (no implementation).
- Use your project's test framework (e.g., import from "bun:test", or use "vitest" / "jest").
- Place tests under ${testDir}/ or co-located __tests__ directories, filenames *.test.ts.
- Use clear input/output examples and cover edge cases.
- Do not create mock implementations or stubs of production code. Reference non-existent functions/classes and imports as needed; the implementation will be added later.`
},
includeToolCall: !1
};
yield "STEP";
yield {
toolName: "run_terminal_command",
input: {
command: `if command -v bun >/dev/null 2>&1; then if [ -f package.json ] && grep -q "\\"test\\"" package.json 2>/dev/null; then bun run test; else bun test; fi; elif [ -f pnpm-lock.yaml ]; then pnpm test; elif [ -f yarn.lock ]; then yarn test; elif [ -f package-lock.json ]; then npm test --silent; else if [ -f package.json ] && grep -q "\\"test\\"" package.json 2>/dev/null; then (pnpm test || yarn test || npm test --silent || bun run test); else echo 'No test script found'; exit 1; fi; fi`,
process_type: "SYNC",
timeout_seconds: 120
}
};
yield {
toolName: "add_message",
input: {
role: "assistant",
content: "Confirm at least one test failure. If no tests fail, refine the tests to capture the missing behavior, then run `bun test` again until there is a failing test."
},
includeToolCall: !1
};
yield "STEP";
yield {
toolName: "run_terminal_command",
input: {
command: 'git add -A && git commit -m "test: add tests for TDD goal"',
process_type: "SYNC",
timeout_seconds: 30
}
};
yield {
toolName: "add_message",
input: {
role: "assistant",
content: `Now implement the minimal code in ${srcDir}/ to pass the committed tests. Do not modify any test files. Iterate: update code, run the project's test command again, and repeat until all tests pass.`
},
includeToolCall: !1
};
yield "STEP_ALL";
if (verifyWithReviewer) {
yield {
toolName: "add_message",
input: {
role: "assistant",
content: "Requesting an independent review to ensure the implementation does not overfit the current tests. Please suggest any additional edge-case tests if necessary."
},
includeToolCall: !1
};
yield {
toolName: "spawn_agents",
input: {
agents: [
{
agent_type: "codebuff/reviewer@0.0.1",
prompt: `Review for overfitting relative to the current tests for: "${prompt}". If gaps exist, propose additional tests or edge cases.`
}
]
}
};
yield {
toolName: "add_message",
input: {
role: "assistant",
content: "If the reviewer suggests essential additional tests, add them first, confirm they fail, implement minimally again, and iterate until all tests pass."
},
includeToolCall: !1
};
yield "STEP_ALL";
}
yield {
toolName: "run_terminal_command",
input: {
command: `if command -v bun >/dev/null 2>&1; then if [ -f package.json ] && grep -q "\\"test\\"" package.json 2>/dev/null; then bun run test; else bun test; fi; elif [ -f pnpm-lock.yaml ]; then pnpm test; elif [ -f yarn.lock ]; then yarn test; elif [ -f package-lock.json ]; then npm test --silent; else if [ -f package.json ] && grep -q "\\"test\\"" package.json 2>/dev/null; then (pnpm test || yarn test || npm test --silent || bun run test); else echo 'No test script found'; exit 1; fi; fi`,
process_type: "SYNC",
timeout_seconds: 120
}
};
yield {
toolName: "run_terminal_command",
input: {
command: 'git add -A && git commit -m "feat: implement functionality to pass TDD tests"',
process_type: "SYNC",
timeout_seconds: 30
}
};
}
}