/** * [WHO]: TerrainNode, TerrainEdge, TerrainSnapshot, buildTerrainIndex(), checkDipCoverage(), CoverageReport * [FROM]: Depends on node:fs/promises, node:path * [TO]: Consumed by extensions/builtin/sal/anchors.ts, extensions/builtin/sal/index.ts * [HERE]: extensions/builtin/sal/terrain.ts - terrain graph builder from DIP P2/P3 headers */ export type TerrainNodeKind = "root" | "module" | "file"; export interface TerrainNode { id: string; kind: TerrainNodeKind; label: string; modulePath?: string; filePath?: string; p3Who?: string; p3From?: string; p3To?: string; p3Here?: string; hasP3: boolean; p2Summary?: string; mtimeMs: number; } export interface TerrainEdge { fromId: string; toId: string; type: "contains" | "adjacent-to"; } export interface TerrainSnapshot { workspaceRoot: string; generatedAt: number; nodes: TerrainNode[]; edges: TerrainEdge[]; moduleByFile: Record; } export interface CoverageReport { module: string; totalFiles: number; filesWithP3: number; coveragePct: number; hasP2: boolean; missingFields: number; } /** * Build a terrain index from a workspace root. * Coarse, file/module-level only. Symbol-level deferred. * * Async by design: walks the filesystem and reads DIP headers without blocking * the Node event loop, so TUI render frames (e.g. the user's message bubble * queued via process.nextTick right before session.prompt()) can flush between * fs operations. A synchronous implementation holds stdout long enough that * GPU block terminals (Warp) coalesce a whole turn into a single block and * only render it when the turn ends. */ export declare function buildTerrainIndex(workspaceRoot: string): Promise; /** * Check DIP coverage for the requested module list. * Each module string is a posix-style path relative to workspace root, e.g. "core/runtime". * If modules is empty, all known modules are reported. */ export declare function checkDipCoverage(snapshot: TerrainSnapshot, modules: string[]): CoverageReport[]; /** * Determine whether the snapshot is stale relative to current DIP files. * Returns true when any AGENT.md (or legacy CLAUDE.md) or source file mtime exceeds snapshot.generatedAt. * * Async to avoid blocking the event loop during the staleness probe that runs * at the top of every before_agent_start hook. */ export declare function isSnapshotStale(snapshot: TerrainSnapshot): Promise; /** * Look up the module id that contains a given relative file path. * Used by action evidence accumulation to map touched files back to anchors. */ export declare function moduleIdForPath(snapshot: TerrainSnapshot, relPath: string): string | undefined; export declare function toPosixPath(p: string): string;