UNPKG

@blundergoat/goat-flow

Version:

AI coding agent harness and local dashboard for Claude Code, OpenAI Codex, Google Antigravity, and GitHub Copilot - setup audits, guardrails, structured skills, deny hooks, and persistent learning loops.

39 lines 2.05 kB
/** * The `index-fresh` collector behind `goat-flow stats --check`: detects when a generated * learning-loop INDEX.md no longer matches its bucket content. Freshness is decided by re-running * the generator in memory and string-comparing against the on-disk file - content comparison, not * mtimes, because mtimes false-stale after checkout/restore and are not portable. A missing * INDEX.md is reported as `missing` (advisory - a fresh install must not fail CI before the first * `goat-flow index` run); a missing bucket directory is `no-bucket` and never reported. */ import { formatIndex } from "../learning-loop-index/format-index.js"; import { INDEX_BUCKETS, parseBucket, } from "../learning-loop-index/parse-bucket.js"; /** Build the INDEX.md path inside a bucket directory regardless of trailing-slash config style. */ function indexPathFor(dirPath) { return `${dirPath.replace(/\/$/, "")}/INDEX.md`; } /** * Compute index freshness for all four learning-loop buckets. * * @param fs - read-only filesystem adapter rooted at the target project * @param paths - bucket-keyed directory paths, normally from `resolveIndexBucketPaths` * @returns one freshness record per bucket in stable INDEX_BUCKETS order */ export function collectIndexFreshness(fs, paths) { return INDEX_BUCKETS.map((bucket) => { const dirPath = paths[bucket]; const indexPath = indexPathFor(dirPath); if (!fs.exists(dirPath)) { return { bucket, dirPath, indexPath, state: "no-bucket" }; } const onDisk = fs.readFile(indexPath); if (onDisk === null) { return { bucket, dirPath, indexPath, state: "missing" }; } const expected = formatIndex(bucket, parseBucket(fs, dirPath, bucket)); // CRLF-normalize so a Windows autocrlf checkout does not read as permanent staleness. const state = onDisk.replace(/\r\n/g, "\n") === expected ? "fresh" : "stale"; return { bucket, dirPath, indexPath, state }; }); } //# sourceMappingURL=index-freshness.js.map