Regression Testing for Claude Code Skills
Automated verification that Claude Code uses correct Base44 APIs
instead of hallucinating Firebase / Supabase patterns
Without skill documentation, Claude falls back to pre-training patterns
| API | Correct (Base44) | Hallucinated |
|---|---|---|
| Create record | entities.Product.create(data) |
Product.insert(data) |
| Filter records | entities.Product.filter(query) |
Product.find(query) / .where() |
| Auth login | loginViaEmailPassword(email, pw) |
signInWithEmailAndPassword() |
| OAuth provider | loginWithProvider('google') |
signInWithGoogle() |
| SDK import | import { ... } from "@base44/sdk" |
import { ... } from "firebase" |
| Config init | createClient({ appId }) |
initializeApp({ apiKey }) |
Every change to skill documentation is tested against 16 fixtures and 30+ prompts. Catch regressions before they ship.
Compare documentation approaches (AGENTS.md format, verbosity level, context priming) to find the most effective strategy.
Run the same fixture N times to measure how reliably Claude produces correct output. Quantify flakiness.
src/experiments.ts → src/setup.ts → src/runner.ts → src/checks/ → src/compare-runner.ts
Experiment injection:
setup.ts copies experiment's skills/ into each fixture's project/skills/CLAUDE.md and AGENTS.md copied from experiment dir if presentAt runtime:
/tmp/eval-*project/{
"$schema": "../../eval.schema.json",
"name": "anti-hallucination",
"description": "Verify correct Base44 APIs, block hallucinated patterns",
"prompts": [
{
"name": "anti-hallucination-auth",
"prompt": "Create a React login page with email/password login,
Google OAuth, registration, and logout...",
"expectedSkills": ["base44-sdk"],
"checks": [
{
"type": "file-exists",
"description": "Login component created",
"filePath": "src/components/Login.jsx"
},
{
"type": "file-content",
"description": "Uses loginViaEmailPassword",
"filePath": "src/components/Login.jsx",
"pattern": "loginViaEmailPassword"
},
{
"type": "file-content-excluded",
"description": "No Firebase signIn pattern",
"filePath": "src/components/Login.jsx",
"pattern": "signInWithEmailAndPassword"
}
]
}
]
}
The three-check pattern: file-exists → file-content (correct API) → file-content-excluded (hallucinated API)
file-exists — Verify a file was created at the expected pathfile-content — Assert a regex pattern exists in a filefile-content-excluded — Assert a pattern does NOT appear in a filecontains — Check agent stdout for a substringvalid-json — Verify a file contains parseable JSONcommand-passes — Run a shell command, assert exit code 0json-schema — Validate file contents against a JSON Schemaentity-config — Validate entity schema: PascalCase name, type:object, properties, requiredagent-config — Validate agent schema: snake_case name, instructions, tool_configsfunction-def — Validate function config: name + entry (not entrypoint)| Feature | baseline | agents-md | agents-md -combined |
verbose -index |
context -first |
|---|---|---|---|---|---|
| SKILL.md files | — | ✓ | ✓ | ✓ | ✓ |
| AGENTS.md API index | — | ✓ | ✓ | ✓ | ✓ |
| CLAUDE.md priming | — | — | ✓ | — | ✓ |
| Expanded signatures | — | — | — | ✓ | — |
| Retrieval-led reasoning hint | — | — | ✓ | — | ✓ |
| Common Mistakes section | — | ✓ | ✓ | ✓ | ✓ |
--concurrency flag
5 experiments × 16 fixtures (45 expanded prompts)
| Experiment | Passed | Failed | Pass Rate |
|---|---|---|---|
| agents-md-combined | 38 | 7 | 84% |
| agents-md-context-first | 36 | 9 | 80% |
| agents-md | 34 | 11 | 76% |
| agents-md-verbose-index | 32 | 13 | 71% |
| baseline | 21 | 24 | 47% |
bestExperiment: agents-md-combined
CLAUDE.md retrieval priming + AGENTS.md compact index = highest pass rate. Verbose signatures did not help — more docs != better results.
Multi-prompt fixtures expand to 30+ individual test prompts.
Each prompt has its own expectedSkills and checks[].
mkdir evals/fixtures/my-new-fixture
# $schema gives autocomplete in VS Code
cat > evals/fixtures/my-new-fixture/eval.json
mkdir -p evals/fixtures/my-new-fixture/project/src
# Add any starter code the agent needs
# project/ becomes the agent's working directory
cd evals
npm run eval -- --fixtures my-new-fixture --verbose
Reference eval.schema.json with "$schema": "../../eval.schema.json" for IDE validation and autocomplete.
cd experiments/my-experiment/skills/base44-sdk
ln -s ../../../../../skills/base44-sdk/references references
cd evals
npm run eval:compare
# Edit skills/base44-sdk/SKILL.md, then:
cd evals && npm run eval -- --verbose
Run all fixtures against the current skill documentation
cd evals && npm run eval:compare
# Runs all experiments x all fixtures
# Outputs pass/fail matrix + bestExperiment
Find which AGENTS.md format produces the highest pass rate
cd evals && tsx src/run-repeated.ts --runs 5 \
--fixtures anti-hallucination --verbose
Run the same fixture N times to measure flakiness and consistency
Claude's pre-training data contains far more Firebase/Supabase patterns than Base44 APIs. Without skill documentation, it hallucinates wrong method names, wrong imports, and wrong auth flows.
16 fixtures with 30+ prompts that verify correct API usage and reject hallucinated patterns. Each fixture uses the three-check pattern: file exists, correct API present, hallucinated API absent.
npm run eval before merging to catch regressions in documentation that cause hallucinations.
Skills that pass evals → fewer hallucinations in production → users get working code on the first try.