Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
// core/prompts/classify.tsexportfunctionclassifyTicketPrompt(ticket: string): string {
return`Classify this support ticket into one of these categories:
- support: Technical issues or help requests
- sales: Pricing, plans, or purchase inquiries
- feedback: Suggestions or complaints
- other: Anything else
Respond with JSON:
{
"category": "...",
"confidence": 0.0-1.0,
"reasoning": "brief explanation"
}
Ticket:
${ticket}`;
}
// tests/llm/mocks/classify.mock.tsexportconst mockClassifyResponse = {
category: 'support',
confidence: 0.95,
reasoning: 'User is asking for help with login',
};
// tests/unit/services/ticket.test.tsimport { classifyTicket } from'../../../src/core/services/ticket';
import { mockClassifyResponse } from'../../llm/mocks/classify.mock';
// Mock the LLM client
vi.mock('../../../src/core/llm/client', () => ({
llmCall: vi.fn().mockResolvedValue(mockClassifyResponse),
}));
describe('classifyTicket', () => {
it('returns classification for ticket', async () => {
const result = awaitclassifyTicket('I cannot log in');
expect(result.category).toBe('support');
expect(result.confidence).toBeGreaterThan(0.9);
});
});
2. Fixture Tests (Deterministic, Tests Parsing)
// tests/llm/fixtures/classify.fixtures.json
{
"support_ticket": {
"input": "I can't reset my password",
"expected_category": "support",
"raw_response": "{\"category\":\"support\",\"confidence\":0.98,\"reasoning\":\"Password reset is a support issue\"}"
}
}
// tests/llm/classify.fixture.test.tsimport fixtures from'./fixtures/classify.fixtures.json';
import { ClassificationSchema } from'../../src/core/llm/schemas';
describe('Classification Response Parsing', () => {
Object.entries(fixtures).forEach(([name, fixture]) => {
it(`parses ${name} correctly`, () => {
const parsed = JSON.parse(fixture.raw_response);
const result = ClassificationSchema.parse(parsed);
expect(result.category).toBe(fixture.expected_category);
});
});
});
3. Evaluation Tests (Slow, Run in CI nightly)
// tests/llm/evals/classify.eval.test.tsimport { classifyTicket } from'../../../src/core/services/ticket';
constTEST_CASES = [
{ input: 'How much does the pro plan cost?', expected: 'sales' },
{ input: 'The app crashes when I click save', expected: 'support' },
{ input: 'You should add dark mode', expected: 'feedback' },
{ input: 'What time is it in Tokyo?', expected: 'other' },
];
describe('Classification Accuracy (Eval)', () => {
// Skip in regular CI, run nightlyconst runEvals = process.env.RUN_LLM_EVALS === 'true';
it.skipIf(!runEvals)('achieves >90% accuracy on test set', async () => {
let correct = 0;
for (const testCase ofTEST_CASES) {
const result = awaitclassifyTicket(testCase.input);
if (result.category === testCase.expected) correct++;
}
const accuracy = correct / TEST_CASES.length;
expect(accuracy).toBeGreaterThan(0.9);
}, 60000); // 60s timeout for LLM calls
});
GitHub Actions for LLM Tests
# .github/workflows/quality.yml (add to existing)jobs:quality:# ... existing steps ...-name:RunTests(withLLMmocks)run:npmruntest:coveragellm-evals:runs-on:ubuntu-latest# Run nightly or on-demandif:github.event_name=='schedule'||github.event_name=='workflow_dispatch'steps:-uses:actions/checkout@v4-name:SetupNodeuses:actions/setup-node@v4with:node-version:'20'-name:Installdependenciesrun:npmci-name:RunLLMEvalsrun:npmruntest:evalsenv:ANTHROPIC_API_KEY:${{secrets.ANTHROPIC_API_KEY}}RUN_LLM_EVALS:'true'