Anti-Hallucination Rules
Agent Anti-Hallucination Rules
Source: FjordConsulting simulation test (2026-02-06) Findings: 75/100 accuracy — 25% hallucinated details
Rule 0: VERIFY BEFORE CLAIMING (NAJVAŽNIJE PRAVILO)
NIKAD ne tvrdi da nešto postoji ili ne postoji bez da PROVJERIS.
Prije nego kažeš "fajl ne postoji" → pokreni ls ili cat.
Prije nego kažeš "tool ne radi" → pokreni ga.
Prije nego kažeš "nema komunikacije" → provjeri kanal.
# ISPRAVNO: provjeri pa tvrdi
ls ~/path/to/file.txt # postoji? → ONDA reci "postoji"
cat ~/path/to/config.json # čitljiv? → ONDA reci šta piše
# POGREŠNO: tvrdi bez provjere
"Taj fajl ne postoji" # ← KAKO ZNAŠ? Jesi li pokrenuo ls?
"Sistem nije konfigurisan" # ← KAKO ZNAŠ? Jesi li provjerio?
Primjer greške (2026-02-06):
Edita tvrdila da 5 fajlova "ne postoji nigdje u Dropboxu" — ls na istoj mašini je pokazao da SVI postoje. Nije provjerila filesystem prije nego je donijela zaključak.
Pravilo: Ako nisi pokrenuo komandu koja DOKAZUJE tvoju tvrdnju — ne tvrdi.
Rule 1: TBD > Hallucination
If you don't know a specific value, write TODO: or TBD instead of inventing it.
NEVER invent:
- Cryptographic hashes, keys, or salts (write
// TODO: generate with bcrypt/openssl) - API names or algorithm names you're not 100% sure exist (write
// TODO: verify API exists) - Market prices, hourly rates, or budgets without source data (write
TBD — requires market research) - Framework-specific APIs without verification (write
// TODO: verify available in iOS X+) - Company names, contact emails, or legal citations without verification
ALWAYS mark uncertainty:
// TODO: verify — this API may not exist in iOS 17
// TBD: Norwegian developer hourly rate (estimate 800-1500 NOK/h, needs verification)
// PLACEHOLDER: replace with real bcrypt hash before deployment
Rule 2: Cross-File Consistency
Before writing code that references another file, READ that file first.
Mandatory checks:
- If you write a DB query with a status value → READ the schema CHECK constraint
- If you add a package.json dependency → IMPORT it somewhere or don't add it
- If you write an API spec endpoint → IMPLEMENT the route handler
- If you reference a type/enum → VERIFY it exists in the type definitions
Anti-pattern (caught in test):
// websocket.ts writes status='online'
// BUT schema.sql only allows: 'active', 'away', 'offline', 'deactivated'
// Result: runtime crash
Rule 3: No Phantom Dependencies
Every dependency in package.json / Package.swift MUST be:
- Actually imported in at least one source file
- Actually used (not just imported)
If you add a dependency for future use, comment it:
// "ioredis": "^5.4.2" // Phase 2: session caching — NOT YET IMPLEMENTED
Rule 4: Health Checks Must Be Real
Never hardcode health check responses. Always verify:
// BAD (caught in test):
return { database: 'up', redis: 'up' }; // lies
// GOOD:
const dbOk = await pool.query('SELECT 1').then(() => true).catch(() => false);
return { database: dbOk ? 'up' : 'down' };
Rule 5: Spec-Implementation Parity
If you write a specification (API spec, design doc), track implementation status:
## Endpoints
| Endpoint | Status |
|----------|--------|
| POST /auth/login | IMPLEMENTED |
| POST /auth/register | IMPLEMENTED |
| GET /groups | NOT YET IMPLEMENTED |
| POST /push/register | PHASE 2 |
Never present unimplemented features as done.
Rule 6: Budget and Timeline Reality Checks
When estimating costs or timelines:
- State assumptions explicitly ("assuming Norwegian senior developer at 1000-1200 NOK/h")
- If you don't have market data, write: "TBD — requires market research for [country/region]"
- Add 30-50% buffer to timeline estimates
- Never present optimistic estimates as realistic
Rule 7: Placeholder Code Must Scream
Mock implementations must be OBVIOUSLY fake:
// BAD (caught in test): looks like real encryption but is base64
func encrypt(_ data: Data) -> Data {
return data.base64EncodedData() // This is NOT encryption
}
// GOOD: impossible to miss
func encrypt(_ data: Data) -> Data {
fatalError("PLACEHOLDER: Real encryption not yet implemented. Integrate libsignal-client-swift before shipping.")
}
Rule 9: Config/Schema Changes Require Docs (dodano 2026-02-12)
ROOT CAUSE: John mijenjao hooks format u settings.json bez čitanja docs. Haiku validator potvrdio pogrešan format.
PRAVILA:
- NIKAD mijenjaj config format (hooks, settings, schema) bez čitanja oficijelne dokumentacije
- WebFetch/WebSearch OBAVEZAN za: hooks format, API schema, config migration, breaking changes
- Validator agent NIJE rubber stamp — mora imati docs URL ili spec file kao input
- Anti-pattern: "Provjeri da sam dobro uradio" bez davanja izvora istine agentu
Primjer greške (2026-02-12):
// POGREŠNO (John napisao):
"matcher": {} // objekt — Claude Code expects string
// ISPRAVNO (iz docs):
"matcher": "*" // regex string — matcha sve toolove
"matcher": "Bash" // regex string — matcha samo Bash
Workflow za config promjene:
1. WebFetch oficijelnu docs stranicu
2. Pročitaj schema/format
3. Tek onda mijenjaj fajl
4. Validator dobije docs URL kao input za nezavisnu provjeru
Rule 10: API Endpoint Verification (dodano 2026-04-04)
ROOT CAUSE: Builder agent hallucinated /upload endpoint for LightRAG when correct endpoint is /documents/text. Error passed through system without detection.
PRAVILA:
- NIKAD pretpostavi da HTTP endpoint postoji bez verifikacije
- Prije pisanja kod-a sa HTTP pozivom — provjeri
/healthili OpenAPI spec - Hallucination-detector hook blokira poznate pogrešne endpoint-e
- KNOWN_API_ENDPOINTS u
~/.claude/hooks/hallucination-detector.pyje source of truth
Poznati pogrešni endpoint-i (BLOCKED):
❌ /upload → ✓ /documents/text (LightRAG)
❌ /ingest → ✓ /documents/texts (LightRAG)
❌ /add → ✓ /documents/text (LightRAG)
Workflow za novi endpoint:
# 1. Provjeri existence
curl -s http://localhost:9621/health # Ako 404 → endpoint nije to
curl -s http://localhost:9621/openapi.json | grep "endpoint-path"
# 2. Ako postoji — dodaj u KNOWN_API_ENDPOINTS
# 3. Ako NE postoji — STOP, pitaj arhitektora
# 4. Tek onda koristi u kodu:
httpRequest('GET', 'http://localhost:9621/documents/text', null)
Hook blokada:
hallucination-detector.py check_phantom_endpoints()
└─ Skenira sve httpRequest/fetch/axios pozive
└─ Ako slijedi poznati invalid endpoint → EXIT(2) sa porukom
Hallucination Examples from Test
| What agent wrote | Reality | Root cause |
|---|---|---|
| "Sesame Algorithm" | Does not exist | Invented name for concept |
contentSecureLevel iOS 17 API |
Does not exist | Invented API |
bcrypt hash $2b$12$vJ4... |
Invalid hash | Generated random string |
| 150 NOK/h developer rate | Norway is 800-1500 NOK/h | No market context |
| Redis "up" in health check | Redis never connected | Hardcoded response |
status = 'online' |
DB enum has no 'online' | Didn't read schema |
| ReportCo AS "WON client" | Demo data, firma ne postoji | Test data bez is_test flag |
| FitLife AS "50K deal" | Demo data, firma ne postoji | Lead→WON bez ugovora |
| FjordConsulting "200K proposal" | Kontakt ne postoji u contacts.db | Phantom pipeline entry |
| Revenue plan 774K Q1 | Realno 544K (230K phantom) | Auto-generated bez review |
Rule 8: Demo/Test Data Protection (dodano 2026-02-11)
ROOT CAUSE: John kreirao demo podatke (FitLife, ReportCo) 2026-02-04 za AIOS testing. Bez oznake. Propagirali kroz leads→contacts→invoices→revenue plan kao REALNI klijenti 7 dana.
PRAVILA:
- NIKAD kreiraj test/demo podatke u production bazama bez jasne oznake
- Flag marking: Svaki test zapis MORA imati polje
is_test=trueili ekvivalent - Name prefix: Test firme MORAJU imati prefix
TEST:iliDEMO:u imenu - Email: Test kontakti koriste
@test.localdomenu, NIKAD realne domene - Human gate: Lead koji ide u WON stage MORA imati:
- Potpisan ugovor, ILI
- Eksplicitna potvrda od Alema
- Revenue plan: NIKAD auto-generate i publish — uvijek draft + human review
- Invoice kreacija: Zahtijeva referencu na potpisan ugovor ili Alem approval
- Contacts baza: Novi kontakt MORA imati verificiran email i dokumentovan source
- Cross-check: Prije uključivanja firme u revenue plan, verificiraj da postoji u contacts.db SA realnom komunikacijom
Ako kreiraš test data za demo:
# ISPRAVNO:
node contacts.js add "TEST: DemoFirma" "[email protected]" --notes "DEMO DATA for testing only"
# POGREŠNO:
node contacts.js add "ReportCo AS" "[email protected]" # izgleda realno, propagira