export type ManifestEntry = { sourceHash: string; /** Transitive agency-import paths, manifest-dir-relative, sorted. */ deps: string[]; depsHash: string; stdlibHash: string; hasPkgImports: boolean; /** False when dependency discovery could not fully establish the * subtree (splice anywhere in it, unparseable/missing reachable file). * Such entries are recorded (outputFor keeps working) but never fresh. */ cacheable: boolean; configKey: string; compilerStamp: string; /** Manifest-dir-relative output path. */ outputPath: string; }; export type BuildManifest = { version: 2; /** Keyed by manifest-dir-relative module path. */ entries: Record; }; export declare const MANIFEST_DIR_NAME = ".agency-build"; export declare function manifestDirFor(entryFile: string): string; export declare function loadManifest(manifestDir: string): BuildManifest; export declare function saveManifest(manifestDir: string, manifest: BuildManifest): void; export declare function hashBytes(data: string | Buffer): string; export declare function hashFile(absPath: string): string | null; /** THE construction of depsHash. Writer (manifestTracker) and checker * (isEntryFresh) both call this; never inline the expression. */ export declare function computeDepsHash(depHashes: string[]): string; /** Canonical config identity. JSON.stringify is order-stable here because * every config passes through AgencyConfigSchema.safeParse (loadConfigSafe * returns result.data), and zod rebuilds objects in SCHEMA shape order — * guarded by the key-order test in lib/cli/precompile.test.ts. */ export declare function deriveConfigKey(config: unknown): string; export declare function computeStdlibHash(stdlibDir: string): string; /** Stdlib STRUCTURE only (sorted file list, no contents). Stdlib-resident * entries carry this flavor: their per-file `deps` already track stdlib * CONTENT, but re-export resolution bakes resolved stdlib PATHS into * emitted output, so add/remove/rename must still rebuild the stdlib * world while a plain edit no longer does. */ export declare function computeStdlibNamesHash(stdlibDir: string): string; /** * Content hash of the code `entryFile` runs: every module it reaches by * relative import, except those under `distLibDir/runtime/`. Only this code * can change what the entry emits, so an edit to the logs viewer or the TUI * does not rebuild every .agency file. Runtime modules are still walked, so * whatever they import is hashed. A match inside a string literal can only * add a file to the hash, which costs a rebuild, never a stale skip. * * A missing entry means it was renamed or moved, and a walk from it would * reach nothing, so every compiler edit would leave the stamp unchanged. * Instead, hash every compiled module except runtime/ and agents/ (the * compiled agents are the agency compiler's own output; hashing them would * make every build invalidate the next). That rebuilds too often but never * skips a stale file. compilerStampEntries.test.ts fails on the rename. * Under vitest the entry resolves into lib/, which holds .ts files, so * the writer and the checker both take this path and agree. */ export declare function computeCompilerStamp(distLibDir: string, entryFile: string): string; export type FreshnessContext = { manifestDir: string; stdlibHash: string; /** Names-only flavor (computeStdlibNamesHash) for stdlib-resident * entries; see stdlibHashFor. */ stdlibNamesHash: string; /** Canonical absolute stdlib dir. Supplied by the tracker so this file * never imports importPaths.ts (leaf-ness, see the header). */ stdlibDir: string; compilerStamp: string; configKey: string; }; /** ONE selection rule for which stdlib-hash flavor an entry carries. * Pure and argument-only so non-compile consumers (the doc cache) can * use it without fabricating a FreshnessContext. Writer and checker * both route through it — never inline the comparison. */ export declare function stdlibHashFlavor(absModule: string, stdlibDir: string, namesHash: string, contentsHash: string): string; export declare function stdlibHashFor(absModule: string, ctx: FreshnessContext): string; export declare function isEntryFresh(moduleRel: string, manifest: BuildManifest, ctx: FreshnessContext): boolean;