/** * Git-based signals for the codeprism indexer. * * A single `git log` pass extracts two signals used throughout the pipeline: * - thermalMap — normalized commit frequency per file (0.0 cold → 1.0 hot) * - staleDirectories — top-level dirs with zero commits in the last STALE_THRESHOLD_DAYS * * These drive file-selection ordering (hot files go first in LLM prompts), card * quality tiering (hot flows get premium LLM cards), and stale-dir filtering. */ export declare const STALE_THRESHOLD_DAYS = 150; export declare const THERMAL_WINDOW_DAYS = 180; export interface GitSignals { /** filePath (relative to repoPath) → normalized commit frequency 0.0–1.0 */ thermalMap: Map; /** * Top-level directory names (relative, no trailing slash) that received * zero commits within THERMAL_WINDOW_DAYS. Safe to skip in LLM prompts. */ staleDirectories: Set; /** Currently checked-out branch name at the time of indexing */ branch: string; /** Branch diff context (null when on main/master — no extra context needed) */ branchDiff: BranchDiffContext | null; } export interface RepoBranchSummary { repo: string; branch: string; branchClass: BranchClass; targetEnvironment: TargetEnvironment | null; ticketIds: string[]; commitsAhead: number; } export interface WorkspaceBranchSignal { /** * The dominant non-base branch if 2+ repos share the same branch name. * This is the "epic" or "feature" branch the team is working on. * null if repos are on different branches or all on base branches. */ epicBranch: string | null; /** Class of the epic branch */ epicBranchClass: BranchClass; /** Target environment of the epic branch (e.g. "demo" for demo/orlando) */ epicTargetEnvironment: TargetEnvironment | null; /** Names of repos currently on the epic branch */ epicRepos: string[]; /** * Repos still on their base branch — they haven't picked up the epic yet. * Their docs should note "this repo has no branch-specific changes for this epic." */ behindRepos: string[]; /** * Repos on a non-base branch that is **not** the epic branch. * Each team member may be on a different personal/task branch. * These repos are diverged from both base and the epic — worth flagging in cross-repo docs. */ splitRepos: string[]; /** Per-repo branch state, ordered as supplied */ repoBranches: RepoBranchSummary[]; /** All ticket IDs found across all repo branch names, deduplicated */ allTicketIds: string[]; /** * Remote branch details per repo, keyed by repo name. * Populated by `git fetch` — no API token needed. * Contains recent commit messages and changed files for the epic branch. */ remoteBranches: Map; } export interface RemoteBranchSummary { /** Branch name as it appears on the remote (without "origin/") */ branch: string; /** The 5 most recent commit subject lines on this remote branch */ recentCommits: string[]; /** Files changed on this branch vs the repo's base branch */ changedFiles: string[]; } /** * Builds the workspace-level branch signal by inspecting all repos in parallel. * * This is the entry point that replaces per-repo `getCurrentBranch()` calls — * it gives the full cross-repo picture before any per-repo processing begins. */ export declare function buildWorkspaceBranchSignal(repos: Array<{ name: string; absPath: string; }>, opts?: { ticketId?: string; branchOverride?: string; /** * Run `git fetch --all --prune` before collecting remote branch details. * Opt-in only to avoid surprise network I/O. Default: false. */ fetchRemote?: boolean; }): Promise; /** * Builds git signals for a single repository root in one git log pass. * * Falls back to an empty map + empty set if the directory is not a git repo * or git is unavailable — all callers must handle zero-heat gracefully. */ export declare function buildGitSignals(repoAbsPath: string): Promise; /** * Returns the name of the currently checked-out branch in a git repo. * Falls back to "main" if git is unavailable or the repo has no commits. */ export declare function getCurrentBranch(repoAbsPath: string): Promise; /** * Semantic classification of a branch by its purpose. * * base — integration branches (main, master, develop, trunk) * environment — long-lived deployment branches (staging, production, demo/*, release/*) * feature — short-lived developer branches (feature/*, ENG-*, fix/*, etc.) */ export type BranchClass = "base" | "environment" | "feature"; /** * The target deployment environment implied by the branch name. * Only set for `environment` class branches. */ export type TargetEnvironment = "demo" | "staging" | "production" | "release" | "other"; /** * Classifies a branch by its semantic purpose. * Used to decide which base to diff against and how to frame prompt context. */ export declare function classifyBranch(branch: string): { branchClass: BranchClass; targetEnvironment: TargetEnvironment | null; }; /** * Returns true if the given branch is a base/integration branch. */ export declare function isBaseBranch(branch: string): boolean; export interface BranchDiffContext { /** Current branch name */ branch: string; /** Semantic classification of the current branch */ branchClass: BranchClass; /** Target deployment environment (demo, staging, production…) — null for feature/base branches */ targetEnvironment: TargetEnvironment | null; /** Base branch this branch diverged from */ baseBranch: string; /** * Relative file paths changed on this branch vs base. * Empty when on a base branch or when git diff is unavailable. */ changedFiles: string[]; /** Number of commits ahead of base */ commitsAhead: number; /** * Ticket IDs extracted from the branch name (e.g. ENG-756 from feature/ENG-756-remote-auth). * Empty array when none found. */ ticketIds: string[]; } /** * Builds branch-aware diff context for non-base branches. * Used to inject "what changed on this branch" into doc prompts so the * generated docs reflect `demo/orlando` or `feature/billing-v2`, not main. * * Returns null when the repo is on a base branch (no extra context needed). */ export declare function buildBranchDiffContext(repoAbsPath: string, currentBranch?: string): Promise; /** * Returns the normalized heat for a file path (relative to repoPath). * Returns 0 if the file has never been committed in the thermal window. */ export declare function getFileHeat(filePath: string, thermalMap: Map): number; /** * Returns true if the file's first path segment matches any stale directory. */ export declare function isInStaleDir(filePath: string, staleDirectories: Set): boolean; //# sourceMappingURL=git-signals.d.ts.map