Algolia-Central

Documentation/03-Files-Reference.md

03 — Files Reference

Last updated: 2026-04-17. Exports verified via grep across the repo. Line counts verified via wc -l.

Every file in the ALIVE call graph, catalogued. For any file listed here, you should be able to answer: what does it do, what does it export, who calls it, and is it fully alive or has dead regions.


Legend

  • ALIVE — fires in every live trace run
  • CONDITIONAL — fires on specific branch (handoff, pricing injection, etc.)
  • DEAD — exported, not called (removed in Steps 1–2 where noted)
  • LEGACY — Pre-RC2 artifact; should be deleted in a later step

Entry Layer — api-src/

api-src/search.ts — 358 lines — ALIVE

The single HTTP entry point. Vercel serverless handler. All requests land here.

Exports: - default function handler(req, res) — the entry

What it does (top-to-bottom): 1. CORS + security headers 2. checkRateLimit(clientId)lib/security/rate-limiter 3. checkCircuit()lib/security/circuit-breaker 4. Input validation (query, history, length ≤ 2000) 5. Dynamic import of igniteMaverick, igniteSpecialist from lib/search/orchestrator 6. Branch A: consent === trueigniteSpecialist({trigger:'execute'}) (lines 193–260) 7. Branch B: isSpecialist(persona)igniteSpecialist({trigger}) (lines 272–280) 8. Branch C: default → igniteMaverick() (lines 282–288) 9. Wires the returned ReadableStream to res.write() for SSE streaming

Known issue: Branches A and B/C duplicate ~60 lines of stream plumbing — F-027 cleanup target in Step 5.

api-src/diag.ts — diagnostic endpoint — ALIVE (low-traffic)

Diagnostic endpoint at /api/diag. Returns system health. Rarely hit.

api-src/health.ts — health check endpoint — ALIVE (low-traffic)

/api/health. Returns 200 for uptime monitors.


Orchestration Layer — lib/search/

orchestrator.ts — 833 lines — ALIVE

The conductor. Both igniteMaverick and igniteSpecialist live here. All pipeline step emissions happen here.

Exports: - async function igniteMaverick(input, sessionId, requestId): Promise<ReadableStream> — line 45 - async function igniteSpecialist(input, sessionId, requestId): Promise<ReadableStream> — line 611 - function buildAgentStudioMessage(params): string — internal helper (line 789), not exported but ALIVE

What each does: see 02-Data-Flow for the step-by-step trace. Full call graph there.

Known issues: - F-026 — merge logic at line 116–128 uses || operator, never accepts user corrections - F-027 — 3-layer handoff routing (regex → keyword → STRONG_BRUNO_SIGNALS override) at line 443–502 - F-038 — specialist path does NOT instantiate InlineStreamAuditor (specialist stream is not audited for hallucination)


signal_extractor.ts — 288 lines — ALIVE

Extracts 8 signals from user query via Gemini.

Exports: - async function extractSignals(input, sessionState, requestId) — line 172 — the primary LLM call - function detectChipAnswer(query) — line 285 — maps user chip clicks (e.g., "e-commerce") to signal field/value pairs via the CHIP_SIGNAL_MAP constant (line 21)

Returns:

{
  intent: string,
  onion_signals: { stack, scale, role, pain },
  entities: { brand, industry, product, architecture_concepts[] },
  search_query, keyword_query,
  discovery_question: { field, question },
  filters: string[]
}

LLM: uses getBrainPrompt() from prompts/brain.ts via getLLMProvider().

Observed timing: 1800–2000ms. P-1 target — parallelize with retrieval.


discovery_analyzer.ts — 209 lines — ALIVE

Tracks discovery state: how many signals locked, what's missing, when to qualify.

Exports: - interface DiscoveryAnalysisResult — line 15 - function analyzeDiscoveryState(sessionState, askedSignals, query, turnCount, intent) — line 36 — PRIMARY - function generateExpandedContextQuery(...) — line 165 — CONDITIONAL (used by retrieval_orchestrator) - function generateDossierSummary(rawState, lockedSignals): string — line 190 — used by orchestrator to build dossier for UI + prompt

