/** * A point-in-time fingerprint attached to any side-channel file loopgraph * writes (Decision record 004, 技术点 4, CodeGraph-inspired: side-channel * output must carry an explicit staleness signal instead of silently * looking as current as a freshly-computed one). * * `modelContentHash` is the ONLY field `isStale` compares against — it's * a hash over every model YAML file's own bytes, so it changes the * instant model data changes, independent of git (uncommitted edits, * detached checkouts, and non-git exports all still get a real hash). * `generatedAt`/`repoHead`/`repoDirty` are read-only context for a human * looking at the file — never treat wall-clock age or repo dirtiness as * a staleness signal by itself: time passing doesn't make a view wrong, * and a repo can be dirty for reasons unrelated to the model. */ export interface StalenessStamp { generatedAt: string; modelContentHash: string; repoHead: string | null; repoDirty: boolean | null; } /** * Deterministic fingerprint of every *.yaml/*.yml file under `modelDir`, * independent of file iteration order (sorted before hashing) and of git * (reads working-tree bytes directly, so uncommitted edits change the * hash immediately — the same "reflect the working tree, not last * commit" posture as the rest of loadModel). This deliberately hashes * the WHOLE model dir rather than per-flow/per-node: it will over-report * staleness when an unrelated node changes, which is the safe direction * for a "don't trust this without checking" signal — a false "maybe * stale" costs a re-run; a false "definitely fresh" costs a wrong * decision made on stale data. */ export declare function computeModelContentHash(modelDir: string): Promise; /** * Best-effort `git rev-parse HEAD` / `git status --porcelain` against * `repoRoot`. Returns `{ head: null, dirty: null }` for anything that * isn't a usable git checkout (no git binary, not a repo, no commits * yet) rather than throwing — a staleness stamp must still be produced * for a plain export or a fresh `git init` with no commits. * * Exported so other commands that need "which commit was this model read * from" (e.g. `loopgraph backtest` — its `--ref` pins the COMMIT WINDOW * scanned, never the model tree, which is always read from whatever is on * disk right now) can stamp their own output without duplicating this git * plumbing a third time. */ export declare function readGitInfo(repoRoot: string): Promise<{ head: string | null; dirty: boolean | null; }>; export declare function computeStalenessStamp(modelDir: string, repoRoot: string): Promise; /** Renders `stamp` as an HTML comment block, prepended to a generated side-channel file. */ export declare function formatStalenessBanner(stamp: StalenessStamp): string; /** * Inverse of `formatStalenessBanner`. Returns undefined if `text` has no * recognizable banner. Parses fields by splitting on lines and matching * each line's start against `BANNER_FIELD_KEYS` rather than building a * `RegExp` per field — field keys are fixed string literals here, never * user input, but avoiding per-call dynamic regex construction sidesteps * the need to reason about escaping altogether, and keeps every field's * value confined to its own line (a value can never accidentally * swallow a neighboring line the way a `.*` non-multiline capture over * a shared block could invite as this function grows more fields). */ export declare function parseStalenessBanner(text: string): StalenessStamp | undefined; /** * Whether a previously-generated stamp no longer reflects the current * model. Compares `modelContentHash` ONLY — see the field's docstring on * `StalenessStamp` for why wall-clock time and repo dirtiness must not * factor in. */ export declare function isStale(generated: StalenessStamp, current: StalenessStamp): boolean; //# sourceMappingURL=staleness.d.ts.map