Argus.Corpus (Panoptes v0.13.0)

Copy Markdown View Source

Real-world checkouts as a regression corpus: a repository at the commit before a closed-issue fix, and at the fix, compiled once into a cache and analyzed in this VM.

Every rule that came out of the 2026-09 issue-mining pass was verified this way — the finding is present on the pre-fix tree and absent on the fix — and Argus.CorpusTest keeps that true, as part of the ordinary test suite. mix argus.corpus uses the same module to fetch the trees ahead of time and to tally every title across them, which is the noise check after a rule changes.

Layout

test/corpus/pairs.exs lists the pairs. Checkouts live under ARGUS_CORPUS_DIR (default ~/.cache/argus/corpus), one directory per <repo>-<sha7>, compiled in MIX_ENV=dev with the project's own dependencies; a marker file records a successful compile so a warm run costs only the analysis. Nothing is added to the project's dependency set: argus runs over its ebin from this VM.

The project's elixir: requirement is relaxed so an old tree builds on the current toolchain; a pair may name an elixir: version instead, exported as ASDF_ELIXIR_VERSION for the compile.

Summary

Functions

Runs every analysis over a checkout's beams; the findings as Argus.run_analyses/2 returns them.

The checkout for one side of a pair: :pre or :fix.

Clones (if absent) and compiles (if not yet marked) one checkout.

The issue pairs, from test/corpus/pairs.exs.

Whether the pair's finding is among the results: its analysis and title, and — when the pair names a module: — anchored in that module. The module matters on the fix side: the same title can be true of another module in the tree (db_connection has two foreign starters; the fix removed one).

Where checkouts live.

The {analysis, title} pairs among findings.

Types

checkout()

@type checkout() :: %{name: String.t(), dir: String.t(), sha: String.t()}

pair()

@type pair() :: %{
  :repo => String.t(),
  :issue => String.t(),
  :pre => String.t(),
  optional(:fix) => String.t(),
  optional(:elixir) => String.t(),
  optional(:module) => String.t(),
  finding: {atom(), String.t()}
}

Functions

analyze(beams)

@spec analyze([Path.t()]) :: {:ok, map()} | {:error, term()}

Runs every analysis over a checkout's beams; the findings as Argus.run_analyses/2 returns them.

checkout(pair, side)

@spec checkout(pair(), :pre | :fix) :: checkout() | nil

The checkout for one side of a pair: :pre or :fix.

ensure(pair, side)

@spec ensure(pair(), :pre | :fix) :: {:ok, [Path.t()]} | {:error, String.t()}

Clones (if absent) and compiles (if not yet marked) one checkout.

Returns the .beam files of the project's own application, or an error naming the step that failed and its log.

pairs()

@spec pairs() :: [pair()]

The issue pairs, from test/corpus/pairs.exs.

present?(map, pair)

@spec present?(map(), pair()) :: boolean()

Whether the pair's finding is among the results: its analysis and title, and — when the pair names a module: — anchored in that module. The module matters on the fix side: the same title can be true of another module in the tree (db_connection has two foreign starters; the fix removed one).

root()

@spec root() :: String.t()

Where checkouts live.

titles(map)

@spec titles(map()) :: MapSet.t({atom(), String.t()})

The {analysis, title} pairs among findings.