Known issue (F-035): qualification threshold too high — requires turn_count ≥ 4 AND lockedSignals reaching saturation before isQualified=true fires. Step 3 fix: relax to lockedSignals ≥ 6 AND has pain signal.


discovery_question_validator.ts — 273 lines — DEPRECATED / PARTIAL ALIVE

Legacy discovery-question generator. Largely superseded — generateNextDiscoveryQuestion() was consolidated into signal_extractor.ts (single LLM call).

Exports: - interface ValidationResult — line 18 - async function generateContextualDiscoveryQuestion(...) — line 34 — still used by stream_processor.ts zombie prevention path - interface DiscoveryQuestionResult — line 113 - async function generateNextDiscoveryQuestion(...) — line 132 — NOT in the main ALIVE path (consolidated); still exported for potential zombie use

Status: one path alive (zombie prevention), one path dead. Review in Step 5.


retrieval_orchestrator.ts — 627 lines — ALIVE

Runs search against Algolia (Atlas + NeuralSearch). Manages the three strategies.

Exports: - interface RetrievalOptions — line 21 - interface RetrievalResult — line 44 - async function orchestrateRetrieval(options): Promise<RetrievalResult> — line 113 — PRIMARY - function injectPricingIfNeeded(query, concepts, chunks) — line 532 — CONDITIONAL - async function fetchGoldenMap(): Promise<any[]> — line 570 — loads Atlas, cached 60s

Strategies (returned in result.strategy): - filtered — constrained by signal-derived filters - relaxed — no filters, broader net (~1100–1600ms) - fallback — last resort

Known dead regions (still in file — Step 4 cleanup): - atlas_guided strategy (line 48 union) — declared but never returned (DEAD, removed in Step 1) - optionalFilters boost logic (line 268–312) — uses <score=N> syntax that Algolia v5 silently ignores - VERTICAL_SYNONYM_MAP (line 273–308) — 2× duplicate boosts, no trace evidence - Reverse Atlas lookup (line 393–427) — rarely fires

Known issue (F-039): No recency signal — blog posts from 2022–2024 surfaced equally with 2025–2026 content.


chunk-merger.ts — 40 lines — ALIVE (minimal)

Formats Algolia hits for LLM prompt injection. Was 217 lines pre-Step-1; stripped to just the ALIVE function.

Exports: - function formatHitsForLLM(hits: any[]): string — line 5

Removed in Step 1: processSearchResults, mergeChunkedRecord, formatHitsForSources, ChunkedHit, MergedHit (5 dead items).


stream_processor.ts — 425 lines — ALIVE (Maverick only)

Maverick streaming + inline auditing + zombie prevention.

