checkcache

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package checkcache is where what file-guards concluded about commits is kept, so that no one asks a judge the same question twice.

The unit it stores is a RUN: one rule evaluated once over one commit range, with its Checks (one per subject and kind, each with its Items) — a10n's check-results shape, which internal/checkstore speaks. What makes a check reusable is its KEY and nothing else: which session, agent, branch or range recorded it is provenance on the run, never part of a lookup. A finished pass with the same key is a cache hit; a stored fail is kept so a reader can say why it is red.

This file is the whole contract the engine depends on: Lookup and Put. The in-memory implementation below is the reference and what the unit tests use; the git-ref store (an orphan branch of content-addressed zstd segments) implements the same interface.

Index

Constants

View Source
const (
	StatusPass        = "pass"
	StatusFail        = "fail"
	StatusSkip        = "skip"
	StatusError       = "error"
	StatusInterrupted = "interrupted"
)

Check statuses. Only a pass is a cache hit.

View Source
const (

	// TrainMin is how many records Gc needs before it trains a dictionary
	// from them; below it segments are written with no dictionary (plain zstd).
	TrainMin = 300
	// SegmentTarget is the record count Gc compacts segments to.
	SegmentTarget = 1000
)
View Source
const GcSegments = 24

GcSegments is how many segments a Put leaves behind before the store compacts them: every Lookup scans every segment index.

View Source
const PushErrorFile = "sloprail-checks-push-error"

PushErrorFile is the file under the git common dir holding why the last push of local results failed (absent once a push succeeds). The push gate (when enabled), a separate process, reads it.

View Source
const SchemaDir = "v2026-10-08"

SchemaDir is the schema version (a date) and the single directory the store reads and writes. A ref carrying a newer v<date>/ directory is refused.

A change to what a key is made of bumps it (with SchemaVersion). Opening or writing a ref that holds only older directories just starts this one, empty: the older directories are not read or rewritten, and everything is judged again. An older binary that meets the new directory refuses it (ErrFutureSchema), so CI's sr-checks is upgraded with the engine that writes it.

v2026-10-08: sr3 keys, no citations in the fingerprint.

View Source
const SchemaVersion = "sr3"

SchemaVersion is the key schema. It is part of every key, so a change to how fingerprints are derived, or to what a key is made of, never collides with an older result.

sr1: rule, the rule's hash, kind, subject, fingerprint (see legacyID).
sr2: no rule hash.
sr3: the fingerprint no longer covers citations.

Changing what a key is made of means bumping this AND SchemaDir: the older directory is left as it is and the new one starts empty.

Variables

View Source
var ErrCorrupt = errors.New("checkcache: corrupt segment")

ErrCorrupt means stored bytes do not match their content address or cannot be decoded. It is never reported as a miss.

View Source
var ErrFutureSchema = errors.New("checkcache: ref uses a newer schema; upgrade sloprail")

ErrFutureSchema means the ref holds a schema directory newer than this binary.

Functions

func Findable

func Findable(c Check) bool

Findable is whether a check can be looked up: it has a fingerprint and finished as a pass or a fail — or is a fail that was resolved as stale (a skip carrying metadata "staleFrom"), which is found so that, being the newest result of its key, it supersedes the fail it resolves: a reader sees a skip, and a skip is no hit. sr:invariant cache/unfinished-never-stored

func Newer

func Newer(a, b Found) bool

Newer reports whether a should be preferred over b when both hold a result for one key: the latest run wins, a tie broken deterministically.

Types

type Cache

type Cache interface {
	// Lookup returns, for each key it has a pass or fail for, the check and its run, by
	// Key.ID(). A key with no result is absent. When several runs hold the key (two
	// writers), the latest wins. Only checks with a fingerprint are findable.
	Lookup(keys []Key) (map[string]Found, error)
	// Put stores runs. Writing a key that already has a result adds to it, never rewrites
	// it; a reader resolves duplicates as Lookup says.
	Put(runs []Run) error
	// Runs returns every run stored, each once (a run put again replaces the earlier copy),
	// newest first: the history a reader that lists (not looks up) works over. A run with no
	// findable check is a run too.
	Runs() ([]Run, error)
}

Cache is the whole contract: look keys up, put runs in.

type Check

