Aggregate snapshot of the local skills (rules) corpus for
difflore doctor --report. Reports total count, breakdown by
origin and top source_repo partitions, and the count of skills
with empty file_patterns (recall-killing signature). Empty
file_patterns once tripped Eval-26 — keeping a permanent counter
catches future cluster-pipeline regressions.
Resolve the current project root: git rev-parse --show-toplevel in
the current working directory, or the cwd itself if that fails (not a
git repo, git not installed, etc.). Never panics; falls back to .
when even current_dir errors.
Path to the global data.db — stays global (cross-project features like
rules stats rely on a single aggregate view). Only the per-project
embedding index moves out of the global root.
Derive a stable hash for a project root. Uses SHA-1 of a purely
lexical, slash-normalised path identity, hex, truncated to 12 chars
(48 bits).
It intentionally does not call canonicalize(): project identity must
not change just because a directory was created/deleted, or because
Windows returned an extended \\?\ path on one call and a normal path
on another. A pair of distinct roots collides with probability 2^-48;
cumulative risk grows with the number of project roots under the usual
birthday bound, so this is suitable for local DB partition names, not as
a security boundary.
Base dir for per-project index DBs: ~/.difflore/projects/{hash}/.
Does not create the directory — callers that need the path on disk
are responsible for create_dir_all.
Count rows in the named tables. Used by difflore doctor to snapshot
store size without leaking SqlitePool to the CLI crate. Tables that
don’t exist (e.g. on a fresh install before migrations) surface as
Err(message) rather than aborting — the doctor report still wants
to show a best-effort inventory.