Exports: - interface StreamOptions — line 26 - interface StreamResult — line 45 - async function streamMaverickResponse(options): Promise<StreamResult> — line 60 — PRIMARY - class StatefulStreamStripper — line 343 — ALIVE (used by agent-studio/stream-adapter.ts to strip Agent Studio's XML control tags)

What streamMaverickResponse does: 1. Instantiates new InlineStreamAuditor(contextSources, products) at line 82 2. Loops Gemini SSE chunks; buffers until paragraph boundary 3. Runs each paragraph through inlineAuditor.auditParagraph(paragraphBuffer) — this is where hallucinated sentences get stripped and dead links get dropped 4. Writes cleaned paragraph to SSE as event: chunk {content} 5. Detects zombie/handoff markers; may inject transition text 6. Post-stream: runs ContentAuditor.auditContent() for link HEAD checks only (tone/grounding methods deleted in Step 2)

Known issue: ONLY Maverick calls this. Specialist stream bypasses it — F-038.


content_auditor.ts — 573 lines — ALIVE (mixed)

The audit classes. Heavy cleanup in Step 2.

Exports (post-Step-2): - interface AuditConfig — line 41 - interface LinkAuditResult — line 52 - interface AuditResult — line 63 - class ContentAuditor — line 113 — post-stream orchestrator (now does HEAD checks only after Step 2) - class InlineStreamAuditor — line 375 — THE HALLUCINATION GUARD

Deleted in Step 2 (~750 lines of theater): - checkPersonaCompliance() — was logged, never enforced - checkSourceGrounding() — duplicate of InlineStreamAuditor.auditGrounding - computeConfidence() — score never gated response - persistAuditResult() — fire-and-forget Redis write never read back - Forbidden phrase lists (UNIVERSAL_FORBIDDEN, MAVERICK_RULES, ELENA_RULES, BRUNO_RULES, PERSONA_RULES_MAP)

See 08-Audit-Pipeline for full behavior.


audit.ts — 308 lines — ALIVE (pure functions)

Stateless audit primitives used by both audit classes. Core to the hallucination guard.

Exports: - Constants: ALLOWED_HOSTNAMES (25), WHITELISTED_PATHS (37), TECHNICAL_FALLBACK_URL_MAP (40), CUSTOMER_STORY_PATH_PATTERNS (58), HALLUCINATED_CUSTOMER_SENTINEL (61), GENERIC_LINK_LABELS_PATTERN (64) - function isAllowedHostname(url) — line 71 - function canonicalizeUrl(url) — line 80 - function isTechnicalDocUrl(url) — line 90 - type LinkDecision — line 104 — the classification output - interface ClassifyContext — line 110 - function findCanonicalCustomerUrl(label, mapData, sources) — line 119 - function classifyLink(label, url, ctx): LinkDecision — line 159 — THE KEY CLASSIFIER — decides keep/replace/strip for every link - function applyDecision(label, fullMatch, decision) — line 211 - function formatTraceLine(label, url, decision) — line 224 — produces the [AUDIT] KEEP | ... console log lines - function htmlAnchorsToMarkdown(content) — line 245 - function upgradeGenericLinkLabels(content, sources) — line 256 — F-031 lives here (double | Algolia suffix) - function stripDanglingAttributions(content) — line 269 - function stripHallucinatedCustomerSentences(content) — line 300

Step 3 additions planned: - validateCustomerClaim(sentence, sources) — for F-038 (verify customer+metric+link combo) - Extension to classifyLink for recency check (F-039)


persona_loader.ts — 504 lines — ALIVE (with dead regions)

Loads persona definitions from YAML/config. Caches in memory.

Exports: - interface PersonaDefinition — line 22 - async function loadPersonaDefinition(persona) — line 402 - function formatPersonaForPrompt(persona) — line 419 - function validatePersonaCompliance(persona, content) — line 452 — theater (logs, doesn't enforce; F-029 fix will make it real in Step 6) - function invalidatePersonaCache() — line 500

Dead inside: parseMaverick, parseElena, parseBruno (lines 149–219) — 71 lines of near-identical code. Step 6 = template parsePersona(name, section). Dead constants: forbidden phrase lists (332–389) — never enforced. Step 6 = delete or wire to validator.


persona_routing.ts — 37 lines — ALIVE

Canonical persona ID mapping and routing check.

Exports: - const PERSONA_IDS = {...} — line 8 - type PersonaID — line 14 - function normalizePersonaID(raw) — line 24 — maps "solutions_engineer" → "elena", etc. - function isSpecialist(persona) — line 34 — persona in ['elena', 'bruno']


redis.ts — ~340 lines — ALIVE

Session state storage layer. Upstash Redis REST client.

Exports: - interface SessionState — line 20 — THE authoritative schema for session persistence (see 09-Session-State) - const getRedisConfig — line 52 - const executeRedisCommand(command) — line 67 — raw REST wrapper - const getSessionState(sessionId) — line 105 — loads with defaults - const getDefaultSessionState() — line 166 - const updateSessionState(sessionId, updates) — line 189 — partial update - const countLockedSignals(state) — line 225 — counts non-null signal fields (used by qualification) - const addAskedSignal(sessionId, signal) — line 245 — records signal asked this turn - const resetSessionState(sessionId) — line 270 - const deleteSessionState(sessionId) — line 285 - const incrementCounter(name, ttl) — line 299 - const setCache(name, value, ttl) — line 313 - const getCache(name) — line 324


algolia_client.ts — 45 lines — ALIVE

Thin Algolia SDK wrapper. Post-Step-1 cleanup (removed dead testConnection).

Exports: - function getAlgoliaClient() — line 16 — returns Algolia v5 client - function getIndexName() — line 41 — returns the configured NeuralSearch index name


insights.ts — ~120 lines — ALIVE

Algolia Insights event tracking.

Exports: - function getInsightsClient() — line 18 - async function trackView(params) — line 46 — fires on retrieval (non-blocking) - async function trackClick(params) — line 81 — fires on result click (client-triggered)


metadata_manager.ts — 443 lines — ALIVE

Post-generation processing + final event construction.

Exports: - interface Source, DiscoveryHistoryEntry, MetadataUpdateOptions, MetadataResult, FinalEventOptions — types - async function processPostGenerationMetadata(options) — line 98 — word count, unique sources, history update - function mapSourceType(source) — line 248 - function constructFinalEvent(options) — line 315 — assembles the event: final payload


pipeline-logger.ts — 242 lines — ALIVE

Dual-emit logging: server console + SSE pipeline_step events.

Exports: - interface StepLogEntry — line 20 - class PipelineLogger — line 28 — methods: step(), turnSnapshot(), finish()

P-8 target: drop dual-emit in production (SSE only, keep dev console via flag).


telemetry.ts — ~200 lines — ALIVE

Writes per-session turn records to Redis for analytics.

Exports: - interface TelemetryTurn, HandoffContext, SessionTelemetry — types - async function persistSessionTelemetry(sessionId, turns, state, handoff, chunkCount, status) — line 93 - async function getSessionTelemetry(sessionId) — line 161 - async function deleteSessionTelemetry(sessionId) — line 189


domain_guardrails.ts — ~200 lines — ALIVE

Intent validation + persona validation.

Exports: - Constants: NON_TECHNICAL_BLOCKERS, TECHNICAL_MARKERS, DOMAIN_TERMS - function guardIntent(query, currentIntent) — line 110 — may override LLM intent - type Persona — line 147 - function validatePersona(persona) — line 159 — guards against injected persona values - function routeIntentToPersona(intent, ...) — line 178


question_expander.ts — ~80 lines — ALIVE (partial)

Keyword-based handoff router.

Exports: - function determineHandoffTarget(sessionState, query) — line 16 — scores query against Bruno vs Elena keywords


gemini.ts — ~25 lines — KEPT (test-only)

Legacy gemini SDK helper. Superseded by getLLMProvider() abstraction but kept for performance-benchmark.test.ts.

Exports: - function getGenAI() — line 9 — STILL ALIVE via test harness


utils.ts — ~80 lines — ALIVE

Misc utilities.

Exports: - async function retryWithBackoff(fn, options) — line 13 - async function sleep(ms) — line 39 - function sanitizeQuery(query) — line 46 - function mapSourceType(options) — line 54


Prompts Layer — lib/search/prompts/

prompts/maverick.ts — ALIVE

Assembles the Maverick system prompt.

Exports: - async function buildMaverickPromptWithPersona(dossierSummary, contextSources, discoveryInstructions, turnCount, isStrictDiscovery): Promise<string> — line 12

Produces a 16KB baseline system prompt. Known to spike to 157KB (F-006). Step 4c investigation.

F-032 suspect: contains a Namedrop template instruction that leaks verbatim into the UI.


prompts/brain.ts — ALIVE

The signal extractor prompt (confusingly named "brain").

Exports: - const BRAIN_PROMPT_VERSION = "8.5.1-..." — line 8 - const ROUTER_SYSTEM_PROMPT — line 13 - type BrainOutput — line 39 — the JSON shape the Brain LLM must return - function getBrainPrompt(currentDate) — line 66 — returns the full signal-extraction prompt with today's date inserted

Used by signal_extractor.extractSignals().


prompts/integrity.ts — ALIVE (CONDITIONAL)

Integrity audit prompt — used by ContentAuditor.checkSourceGrounding BEFORE Step 2. After Step 2, file may be dead. Verify in Step 3.

Exports: - INTEGRITY_PROMPT_VERSION, INTEGRITY_AUDIT_PROMPT, INTEGRITY_MODEL_CONFIG - function formatChunksForAudit(chunks) — line 94 - function getIntegrityAuditPrompt(userQuery, chunks) — line 113 - interface ConstraintReport, IntegrityAudit — types - function parseAuditResponse(response) — line 141 - function formatWarningsForArchitect(audit) — line 172

[UNVERIFIED post-Step-2] — run grep for callers, may all be dead now.


prompts/fallback.ts, prompts/casual.ts, prompts/consultant.ts, prompts/squad.ts, prompts/support.ts, prompts/se.ts — MIXED

Legacy persona prompts. Need to verify which are still referenced after Step 2 cleanup. Each exports a *_PROMPT_VERSION constant and a prompt string or builder function.

[UNVERIFIED] — run grep for imports. Likely most are LEGACY from RC1.

prompts/index.ts

Exports getAllPromptVersions() — line 85. Aggregator.


schemas/response_schemas.ts

JSON schema contracts for Maverick + specialist responses. Used in prompt-building and validation.

Exports: MaverickResponse, ElenaResponse, ElenaHandshakeResponse, BrunoResponse, BrunoHandshakeResponse interfaces + MAVERICK_SCHEMA, ELENA_EXECUTE_SCHEMA, ELENA_HANDSHAKE_SCHEMA, BRUNO_EXECUTE_SCHEMA, BRUNO_HANDSHAKE_SCHEMA constants.


Agent Studio Layer — lib/agent-studio/

client.ts — 156 lines — ALIVE

Thin HTTP client for Agent Studio.

Exports: - const AGENT_IDS = { elena: 'f029acbb-...', bruno: 'facb549e-...' } — line 20 - type AgentPersona — line 25 - interface AgentStudioRequest, AgentStudioConfig — lines 27, 36 - async function callAgentStudio(request): Promise<Response> — line 62 — POSTs to Agent Studio, returns the raw SSE Response - function getAgentId(persona) — line 150


stream-adapter.ts — 293 lines — ALIVE

Parses Agent Studio's XML-tagged SSE into clean chunks.

Exports: - interface StreamAdapterOptions, StreamAdapterResult - async function adaptAgentStudioStream(response, options): Promise<StreamAdapterResult> — line 42

Uses: StatefulStreamStripper from lib/search/stream_processor.ts (this is why that class must NOT be deleted — memory file explicitly forbids).

F-038: this is where the specialist stream should be routed through a hallucination audit but currently isn't.


Frontend Layer — src/hooks/chat/

useChatStream.ts — ALIVE

React hook for Maverick turns.

Exports: - export const useChatStream = ({...}) — line 20

Parses SSE events from /api/search, updates message state. Handles: signals, sources, chunk, discovery, handoff_proposal, quality, audit, turn_snapshot, final, error.

P-9 target: 3 separate message update cycles per turn (signals → sources → final) — should consolidate to single reducer commit.


useSpecialist.ts — ALIVE

React hook for Specialist (Elena/Bruno) turns.

Exports: - export const useSpecialist = ({...}) — line 18

Parses SSE events from specialist flow. Partially duplicates useChatStream event handlers (F-027 cleanup target — Step 7).


streamParsers.ts — ALIVE

SSE parsing utilities shared between hooks.

Exports: - function parseStreamTags(content) — line 7 - function normalizeSources(rawSources) — line 106 - function mergeDebugChunks(currentSources, debugChunks) — line 137


types.ts — ALIVE (pure types)

Shared TypeScript types for hook state.


Summary Table — Total Files

Layer Files Total lines ALIVE %
API entry 3 ~400 100%
Orchestration 20+ ~4800 ~85%
Agent Studio 2 ~449 100%
Frontend hooks 4 ~900 100%
Prompts 10 ~1200 ~60% (need audit of legacy)
Schemas 1 ~230 100%

Cross-references

  • 01-System-Overview — architecture view
  • 02-Data-Flow — request lifecycle using these files
  • 04-Functions-Reference — deeper function-level reference
  • 08-Audit-Pipeline — InlineStreamAuditor + audit.ts detail
  • 09-Session-State — SessionState interface from redis.ts
  • 10-Known-Issues — F-001 to F-039