/** * repo-signals.ts * * Derives keyword signals per repository from: * 1. Detected stack profile (language + frameworks) — deterministic, always available * 2. File class-type distribution from file_index — structural, always available * 3. LLM-generated project docs (about, architecture, pages) — optional enrichment * using cross-corpus TF-IDF so generic web-app terms don't dominate * * Design constraints: * - Zero LLM calls at query time — all computation is at index time * - Project-agnostic — no hardcoded repo names anywhere * - Works for monoliths (single repo = BE + FE), microservices, Lambda, unknown stacks * - Signals survive server restart (persisted in `repo_signals` table, migration v16) * - Manual overrides are respected (locked = 1 rows are never overwritten) */ import type { StackProfile } from "../indexer/stack-profiler.js"; export declare const LANGUAGE_SIGNALS: Record; export declare const FRAMEWORK_SIGNALS: Record; export declare const ROLE_SIGNALS: Record<"backend" | "frontend", string[]>; export declare const LAMBDA_SIGNALS: string[]; /** * Extracts domain-specific terms using cross-corpus inverse document frequency. * * All repos' docs are loaded together so terms that appear in every repo's * about page (e.g. "authentication", "API", "user") are penalized by their * high document frequency. Only terms that are characteristic of ONE or FEW * repos survive — these are the actual domain signals (e.g. "prescription", * "billing_order", "blood_pressure", "pre_authorization"). * * Algorithm: * 1. Extract candidate terms: 4+ char words, hyphenated, snake_case, CamelCase * 2. Count term frequency (TF) within each repo's doc set * 3. Count document frequency (DF) across all repos' doc sets * 4. TF-IDF = TF × log(N / DF + 1) where N = total number of repos with docs * 5. Filter freq < 2 and apply STOP_WORDS * 6. Return top topN by TF-IDF score for each repo * * @param allRepoDocs - Map of repoName → array of doc content strings * @param topN - Maximum domain signals to return per repo */ export declare function extractCrossCorpusDomainTerms(allRepoDocs: Map, topN?: number): Map; export interface SignalSources { language: string[]; framework: string[]; role: string[]; domain: string[]; repoName: string[]; } export interface GenerateRepoSignalsResult { signals: string[]; sources: SignalSources; } /** * Derives keyword signals for a single repo from its detected stack profile, * file class-type distribution, and optional cross-corpus domain terms. * * Pure function — all DB I/O happens in {@link generateAndSaveAllRepoSignals}. */ export declare function generateRepoSignals(repoName: string, profile: StackProfile, domainTerms: string[], classTypeCounts: Record): GenerateRepoSignalsResult; /** * Generates signals for all indexed repos in one batch call. * * Uses cross-corpus TF-IDF so that IDF is computed across ALL repos' docs * simultaneously — terms appearing in every repo's about page are penalized. * * Repos with `locked = 1` in the `repo_signals` table are skipped. * Call this after `saveRepoProfile()` and after `project_docs` are generated. */ export declare function generateAndSaveAllRepoSignals(): void; /** * Clears the in-memory signal cache. Called at the end of each indexing run. * Cross-process note: `index-repos.ts` and the MCP server are separate processes. * The server picks up new signals on next cache miss (after its own cache is cleared * on server restart, or after a TTL if TTL-based invalidation is added). */ export declare function invalidateRepoSignalsCache(): void; /** * Returns all stored repo signals as a Map. * Loaded from the `repo_signals` table once per process lifetime, then cached. * Returns an empty map — not null — if no signals exist yet, so callers * always receive a valid map and the embedding-classifier fallback takes over. */ export declare function loadRepoSignals(): Map; /** * Reads the full signal record for a repo including source breakdown * and lock status (used by the dashboard API). */ export interface RepoSignalRecord { repo: string; signals: string[]; signalSource: "derived" | "manual"; locked: boolean; generatedAt: string | null; } export declare function getAllRepoSignalRecords(): RepoSignalRecord[]; //# sourceMappingURL=repo-signals.d.ts.map