type Check struct {
	Subject string `json:"subject"`
	Kind    string `json:"kind"`
	Status  string `json:"status"`
	// Fingerprint is the cache key part; only a guard's verdict carries one (its steps inside
	// it do not), and what has none is not findable.
	Fingerprint string         `json:"fingerprint,omitempty"`
	Metadata    map[string]any `json:"metadata,omitempty"`
	Items       []Item         `json:"items,omitempty"`
}

Check is one (subject, kind) of a run.

type File

type File struct {
	// contains filtered or unexported fields
}

File is a Cache kept as an append-only JSON-lines file of runs: the local, single-machine store until the git-ref store (an orphan branch of content-addressed segments) replaces it behind the same interface. Appending a line is atomic enough for several processes writing at once, and a reader resolves duplicates as Cache.Lookup says.

func OpenFile

func OpenFile(path string) *File

OpenFile returns the cache kept at path. The file is created on the first Put.

func (*File) Lookup

func (f *File) Lookup(keys []Key) (map[string]Found, error)

func (*File) Put

func (f *File) Put(runs []Run) error

func (*File) Runs

func (f *File) Runs() ([]Run, error)

type Found

type Found struct {
	Run   Run
	Check Check
}

Found is the stored check for a key, with the run it was recorded in.

type GcStats

type GcStats struct {
	Records    int // latest result per key kept
	Duplicates int // superseded results dropped
	SegsBefore int
	SegsAfter  int
	Retrained  bool
}

GcStats says what a compaction did.

type Item

type Item struct {
	Key      string         `json:"key,omitempty"`
	Passed   bool           `json:"passed"`
	Metadata map[string]any `json:"metadata,omitempty"`
}

Item is one finding inside a check (a file a judge named, a citation a prerequisite saw).

type Key

type Key struct {
	// Rule is the rule's qualified name (<plugin>/file-guard/<name>).
	Rule string `json:"rule"`
	// Kind names the check inside the rule: check[1]:judge:./rubric.md.j2.
	Kind string `json:"kind"`
	// Subject is the unit judged. Today the one subject of a rule's checks is "changeset".
	Subject string `json:"subject"`
	// Fingerprint is what the verdict is about: the subject's files (path and content) and the
	// fingerprint the rule's `subjects:` script gave the subject (changeset.GuardFingerprint).
	// Not in it: a commit SHA, a citation, the model, the judge's template, `prepare`'s output.
	Fingerprint string `json:"fingerprint"`
}

Key is what a check's result is a fact about.

func (Key) ID

func (k Key) ID() string

ID is the key's stable identity: a hex sha256 of its parts, each separated so no two keys can be re-cut into one another.

type Memory

type Memory struct {
	// contains filtered or unexported fields
}

Memory is the in-memory Cache.

func NewMemory

func NewMemory() *Memory

NewMemory returns an empty in-memory cache.

func (*Memory) Lookup

func (m *Memory) Lookup(keys []Key) (map[string]Found, error)

func (*Memory) Put

func (m *Memory) Put(runs []Run) error

func (*Memory) Runs

func (m *Memory) Runs() ([]Run, error)

type Options

type Options struct {
	// Dir is any directory inside the repository whose object store holds the ref.
	Dir string
	// Remote is a remote name or URL the ref is synced with. Empty = local only.
	Remote string
	// Ref is the local ref that mirrors the branch. Default refs/sloprail/checks.
	// CI points it at a ref it fetched (refs/remotes/origin/sloprail/checks).
	Ref string
	// Branch is the remote ref. Default refs/heads/sloprail/checks.
	Branch string
	// NoAutoGc stops a Put from compacting the branch when it grows (see maybeGc). For tests
	// that count segments or commits.
	NoAutoGc bool
}

Options configures a Store.

type Run

