refactor: architecture compliance pass — DS tokens, hook boundary, god component split, AI hardening

- DS token migration: Anfragen.tsx + child components (AnfragenInquiryItem, AnfragenMessageBubble)
  fully migrated; DS_TEXT.brandDark added; scoreTheme.ts moved to src/lib/ with re-export proxy
- Hook boundary: Results.tsx no longer calls needService directly — routes through useNeeds()
  with optional refetchOnMount/gcTime overrides
- NewListing.tsx (440L) split into useNewListingForm hook + 8 section components under
  src/components/new-listing/; page shell reduced to 121 lines
- AI hardening: Zod .strict() on all schemas, AIProvenance extended with schemaVersion/
  fallbackReason/traceId/latencyMs, AITraceStore stats with p50/p90/p99 + failure breakdowns,
  MockAIService buildFollowUpQuestions with priority ordering + area-ambiguity detection,
  prompt templates updated (LIGHT_INDUSTRIAL, budget unit, ambiguity detection, decimal precision)
- Tests: all 154 passing; fixed test regression caused by OfferEmailResponseSchema body min(50)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-24 16:10:39 +02:00
parent e36c5bc979
commit e1f4beb898
44 changed files with 1610 additions and 1058 deletions
+10
View File
@@ -14,12 +14,20 @@ export interface AIProvenance {
generatedAt: string
/** Prompt version string used to generate this response */
promptVersion: string
/** Zod schema version used for validation */
schemaVersion: string
/** Whether the response is AI-only, mock-only, or a hybrid merge */
source: 'ai' | 'mock' | 'hybrid'
/** True when the original AI call failed and mock was substituted */
fallbackUsed: boolean
/** Human-readable reason why a fallback occurred — undefined when no fallback */
fallbackReason?: string
/** True when the AI response passed Zod schema validation */
validationPassed: boolean
/** Unique request ID — correlates AIResponse with AITrace.id */
traceId: string
/** Wall-clock latency for this call in milliseconds */
latencyMs?: number
}
/**
@@ -40,9 +48,11 @@ export function mockProvenance(overrides?: Partial<AIProvenance>): AIProvenance
model: 'mock',
generatedAt: new Date().toISOString(),
promptVersion: 'mock',
schemaVersion: 'mock',
source: 'mock',
fallbackUsed: false,
validationPassed: true,
traceId: crypto.randomUUID(),
...overrides,
}
}