Per-.erl and per-.hrl findings: runs the three resolvers
(test-module helpers, missing behaviours, missing headers) on a
single added file and returns the typed reasons plus the
diagnostic counters the caller merges into Diagnostics.
The added lines of a patch’s hunks as one blob plus a map from blob
line to file line. The target-axis resolvers scan the blob and
report a blob line; the map turns it into the file line the reason
shows.
Compares a declared behaviour’s -callback surface between the two
trees: the case where a pick adds an implementation written against
the source’s callback set and lands on a target whose set is wider
or shape-different. First-party behaviours only, the ones no pin
snapshot covers. A legacy behaviour that declares its surface
through behaviour_info/1 has no -callback forms and is
invisible here, which withholds.
C6: the first verdict-pipeline integration of backhopper-cuttlefish.
backhopper-core stays free of the parser crate: the CLI extracts
IntroducedMapping values from CuttlefishFragments whose span
intersects an added region, and this module compares those values
against the pinned cuttlefish version and the target tree.
Resolves ?MACRO and #record references a patch adds against the
target tree: the case where a hunk applies cleanly but the symbol it
references is defined nowhere the target reaches. Both are
directive-defined (-define, -record) and defined in the file or its
includes, so one tree walk gathers both. It gathers type
declarations too: the exported-type axis needs the same closure.
read_target is injected: core stays I/O-free.
Resolves -export_type entries a patch adds against the type
declarations the target module reaches. A module cannot export a
type it does not define, so an entry naming a type the target
declares under another name is an erlc error the pick introduces:
the case where a rename landed on the source branch and never
cascaded.
Extractor for m:f/a references carried as arguments to a known
indirection form: meck expectations, rpc:call, erpc:call,
rabbit_misc:rpc_call, and the RabbitMQ CT broker rpc helpers. The
atoms naming the referenced function are argument payload to the
call-site extractor, so without this pass a test ported from a newer
branch can reference a function the target branch never had and the
target-tree axis reports nothing. One level of unwrapping covers a
meck expectation reached through an rpc helper, the observed
incident’s shape.
Resolves unqualified f(Args) calls a patch adds against the target
module’s own function set: the case where a hunk calls a local
function a sibling commit introduced that the target branch lacks.
A call that does resolve against the module’s own definitions gets
its -spec return shape compared between the checkouts, with the
same comparator and tally semantics as the qualified axis.
C2: option-map key drift (OptionKeyUnknownOnPin). A map key found
in added lines fires only when it is a recognized option-type key
on the source side and absent from the same type on the target
pin. Both-side membership is the entire noise filter.
Resolves qualified m:f/a calls a patch adds against the called
module’s exports on the target tree: the snapshot-free equivalent
of local_call_resolve for the qualified case. A call is flagged
only when its module is first-party (present on the target tree and
covered by no pin snapshot), the export set is fully readable, and
neither the target nor the patch exports f/a. A call that does
resolve gets its -spec return shape compared between the source
and target checkouts, with the same comparator and guards the
tracked-dependency axis uses; every withheld comparison is counted
in a ShapeCheckTally so a shape-blind round is distinguishable
from a compared-clean one. Everything else is withheld and left to
the build.
Per-pin path routing: which configured project owns each touched
path, so a pin’s verdict can promote to OutOfScopeFor or
Untracked instead of firing a misleading FileAbsent row.
C5: a new test suite added to an app whose Makefile dispatches
suites by explicit registration (a family-declared marker) must be
referenced from that Makefile. read_target is injected: core
stays I/O-free.
Per-touched-path classification against an optional target-branch
tree. Pure data; no I/O. CLI builds the inputs (TargetTreeIndex
plus PathTranslations) and merges the result into each pin’s
verdict.
Built-once-per-invocation index of every blob path in a target
tree. Backs the --target-repo-dir-path cross-branch backport
analyser. Pure data: construction from a live repository is in
backhopper-git.
Classify each hunk’s preimage against the target-tree content of one
file and return the drift reasons. Like the self-pin check above but
cross-branch: target_content is the file at the apply target, so
Missing predicts a textual conflict and Drifted a clean shifted
apply. added_lines_collide covers the add/add case the contiguous
preimage match alone cannot detect.