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 forgateinns_dir, or""for a tool without a cache, or typed (or undetermined) eslint. - config_
is_ typed - Whether an
eslint --print-configJSON uses type information (parserOptions.projectset, orprojectServicetrue), 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, sosrc/config/app.tsis not config. - config_
matches_ index - Whether every config-like file under
cwdis 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
cwdnames 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’sLock.- 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.Nonewhen git cannot answer, which reads as cold. - record_
durations - Merge
measuredinto 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
.venvor the network on its own account; a wrapper that does (pyright’s) is bounded bydeadlineandcancel, like any gate run.Nonewhen it could not be read in time — the caller withholds rather than guess. - try_
lock - Take
gate’s lock without waiting.Nonewhen 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.