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 === true → igniteSpecialist({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