type Run struct {
	ID      string `json:"id"`
	RunAt   string `json:"run_at"` // fixed-width UTC, so stamps compare as strings
	BatchID string `json:"batch,omitempty"`
	// Rule is the rule's qualified name; RuleHash its definition's hash when the run was made.
	// The hash is recorded for the trace only: a verdict's key never holds it, so a rule's
	// logic changing does not void what was judged before.
	Rule     string `json:"rule"`
	RuleHash string `json:"ruleHash"`
	BaseRef  string `json:"base_ref"`
	HeadRef  string `json:"head_ref"`
	// BaseTree and HeadTree are the tree ids of BaseRef and HeadRef when the run was made
	// (absent on a run recorded before they existed): equal trees are an equal net change,
	// so a range over the same two trees can read this run's verdict (Store.CachedByTrees).
	BaseTree string `json:"base_tree,omitempty"`
	HeadTree string `json:"head_tree,omitempty"`
	// ExitCode and Error record an ENGINE failure (git, a range that could not be read):
	// such a run passes nothing.
	ExitCode int            `json:"exit_code,omitempty"`
	Error    string         `json:"error,omitempty"`
	Complete bool           `json:"complete"` // every check it was going to run is stored
	Metadata map[string]any `json:"metadata,omitempty"`
	// Provenance: who ran it. Never part of a key.
	RepoID    string  `json:"repo_id,omitempty"`
	Branch    string  `json:"branch,omitempty"`
	SessionID string  `json:"session_id,omitempty"`
	AgentID   string  `json:"agent_id,omitempty"`
	Checks    []Check `json:"checks"`
}

Run is one rule evaluated once over one commit range.

func (Run) CheckKey

func (r Run) CheckKey(c Check) Key

CheckKey is the key of one check of a run.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is the git-ref Cache. It implements Cache.

func Open

func Open(opt Options) (*Store, error)

Open prepares a store on the repository containing opt.Dir.

func (*Store) Find

func (s *Store) Find(subject string) ([]Found, error)

Find returns the latest stored result of every key of a subject, newest first. It reads the local ref only.

func (*Store) FreezeTip

func (s *Store) FreezeTip()

FreezeTip reads the local ref once and answers every later read from that commit and its index, with no git process: for a caller that only reads (`verify`, `show`) and asks hundreds of times. Do not write through a frozen store.

func (*Store) Gc

func (s *Store) Gc() (GcStats, error)

Gc compacts the branch: one new commit on top of the tip (never a rewrite of the shared history) whose tree holds the latest result of every key and every run (run-only history included, so Runs is the same before and after) in segments of about SegmentTarget runs, with a dictionary trained on the runs when there are TrainMin or more of them, and none (plain zstd) below that. With a remote the commit is pushed like any Put's, as a fast-forward; a push that loses a race is fetched, replayed on the new tip and retried, and one that fails for another reason stays pending (PendingPush).

Gc runs by itself after a Put once the branch holds GcSegments segments, or TrainMin runs with no dictionary yet (see maybeGc); it is also callable on its own.

func (*Store) Lookup

func (s *Store) Lookup(keys []Key) (map[string]Found, error)

Lookup returns the stored result of each key, by Key.ID(). It reads the local ref only (call Sync first for fresh data); a corrupt segment is an error. sr:invariant cache/store-failures-not-misses

func (*Store) PendingPush

func (s *Store) PendingPush() error

PendingPush is why the last push of local results failed (nil when nothing is waiting). The results are stored locally regardless and pushed on a later Sync or Put.

func (*Store) Pull

func (s *Store) Pull() error

Pull brings the remote branch into the local ref, and nothing else: it never pushes and never writes a result. It is what a read-only command (`verify`, `show`) uses. A remote without the branch yet is not an error; only a failed fetch is.

func (*Store) Put

func (s *Store) Put(runs []Run) error

Put stores results as one new segment. The local ref moves first, so a result is never lost to a push that fails (offline, denied): it is pushed best-effort afterwards and retried by the next Sync or Put (PendingPush says why it is waiting). Concurrent writers never conflict: the segment is content-addressed, so on a lost race the store re-bases the same files onto the new tip.

func (*Store) Runs

func (s *Store) Runs() ([]Run, error)

Runs returns every run the local ref holds, each once, newest first. It reads the local ref only (call Sync first for fresh data); for a test or a reader that lists, not for a lookup.

func (*Store) Show

func (s *Store) Show(subject string) (string, error)

Show renders the stored results of a subject for a human.

func (*Store) Sync

func (s *Store) Sync() error

Sync brings the remote branch into the local ref and pushes local results the remote does not hold yet (a failed push is retried here). A remote without the branch yet is not an error. It is a no-op for a local-only store. Only a failed FETCH is an error: a push that fails leaves the results local and is reported by PendingPush.

func (*Store) Tip

func (s *Store) Tip() string

Tip is the commit the local results ref points at ("" if none): what a result memo is keyed by, so a new `run` (which moves it) invalidates the memo.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL