Skip to main content

Module tree_cache

Module tree_cache 

Source
Expand description

Tree-gate caches: namespaced by everything that can change a verdict, never trusted across a namespace (ADR-0024).

A tool’s own cache is not enough. Prettier’s cache keys exclude plugin versions and implementations, so a plugin upgrade would reuse stale passes. So every gate’s cache lives under a NAMESPACE — a hash of:

  • the declared command;
  • the version of the tool the gate actually runs;
  • the staged blob of every lockfile and every config-like file, matched by basename anywhere in the tree;
  • the gate’s inputs=.

A plugin upgrade moves the lockfile, so it moves the namespace, and the old namespace is deleted (under the gate’s lock) before anything warms the new one.

Warm means a completion marker exists in the current namespace: a full run finished there. The marker is only a hint about cost (“starting this gate at commit is cheap”). Proof always comes from the commit-time run on the exact tree.

Caches are per worktree ($GIT_DIR): eslint’s and prettier’s key files by absolute path, so a shared cache would give a new worktree no warmth.

Structs§

Lock
A held, non-blocking lock on one gate’s cache. Released on drop.

Functions§

cache_flags
What {cache} expands to for gate in ns_dir, or "" for a tool without a cache, or typed (or undetermined) eslint.
config_is_typed
Whether an eslint --print-config JSON uses type information (parserOptions.project set, or projectService true), which makes a per-file cache stale across files.
config_like
Whether a path’s BASENAME is config-like: *.json, *.toml, *.yaml, *.yml, *config*, .*rc*, .*ignore, or a lockfile. Basename only, so src/config/app.ts is not config.
config_matches_index
Whether every config-like file under cwd is exactly as staged: no unstaged edit and no untracked one. A git that cannot answer reads “no”.
config_text_is_typed
Whether any tracked eslint config under cwd names type information in its text. A heuristic that can only err towards typed.
duration_of
The last measured duration of each declared commit check, <id> <ms> per line, in $GIT_DIR/amont-cache/.durations: how long a commit’s own checks run, which is the cover a tree gate can hide behind.
enter_namespace
gate_dir/<ns>, created, with every OTHER namespace of the gate deleted. Call only while holding the gate’s Lock.
gate_dir
$GIT_DIR/amont-cache/<gate>.
gate_last_ms
How long this gate’s last commit-time run took, kept in the gate’s directory (not a namespace), so the fit test can run FIRST — before the version probe, the skew check and the namespace — and a gate that cannot fit costs the commit nothing. A cancelled run records its elapsed time: a lower bound, which is what matters.
is_warm
Whether a full run completed in this namespace.
mark_complete
Record that a full run completed in ns_dir: temp + rename, so a killed writer leaves no marker at all rather than a half one.
namespace
The namespace for gate: see the module doc. None when git cannot answer, which reads as cold.
record_durations
Merge measured into the durations file (temp + rename).
record_gate_last_ms
tool_version
The version of the tool the gate actually runs, as best it can be read without running the gate. Never touches .venv or the network on its own account; a wrapper that does (pyright’s) is bounded by deadline and cancel, like any gate run. None when it could not be read in time — the caller withholds rather than guess.
try_lock
Take gate’s lock without waiting. None when another run holds it (or the lock file cannot be made) — which the caller reads as cold: a commit never waits on a warm-up.
typed_eslint
Whether eslint here uses type information. FAIL-CLOSED: anything but a definite “untyped” reads as typed, which only costs the cache, where a wrong “untyped” would let a stale per-file cache prove a typed tree.