{
"$schema": "https://json-schema.org/draft-07/schema",
"batch_payload": {
"$defs": {
"AlreadyPresent": {
"description": "Advisory: the patch's content appears to already exist on the\ntarget. Never affects the verdict; q-port and the operator own\nthe exclusion decision.",
"properties": {
"content": {
"anyOf": [
{
"$ref": "#/$defs/ContentPresence"
},
{
"type": "null"
}
],
"description": "Tier-2 tally: the post-image is (partly) present in the tree."
},
"identical": {
"anyOf": [
{
"$ref": "#/$defs/TargetMatch"
},
{
"type": "null"
}
],
"description": "Tier-1 hit: an identical patch landed on the target."
}
},
"type": "object"
},
"AlreadyPresentSkipped": {
"description": "Why already-present detection could not run. Emitted instead of\nsilence: an invisible skip would read as \"not present\".",
"oneOf": [
{
"description": "The candidate commit object is absent from the target object\nstore (an unfetched branch, usually).",
"properties": {
"reason": {
"const": "candidate_missing_from_target_odb",
"type": "string"
},
"sha": {
"type": "string"
}
},
"required": [
"reason",
"sha"
],
"type": "object"
},
{
"description": "The candidate and the target tip share no history.",
"properties": {
"reason": {
"const": "no_merge_base",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "The target-side walk failed (shallow clone, corrupt object).",
"properties": {
"detail": {
"type": "string"
},
"reason": {
"const": "target_walk_failed",
"type": "string"
}
},
"required": [
"reason",
"detail"
],
"type": "object"
}
]
},
"ApplyConflictKind": {
"description": "The apply outcomes a divergence predictor consumes, ordered by\nseverity: a higher variant outranks a lower one on the same path, so\ndedup to one conflict per path is a `max`.",
"enum": [
"postimage_collision",
"preimage_missing",
"file_absent"
],
"type": "string"
},
"ApplyForecast": {
"description": "Per-path apply prediction for one `(commit, series)` row, computed\nfrom the target tree. Present exactly when a target context was\nsupplied.",
"properties": {
"paths": {
"additionalProperties": {
"$ref": "#/$defs/PathApplyOutcome"
},
"description": "Every assessed touched path, including ones absent on the\ntarget (`Conflict { FileAbsent }`).",
"type": "object"
}
},
"required": [
"paths"
],
"type": "object"
},
"ArgShape": {
"oneOf": [
{
"description": "Variable identifier (starts with `_` or capital letter).",
"properties": {
"kind": {
"const": "variable",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Atom literal: `foo`, `'quoted atom'`.",
"properties": {
"kind": {
"const": "atom",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"description": "Integer literal.",
"properties": {
"kind": {
"const": "integer",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Float literal.",
"properties": {
"kind": {
"const": "float",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Binary literal: `<<...>>`.",
"properties": {
"kind": {
"const": "binary",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "List literal: `[...]`.",
"properties": {
"kind": {
"const": "list",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Tuple literal: `{...}` (size is the number of elements).",
"properties": {
"kind": {
"const": "tuple",
"type": "string"
},
"size": {
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"required": [
"kind",
"size"
],
"type": "object"
},
{
"description": "Record reference: `#name{...}`.",
"properties": {
"kind": {
"const": "record",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"description": "String literal: `\"...\"`.",
"properties": {
"kind": {
"const": "string",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Anonymous fun: `fun ... end` or `fun mod:f/A`.",
"properties": {
"kind": {
"const": "fun",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Anything the extractor cannot classify. Always matches.",
"properties": {
"kind": {
"const": "unknown",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
}
]
},
"ArtifactKind": {
"oneOf": [
{
"description": "`<<<<<<<`, `=======`, `>>>>>>>`, or `||||||| ` marker present in a\ntouched file. The cherry-pick driver left a conflict unresolved.",
"properties": {
"artifact_kind": {
"const": "conflict_marker",
"type": "string"
},
"marker": {
"$ref": "#/$defs/ConflictMarker"
}
},
"required": [
"artifact_kind",
"marker"
],
"type": "object"
},
{
"description": "`-export([f/N])` line without a matching clause defining `f/N`.\nCompiles, then crashes at runtime on the first call.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"artifact_kind": {
"const": "export_without_body",
"type": "string"
},
"function": {
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"artifact_kind",
"module",
"function",
"arity"
],
"type": "object"
}
]
},
"BatchQuery": {
"description": "One series queried by the batch. Holds the pin set used during\nevaluation so consumers can correlate per-row results.",
"properties": {
"pins": {
"items": {
"$ref": "#/$defs/PinPayload"
},
"type": "array"
},
"series": {
"type": "string"
}
},
"required": [
"series",
"pins"
],
"type": "object"
},
"BatchResult": {
"description": "One row in the batch result set.",
"properties": {
"apply": {
"anyOf": [
{
"$ref": "#/$defs/ApplyForecast"
},
{
"type": "null"
}
],
"description": "Apply-axis prediction for this row. `None` means no target\ncontext was supplied, so the axis was not evaluated: never\n\"clean\". A producer with a target context always emits `Some`,\neven when the patch touched zero files."
},
"commit": {
"type": "string"
},
"diagnostics": {
"$ref": "#/$defs/Diagnostics"
},
"parent_count": {
"default": null,
"description": "Number of parents of the evaluated commit: 1 for plain\ncommits, 2 for PR merges, 3+ for octopus merges. `None` only\nwhen the envelope was produced by a pre-v7 binary; v7\nproducers always emit it.",
"format": "uint32",
"minimum": 1,
"type": [
"integer",
"null"
]
},
"patch_facts": {
"$ref": "#/$defs/PatchFacts"
},
"pr_commits": {
"default": null,
"description": "Inner PR-branch commits for 2-parent merge SHAs. `None` for\nnon-2-parent merges and non-merge SHAs.\n\nDo NOT add `skip_serializing_if = \"Option::is_none\"`. The\n`None` vs `Some(vec![])` distinction is part of the wire contract.",
"items": {
"$ref": "#/$defs/PrCommit"
},
"type": [
"array",
"null"
]
},
"series": {
"type": "string"
},
"target_findings": {
"anyOf": [
{
"$ref": "#/$defs/TargetFindings"
},
{
"type": "null"
}
],
"description": "Symbol-axis target findings for this row. `None` means no\ntarget context was supplied, so the axis was not evaluated:\nnever \"clean\". A producer with a target context always emits\n`Some`, even when no check produced a finding."
},
"touched_paths": {
"default": [],
"description": "Paths the analysed patch touched, in diff-encounter order.\nAlways emitted; an empty vec means the patch touched zero\nfiles.",
"items": {
"type": "string"
},
"type": "array"
},
"verdict": {
"$ref": "#/$defs/SeriesVerdict"
},
"verdict_fingerprint": {
"anyOf": [
{
"$ref": "#/$defs/VerdictFingerprint"
},
{
"type": "null"
}
],
"description": "Stable join key tying this row's verdict to a later build\noutcome. Absent for uncacheable rows (`--no-cache`, an\nunresolvable pin) and pre-fingerprint producers."
}
},
"required": [
"commit",
"series",
"verdict"
],
"type": "object"
},
"BumpStatus": {
"description": "Snapshot-store status of a bumped-to pin version.",
"oneOf": [
{
"description": "The bumped dep is not a tracked project; nothing to vet.",
"properties": {
"state": {
"const": "untracked",
"type": "string"
}
},
"required": [
"state"
],
"type": "object"
},
{
"description": "No snapshot for the bumped-to version; `note` carries the remedy.",
"properties": {
"note": {
"type": "string"
},
"state": {
"const": "snapshot_missing",
"type": "string"
}
},
"required": [
"state",
"note"
],
"type": "object"
},
{
"properties": {
"state": {
"const": "snapshot_present",
"type": "string"
}
},
"required": [
"state"
],
"type": "object"
}
]
},
"ConflictMarker": {
"oneOf": [
{
"const": "ours",
"description": "`<<<<<<<` line: start of the local side.",
"type": "string"
},
{
"const": "divider",
"description": "`=======` line: divider between sides.",
"type": "string"
},
{
"const": "theirs",
"description": "`>>>>>>>` line: end of the incoming side.",
"type": "string"
},
{
"const": "ancestor",
"description": "`||||||| ` line: base ancestor marker from a 3-way diff.",
"type": "string"
}
]
},
"ContentPresence": {
"description": "Tier-2 advisory: how much of the patch's post-image already exists\nin the named pin's tree. A tally, never a boolean: partial presence\nis common and the fraction is the signal.",
"properties": {
"hunks_already_applied": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"hunks_ambiguous": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"hunks_considered": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"hunks_low_confidence": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"per_file": {
"additionalProperties": {
"$ref": "#/$defs/HunkTally"
},
"type": "object"
},
"pin": {
"description": "The pin whose evaluation produced the tally. In cross-branch\nmode the self pin resolves to the target branch, so its tally\nis the target-tree answer.",
"type": "string"
}
},
"required": [
"pin",
"hunks_already_applied",
"hunks_considered",
"hunks_ambiguous",
"hunks_low_confidence"
],
"type": "object"
},
"DepPinDivergence": {
"description": "A dependency whose `rabbitmq-components.mk` pin differs between\nthe source commit's tree and the target tree, and that an app\ntouched by the patch (transitively) depends on. Advisory only.",
"properties": {
"dep": {
"type": "string"
},
"source": {
"description": "Pin at the source commit, e.g. `hex 2.16.0`.",
"type": "string"
},
"target": {
"description": "Pin at the target tree, e.g. `hex 2.13.0`.",
"type": "string"
}
},
"required": [
"dep",
"source",
"target"
],
"type": "object"
},
"Diagnostics": {
"description": "Series-wide diagnostic envelope. Strictly separate from `Verdict`\nso untracked-call signals never leak into machine-readable verdicts.",
"properties": {
"already_present": {
"anyOf": [
{
"$ref": "#/$defs/AlreadyPresent"
},
{
"type": "null"
}
],
"description": "Advisory: the patch's content appears to already exist on the\ntarget (tier-1 identical patch, tier-2 content tally, or both)."
},
"already_present_skipped": {
"anyOf": [
{
"$ref": "#/$defs/AlreadyPresentSkipped"
},
{
"type": "null"
}
],
"description": "Why already-present detection was skipped, when it was."
},
"context_refs_missing": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"description": "In-scope references on *context* lines that do not resolve at\nsome pin, per module. Pre-existing target facts: never reasons.",
"type": "object"
},
"dep_pin_divergence": {
"description": "Dep pins that diverge between source and target trees and are\nreachable from the apps this patch touches.",
"items": {
"$ref": "#/$defs/DepPinDivergence"
},
"type": "array"
},
"indirect_call_checks": {
"$ref": "#/$defs/IndirectCallTally",
"description": "What the indirect-reference check (meck expectations and rpc\nforms) did with each recognized occurrence: resolved against the\ntarget module, or seen with an unreadable arity and withheld."
},
"local_call_shape_checks": {
"$ref": "#/$defs/ShapeCheckTally",
"description": "The same tally for local calls: resolved unqualified calls, compared or\nwithheld. Kept apart from the qualified tally so one axis's\ncoverage never reads as the other's."
},
"macro_value_checks": {
"$ref": "#/$defs/MacroValueTally",
"description": "Same-file `-define` value comparisons over macros the patch\nuses: compared, or withheld and why."
},
"missing_test_modules": {
"additionalProperties": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"type": "object"
},
"description": "Per-`_SUITE.erl` map of `helper_module -> call_site_count`. The\nalways-on diagnostic form of\n`Reason::TestModuleSymbolMissing`: emitted by the parse pass\neven without a target tree (which is why the inner key is the\n`ModuleName` rather than a resolved-or-not bit). When\n`--target-repo-dir-path` is supplied the resolver re-checks this\nmap and promotes the absent ones to typed reasons. The nested\n`BTreeMap` shape keeps the JSON envelope serialisable without\na custom composite-key encoder.",
"type": "object"
},
"pin_bumps": {
"description": "Dep pins this patch itself changes or introduces in the root\n`rabbitmq-components.mk`.",
"items": {
"$ref": "#/$defs/PinBump"
},
"type": "array"
},
"qualified_call_shape_checks": {
"$ref": "#/$defs/ShapeCheckTally",
"description": "What the live qualified-call gate's return-shape check did with\neach first-party resolved call: compared, or withheld and why."
},
"suggested_suites": {
"description": "SUITE names worth running for the patch, derived from touched paths.\nPopulated even when the verdict promotes to `Inapplicable` so that\nschema-only and config-only diffs still surface relevant suites.",
"items": {
"type": "string"
},
"type": "array"
},
"unanalyzed": {
"$ref": "#/$defs/Unanalyzed"
},
"unattributed_paths": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"description": "Touched paths no configured project owns, tallied by their\nfirst two path components. The evidence behind an\n`Inapplicable { Untracked }` verdict.",
"type": "object"
},
"untracked_calls": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"type": "object"
},
"untracked_records": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"type": "object"
}
},
"type": "object"
},
"FileLoggingStyle": {
"properties": {
"dominant": {
"$ref": "#/$defs/LoggingStyle"
},
"logger_macro_sites": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"rabbit_log_sites": {
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"required": [
"dominant",
"logger_macro_sites",
"rabbit_log_sites"
],
"type": "object"
},
"HunkTally": {
"description": "Per-file hunk counters for the content-presence check.",
"properties": {
"ambiguous": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"applied": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"considered": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"low_confidence": {
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"required": [
"applied",
"considered",
"ambiguous",
"low_confidence"
],
"type": "object"
},
"InapplicableReason": {
"oneOf": [
{
"properties": {
"reason": {
"const": "no_erlang_surface_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_docs_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_test_fixtures_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_schema_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_makefile_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_mix_exs_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_ci_workflow_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_app_src_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_rebar_config_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "Every changed `.erl` hunk is a Variant A unwrap: dropping\n`-ifdef(TEST).` or `-endif.` around an `-export(...)` directive,\nor rewriting `-compile(export_all).` to an explicit\n`-export([...])`. No call sites, no specs, no bodies touched:\nonly test-visibility metadata.",
"properties": {
"reason": {
"const": "only_test_visibility_changed",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "The patch touches Erlang surface but every referenced symbol\nresolves to the self-pin or to a local definition: every\ntracked-dep pin has zero in-scope references. Without this\nreason the operator would see many vacuous `Compatible`\nrows for a patch that backhopper genuinely has no signal on.",
"properties": {
"reason": {
"const": "only_self_surface_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "Every touched path is in a sibling project's scope, not this\npin's. The pin has nothing to say about the patch. `project`\nnames the first sibling project (alphabetical) that owns the\nout-of-scope paths.",
"properties": {
"project": {
"type": "string"
},
"reason": {
"const": "out_of_scope_for",
"type": "string"
}
},
"required": [
"reason",
"project"
],
"type": "object"
},
{
"description": "Every touched path is unclaimed by any configured project's\nscan_paths or app_roots. Vendored files, docs, build scripts.",
"properties": {
"reason": {
"const": "untracked",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "`--target-repo-dir-path` was supplied and every touched path\nis missing from the target tree, with no configured\ntranslation mapping any of them. The patch as written does\nnot apply to the target.",
"properties": {
"paths": {
"items": {
"type": "string"
},
"type": "array"
},
"reason": {
"const": "paths_missing_on_target",
"type": "string"
}
},
"required": [
"reason",
"paths"
],
"type": "object"
}
]
},
"IncludeDirective": {
"description": "`-include` and `-include_lib` are syntactically distinct: the\nformer takes a relative-to-source path, the latter an\n`application/include/file.hrl` shape resolved through OTP's lib\npath. The variant preserves which form the source used so the\nremediation text can match.",
"oneOf": [
{
"properties": {
"form": {
"const": "include",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"form",
"path"
],
"type": "object"
},
{
"properties": {
"form": {
"const": "include_lib",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"form",
"path"
],
"type": "object"
}
]
},
"IndirectCallForm": {
"description": "Which recognized call form carried an indirect MFA reference. Names\nthe innermost form: a meck expectation reached through an rpc helper\nis `MeckExpect`, not the helper.",
"enum": [
"meck_expect",
"rpc_call",
"erpc_call",
"ct_broker_helper_rpc",
"rabbit_misc_rpc_call"
],
"type": "string"
},
"IndirectCallTally": {
"description": "What the indirect-reference check did with each recognized form\noccurrence. `checked` counts deduplicated resolved sites, the same\ndedup the reasons use; flagged sites are visible in the reasons,\nnot double-counted here.",
"properties": {
"checked": {
"description": "Module first-party, export and definition sets readable: the\nmembership check ran.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_dynamic": {
"description": "Module and function were literal atoms but the arity source was\nnot statically readable: a variable argument list, a list with a\ncons tail, or a non-literal arity argument.",
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"KhepriSignals": {
"properties": {
"touches_dual_branch": {
"default": false,
"type": "boolean"
},
"touches_khepri_module": {
"default": false,
"type": "boolean"
},
"touches_only_khepri_branch": {
"default": false,
"type": "boolean"
},
"uses_khepri_macros": {
"default": false,
"type": "boolean"
}
},
"type": "object"
},
"LoggingStyle": {
"enum": [
"logger_macros",
"rabbit_log_module",
"mixed",
"none"
],
"type": "string"
},
"MacroValueTally": {
"description": "What the macro-value check did with each `?MACRO` the patch uses:\ncompared, or withheld and why. Same-file `-define`s only; anything\nreached another way is withheld, never guessed.",
"properties": {
"compared": {
"description": "Defined exactly once same-file on both sides; values compared.\nDrift is visible in the reasons, not double-counted here.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_definition_elsewhere": {
"description": "Not defined same-file on both sides: the definition is in an\ninclude, or moved between files across the trees.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_multiple_defines": {
"description": "Defined more than once in the file on either side (`-ifdef`\nbranches): either value could be live.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_no_source": {
"description": "The touched file was not readable on the source side.",
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"Mfa": {
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"module",
"function",
"arity"
],
"type": "object"
},
"NeedsPin": {
"description": "The minimum pin that satisfies a missing-symbol reason: the typed\nordering payload q-port turns into a \"bump must land first\" edge.",
"properties": {
"project": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"project",
"tag"
],
"type": "object"
},
"PatchFacts": {
"description": "Source classifiers on the patch. Strictly separate from `Verdict` reasons.",
"properties": {
"introduces_versioned_record": {
"items": {
"type": "string"
},
"type": "array",
"uniqueItems": true
},
"khepri_signals": {
"$ref": "#/$defs/KhepriSignals"
},
"logging_style": {
"additionalProperties": {
"$ref": "#/$defs/FileLoggingStyle"
},
"type": "object"
}
},
"type": "object"
},
"PathApplyOutcome": {
"description": "How one touched path is predicted to apply to the target tree.\nRanked by [`PathApplyOutcome::severity`]; payload-carrying variants\nkeep the enum out of `Ord`.",
"oneOf": [
{
"description": "Every hunk's preimage matches at its expected line.",
"properties": {
"outcome": {
"const": "clean_exact",
"type": "string"
}
},
"required": [
"outcome"
],
"type": "object"
},
{
"description": "Applies, but at least one hunk's preimage was found at a shifted\nline. `line_delta` is the largest-magnitude shift.",
"properties": {
"line_delta": {
"format": "int64",
"type": "integer"
},
"outcome": {
"const": "clean_drifted",
"type": "string"
}
},
"required": [
"outcome",
"line_delta"
],
"type": "object"
},
{
"description": "The path could not be assessed; stated, never silent.",
"properties": {
"outcome": {
"const": "unassessed",
"type": "string"
},
"reason": {
"$ref": "#/$defs/UnassessedReason"
}
},
"required": [
"outcome",
"reason"
],
"type": "object"
},
{
"description": "At least one hunk predicts a conflict. `kind` is the worst\nconflict kind across the path's hunks.",
"properties": {
"kind": {
"$ref": "#/$defs/ApplyConflictKind"
},
"outcome": {
"const": "conflict",
"type": "string"
}
},
"required": [
"outcome",
"kind"
],
"type": "object"
}
]
},
"Pin": {
"properties": {
"project": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"project",
"tag"
],
"type": "object"
},
"PinBump": {
"description": "A dep pin the candidate commit itself changes or introduces in the\nroot `rabbitmq-components.mk`. Advisory only: the verdict on a\nbump-only diff stays `Inapplicable`, this is the evidence behind it.",
"properties": {
"dep": {
"type": "string"
},
"from": {
"description": "Pin before the commit, e.g. `hex 2.16.0`; `None` when the\ncommit introduces the pin.",
"type": [
"string",
"null"
]
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/BumpStatus"
},
{
"type": "null"
}
],
"description": "Snapshot-store assessment of the bumped-to version. Detection\nis a pure function of the patch and may be cached; the store's\ncontents are not a cache-key input, so this field is filled\npost-cache and cached values carry `None`."
},
"to": {
"description": "Pin after the commit, e.g. `hex 2.17.1`.",
"type": "string"
}
},
"required": [
"dep",
"to"
],
"type": "object"
},
"PinPayload": {
"description": "On-wire pin shape used inside `BatchQuery`. Distinct from\n`crate::model::pin::Pin` because the wire form is a `(project, tag)`\nprojection without the resolution logic.",
"properties": {
"project": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"project",
"tag"
],
"type": "object"
},
"PinVerdict": {
"properties": {
"pin": {
"$ref": "#/$defs/Pin"
},
"source_delta_details": {
"items": {
"$ref": "#/$defs/SourceDelta"
},
"type": "array"
},
"touched": {
"$ref": "#/$defs/TouchedKinds"
},
"tracked_ref_details": {
"items": {
"$ref": "#/$defs/SymbolRef"
},
"type": "array"
},
"tracked_refs": {
"default": 0,
"format": "uint",
"minimum": 0,
"type": "integer"
},
"verdict": {
"$ref": "#/$defs/Verdict"
}
},
"required": [
"pin",
"verdict"
],
"type": "object"
},
"PrCommit": {
"description": "One commit on the PR-branch side of a 2-parent merge.",
"properties": {
"author_date": {
"type": "string"
},
"kind": {
"$ref": "#/$defs/PrCommitKind"
},
"sha": {
"type": "string"
},
"subject": {
"type": "string"
}
},
"required": [
"sha",
"subject",
"author_date",
"kind"
],
"type": "object"
},
"PrCommitKind": {
"description": "Classification of a PR-branch commit's role.\n\n`#[non_exhaustive]` so future, richer taxonomies (test-only,\ndocs-only, dependency-bump, etc.) can add variants without a\nbreaking change.",
"oneOf": [
{
"const": "substantive",
"description": "Default: substantive change worth reviewing.",
"type": "string"
},
{
"const": "conflict_resolution",
"description": "Subject matched the conflict-resolution catalog AND the file\nset was a strict subset of prior PR-branch commits.",
"type": "string"
},
{
"const": "review_feedback",
"description": "Subject indicated the commit applied code-review feedback.",
"type": "string"
},
{
"const": "fixup",
"description": "`git --fixup` auto-generated or the manual `fixup:` convention.",
"type": "string"
},
{
"const": "wip_or_cleanup",
"description": "Subject was `WIP` or bare `Cleanup`.",
"type": "string"
}
]
},
"Reason": {
"oneOf": [
{
"properties": {
"first_seen_at_tag": {
"description": "Earliest snapshot tag strictly later than the pin where the\nsymbol appears. `Some` reclassifies the reason as\nadaptable: land the dep pin bump first.",
"type": [
"string",
"null"
]
},
"kind": {
"const": "missing_symbol",
"type": "string"
},
"needs_pin_at_least": {
"anyOf": [
{
"$ref": "#/$defs/NeedsPin"
},
{
"type": "null"
}
]
},
"suggested_replacement": {
"anyOf": [
{
"$ref": "#/$defs/SymbolRef"
},
{
"type": "null"
}
]
},
"symbol": {
"$ref": "#/$defs/SymbolRef"
}
},
"required": [
"kind",
"symbol"
],
"type": "object"
},
{
"properties": {
"expected": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"expected_available_at": {
"description": "Earliest snapshot tag strictly later than the pin exporting\nthe expected arity. Same bump-first semantics as\n`MissingSymbol::first_seen_at_tag`.",
"type": [
"string",
"null"
]
},
"found": {
"items": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"type": "array"
},
"function": {
"type": "string"
},
"kind": {
"const": "arity_changed",
"type": "string"
},
"module": {
"type": "string"
},
"needs_pin_at_least": {
"anyOf": [
{
"$ref": "#/$defs/NeedsPin"
},
{
"type": "null"
}
]
}
},
"required": [
"kind",
"module",
"function",
"expected",
"found"
],
"type": "object"
},
{
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"expected_spec": {
"type": "string"
},
"found_spec": {
"type": "string"
},
"function": {
"type": "string"
},
"kind": {
"const": "signature_changed",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"function",
"arity",
"expected_spec",
"found_spec"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "file_absent",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path"
],
"type": "object"
},
{
"properties": {
"hunk_index": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "context_drift",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"hunk_index"
],
"type": "object"
},
{
"description": "The contiguous preimage block (Context and Removed lines from\nthe hunk) was found verbatim at a different starting line.\nCherry-pick adapters handle this with the `-x` trailer; the\noperator just needs the delta to confirm the patch's intent\nstill applies.",
"properties": {
"hunk_index": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "preimage_drifted",
"type": "string"
},
"line_delta": {
"format": "int",
"type": "integer"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"hunk_index",
"line_delta"
],
"type": "object"
},
{
"description": "The hunk's preimage matches, but its added lines land at a file\nedge where the target already has divergent content the base\nlacked: an add/add a contiguous preimage match cannot detect. The\n3-way cherry-pick conflicts where the preimage-only check reads\nclean. Non-blocking: the operator resolves the overlap.",
"properties": {
"hunk_index": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "postimage_collision",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"hunk_index"
],
"type": "object"
},
{
"description": "The preimage block does not appear anywhere in the file. The\npatch was authored against a tree where the lines existed; on\nthis pin they don't. Structurally inapplicable: the operator\nneeds an excerpt to reason about why.",
"properties": {
"hunk_index": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "preimage_missing",
"type": "string"
},
"path": {
"type": "string"
},
"preimage_excerpt": {
"type": "string"
}
},
"required": [
"kind",
"path",
"hunk_index",
"preimage_excerpt"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "deprecated_usage",
"type": "string"
},
"replacement": {
"anyOf": [
{
"$ref": "#/$defs/SymbolRef"
},
{
"type": "null"
}
]
},
"since": {
"type": [
"string",
"null"
]
},
"symbol": {
"$ref": "#/$defs/SymbolRef"
}
},
"required": [
"kind",
"symbol"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "now_hidden",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module"
],
"type": "object"
},
{
"properties": {
"expected": {
"items": {
"type": "string"
},
"type": "array"
},
"found": {
"items": {
"type": "string"
},
"type": "array"
},
"kind": {
"const": "record_fields_changed",
"type": "string"
},
"record": {
"type": "string"
}
},
"required": [
"kind",
"record",
"expected",
"found"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "unsupported_file_type",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "untracked_module_missing",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module"
],
"type": "object"
},
{
"description": "Call-site argument shapes don't satisfy any clause head at the\npin. Emitted when both the call and the pin's clause patterns\nare concrete enough to compare; `Unknown` on either side\nsuppresses the reason.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"call_args": {
"items": {
"$ref": "#/$defs/ArgShape"
},
"type": "array"
},
"function": {
"type": "string"
},
"kind": {
"const": "clause_mismatch",
"type": "string"
},
"module": {
"type": "string"
},
"pin_clauses": {
"items": {
"items": {
"$ref": "#/$defs/ArgShape"
},
"type": "array"
},
"type": "array"
}
},
"required": [
"kind",
"module",
"function",
"arity",
"call_args",
"pin_clauses"
],
"type": "object"
},
{
"description": "Patch references an MFA owned by the self-project but absent from the\nresolved self-snapshot. `suggested_source_for_prereq` is filled only\nwith `--suggest-prereqs`.",
"properties": {
"kind": {
"const": "missing_prereq",
"type": "string"
},
"self_branch": {
"type": "string"
},
"suggested_source_for_prereq": {
"type": [
"string",
"null"
]
},
"symbol": {
"$ref": "#/$defs/SymbolRef"
}
},
"required": [
"kind",
"symbol",
"self_branch"
],
"type": "object"
},
{
"description": "Pre-flight syntactic damage in a touched file: an unresolved\nmerge-conflict marker, an exported function with no definition, etc.",
"properties": {
"artifact": {
"$ref": "#/$defs/ArtifactKind"
},
"kind": {
"const": "syntactic_artifact",
"type": "string"
},
"line": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"line",
"artifact"
],
"type": "object"
},
{
"description": "Patch changes a `-callback` signature; an implementer still has the old one.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"expected_after_patch": {
"type": "string"
},
"implementer": {
"type": "string"
},
"implementer_signature": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_signature_changed",
"type": "string"
}
},
"required": [
"kind",
"behaviour",
"callback",
"arity",
"expected_after_patch",
"implementer",
"implementer_signature"
],
"type": "object"
},
{
"description": "Patch removes a required callback; implementer still exports it.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"implementer": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_removed",
"type": "string"
}
},
"required": [
"kind",
"behaviour",
"callback",
"arity",
"implementer"
],
"type": "object"
},
{
"description": "Patch adds a required callback; implementer is missing the export.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"implementer": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_added",
"type": "string"
}
},
"required": [
"kind",
"behaviour",
"callback",
"arity",
"implementer"
],
"type": "object"
},
{
"description": "Patch touches a path absent on pin, but a module of the same basename exists elsewhere.",
"properties": {
"kind": {
"const": "module_relocated",
"type": "string"
},
"module": {
"type": "string"
},
"patch_path": {
"type": "string"
}
},
"required": [
"kind",
"module",
"patch_path"
],
"type": "object"
},
{
"description": "Wire-bearing macro value differs between source and pin.",
"properties": {
"after": {
"type": "string"
},
"before": {
"type": "string"
},
"kind": {
"const": "wire_constant_changed",
"type": "string"
},
"macro_name": {
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"macro_name",
"before",
"after"
],
"type": "object"
},
{
"description": "`version/0` advanced without the matching historical-implementation module.",
"properties": {
"advertised_version_after": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"advertised_version_before": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"expected_historical_module": {
"type": "string"
},
"kind": {
"const": "historical_implementation_missing",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"advertised_version_before",
"advertised_version_after",
"expected_historical_module"
],
"type": "object"
},
{
"description": "Function bodies drifted at the same advertised `version/0`. Mixed-version cluster risk.",
"properties": {
"advertised_version": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"functions": {
"items": {
"type": "string"
},
"type": "array"
},
"kind": {
"const": "wire_contract_body_drift",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"functions",
"advertised_version"
],
"type": "object"
},
{
"description": "`version/0` decreased pin → patch.",
"properties": {
"kind": {
"const": "wire_contract_regression",
"type": "string"
},
"module": {
"type": "string"
},
"patch_version": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"pin_version": {
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"required": [
"kind",
"module",
"pin_version",
"patch_version"
],
"type": "object"
},
{
"description": "Spec return shape differs between source and pin for a referenced MFA.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "return_shape_mismatch",
"type": "string"
},
"module": {
"type": "string"
},
"pin_signature": {
"type": "string"
},
"source_signature": {
"type": "string"
}
},
"required": [
"kind",
"module",
"function",
"arity",
"source_signature",
"pin_signature"
],
"type": "object"
},
{
"description": "A type-reference inside a `-spec`, `-callback`, `-type`, or\n`-opaque` attribute resolves to a name and arity that the pin\ndoes not expose via `-export_type`. Non-blocking: a missing\ntype alias is a dialyzer-level concern, not a load-time crash.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "missing_type",
"type": "string"
},
"module": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"module",
"name",
"arity"
],
"type": "object"
},
{
"description": "A touched path is absent from the target tree, but a\nconfigured `[[path_translation]]` rewrites it to a path that\ndoes exist on the target. Non-blocking: the operator (or the\ncherry-pick driver) rewrites the path before applying.",
"properties": {
"kind": {
"const": "path_rename",
"type": "string"
},
"source_path": {
"type": "string"
},
"target_path": {
"type": "string"
},
"translation": {
"$ref": "#/$defs/TranslationSource"
}
},
"required": [
"kind",
"source_path",
"target_path",
"translation"
],
"type": "object"
},
{
"description": "A touched path is absent on the target while others are present\nand no `[[path_translation]]` rewrites it. Non-blocking: dropping\nthe hunks for this path lets the rest apply. The all-absent case\nis `InapplicableReason::PathsMissingOnTarget`.",
"properties": {
"kind": {
"const": "target_path_absent",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path"
],
"type": "object"
},
{
"description": "A `_SUITE.erl` file in the patch references `missing_module:f/n`\nwhere `missing_module` resolves to no source file under any\nconfigured `FamilyDefaults.test_helper_search_paths` on the\ntarget tree. The cherry-pick compiles and the SUITE may even\nload, but every call to the missing helper crashes at runtime:\nthe failure pattern seen in the Jun 2026 v4.1.x → v4.0.x round\n(the `amqp_utils:connection_config/1` undef in\n`amqp10_connection_max_SUITE`). Non-blocking by default: the\ndiagnostic equivalent (`Diagnostics.missing_test_modules`)\nalways fires; the `Reason` variant fires only when\n`--target-repo-dir-path` is supplied and the resolution is\nauthoritative.",
"properties": {
"call_sites": {
"items": {
"$ref": "#/$defs/TestCallSite"
},
"type": "array"
},
"kind": {
"const": "test_module_symbol_missing",
"type": "string"
},
"missing_module": {
"type": "string"
},
"suite_path": {
"type": "string"
}
},
"required": [
"kind",
"suite_path",
"missing_module",
"call_sites"
],
"type": "object"
},
{
"description": "A touched `.erl` declares `-behaviour(behaviour)` (or\n`-behavior(...)`) where `behaviour` resolves to no source\nmodule on the target tree. `erlc` compiles with a warning,\nthen hook dispatch crashes at runtime. The `BehaviourCallback*`\nvariants model implementer drift; this one catches the\nmissing-behaviour-module case they do not.",
"properties": {
"behaviour": {
"type": "string"
},
"kind": {
"const": "behaviour_module_missing",
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"behaviour"
],
"type": "object"
},
{
"description": "A touched `.erl` or `.hrl` declares `-include(path)` or\n`-include_lib(app/include/file.hrl)` against a target tree that\ndoes not ship the resolved header. Compile-time failure rather\nthan runtime, but same user-facing shape as\n`TestModuleSymbolMissing`: looked fine on source, broken on\ntarget.",
"properties": {
"attempted_paths": {
"items": {
"type": "string"
},
"type": "array"
},
"include_directive": {
"$ref": "#/$defs/IncludeDirective"
},
"kind": {
"const": "header_file_missing",
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"include_directive",
"attempted_paths"
],
"type": "object"
},
{
"description": "A touched `.erl` or `.hrl` file references `?MACRO` on an added\nline, but `MACRO` is defined nowhere the target tree reaches (not\nin the file, its includes, or the patch itself) and is not\npredefined. Compiles on source, dangles on target. Non-blocking:\nthe operator drops or adapts the reference.",
"properties": {
"kind": {
"const": "macro_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"macro_name": {
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"macro_name",
"line"
],
"type": "object"
},
{
"description": "A touched `.erl` or `.hrl` file uses `#record{}` on an added\nline, but `record` is defined nowhere the target tree reaches and\nis not added by the patch. Same check as `MacroUndefinedOnTarget`\nfor the record namespace; non-blocking.",
"properties": {
"kind": {
"const": "record_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"record_name": {
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"record_name",
"line"
],
"type": "object"
},
{
"description": "A touched `.erl` file calls an unqualified `f/a` on an added line\nthat the target version of the same module neither defines,\nexports, imports, nor inherits as an auto-imported BIF. The\nsame check for the function namespace; non-blocking.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "local_call_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"function",
"arity",
"line"
],
"type": "object"
},
{
"description": "A touched `.erl` file calls a qualified `m:f/a` on an added line\nwhose module is a first-party module present on the target tree,\nbut the target version of that module does not export `f/a` (and\nthe patch does not add it). The qualified form of\n`LocalCallUndefinedOnTarget`, resolved against the called\nmodule's exports. Withheld when any pin snapshot already covers\nthe module, when it is absent from the tree, or when its export\nsurface is not fully readable. Non-blocking.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "qualified_call_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"module": {
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"module",
"function",
"arity",
"line"
],
"type": "object"
},
{
"description": "A qualified `m:f/a` call that resolves against the target tree\nhas a target-tree `-spec` return shape that disagrees with its\nsource-tree `-spec`. Same comparison as `ReturnShapeMismatch` on\nthe live, snapshot-free first-party axis: same comparator,\nnon-blocking like the rest of that axis. Only evaluated once the\ncall is confirmed to resolve; withheld when either side lacks a\n`-spec`.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "qualified_call_return_shape_drift",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"module": {
"type": "string"
},
"source_path": {
"type": "string"
},
"source_signature": {
"type": "string"
},
"target_signature": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"module",
"function",
"arity",
"source_signature",
"target_signature",
"line"
],
"type": "object"
},
{
"description": "An unqualified call that resolves against the target module's\nown definitions has a target-tree `-spec` return shape that\ndisagrees with its source-tree `-spec`. The local-call form of\n`QualifiedCallReturnShapeDrift`; imported resolutions are\nwithheld, since the callee's spec is in another module.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "local_call_return_shape_drift",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
},
"source_signature": {
"type": "string"
},
"target_signature": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"function",
"arity",
"source_signature",
"target_signature",
"line"
],
"type": "object"
},
{
"description": "A `?MACRO` the patch uses is defined in the touched file itself\non both trees, exactly once each, and the normalized `-define`\nbodies disagree: the compile-clean, behavior-divergent class.\nWithheld for definitions reached any other way. Non-blocking.",
"properties": {
"kind": {
"const": "macro_value_drift",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"macro_name": {
"type": "string"
},
"source_path": {
"type": "string"
},
"source_value": {
"type": "string"
},
"target_value": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"macro_name",
"source_value",
"target_value",
"line"
],
"type": "object"
},
{
"description": "The target's version of a behaviour the patch declares requires\na callback the source's version does not, and the target does\nnot list it as optional: an implementation written against the\nsource is missing it. `line` is the `-behaviour` attribute's\nline in the touched file. Non-blocking.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_added_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"behaviour",
"callback",
"arity",
"line"
],
"type": "object"
},
{
"description": "A callback both trees' versions of a declared behaviour declare\nhas a different normalized signature on the target. The whole\nsignature is compared, not just the return half: a callback\ncontract's argument types are the implementer's obligation.\nNon-blocking.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_drift_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
},
"source_signature": {
"type": "string"
},
"target_signature": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"behaviour",
"callback",
"arity",
"source_signature",
"target_signature",
"line"
],
"type": "object"
},
{
"description": "Declared versioned-machine module is touched but the snapshot\nhas no recorded `versioned_machine_version` on `side`.\nNon-blocking.",
"properties": {
"kind": {
"const": "versioned_machine_snapshot_missing",
"type": "string"
},
"module": {
"type": "string"
},
"side": {
"$ref": "#/$defs/SnapshotSide"
}
},
"required": [
"kind",
"module",
"side"
],
"type": "object"
},
{
"description": "Declared wire constants are touched but the snapshot's\n`wire_constants` vector lacks the listed macros on `side`.\n`macros` is sorted alphabetically. Non-blocking.",
"properties": {
"kind": {
"const": "wire_constant_bindings_missing",
"type": "string"
},
"macros": {
"items": {
"type": "string"
},
"type": "array"
},
"module": {
"type": "string"
},
"side": {
"$ref": "#/$defs/SnapshotSide"
}
},
"required": [
"kind",
"module",
"macros",
"side"
],
"type": "object"
},
{
"description": "A first-party `m:f/a` referenced as arguments to a mocking or\nrpc form (a meck expectation, `rpc:call`, `erpc:call`, or a CT\nbroker rpc helper) is neither exported nor defined by the target\ntree's module. Non-blocking: a meck expectation can install a\nfunction the module never had, so absence proves drift, not\nfailure.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "indirect_call_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"module": {
"type": "string"
},
"source_path": {
"type": "string"
},
"via": {
"$ref": "#/$defs/IndirectCallForm"
}
},
"required": [
"kind",
"source_path",
"module",
"function",
"arity",
"via",
"line"
],
"type": "object"
},
{
"description": "A touched `.erl` file adds an `-export_type([t/a])` entry naming\na type neither the target version of the same module declares\nnor the patch adds. An `erlc` error, unlike `MissingType`, which\nis dialyzer-level; non-blocking regardless, being a target-tree\nfinding rather than a pin verdict. Withheld when the target file\nis unreadable or declares a `parse_transform`, or when the added\nlist names a macro.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "exported_type_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
},
"type_name": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"type_name",
"arity",
"line"
],
"type": "object"
}
]
},
"RefOrigin": {
"description": "Which side of the hunk a reference was extracted from. `Added`\nlines are requirements the patch introduces; `Context` lines are\npre-existing facts about the target and never drive verdicts.\n`Added` orders first so a kind-level dedup keeps the stronger\norigin.",
"enum": [
"added",
"context"
],
"type": "string"
},
"ResolverClass": {
"description": "A class of symbol whose presence a backport can dangle on.",
"enum": [
"macro",
"include",
"behaviour",
"qualified_call",
"record",
"local_call",
"type",
"indirect_call"
],
"type": "string"
},
"ResolverCoverage": {
"description": "The set of classes a producer checks, stamped on a verdict envelope\nso a corpus row self-describes its producer's coverage. Stores only\nthe checked set: `unchecked` is derived, so a class can never be in\nboth or neither.",
"properties": {
"checked": {
"items": {
"$ref": "#/$defs/ResolverClass"
},
"type": "array",
"uniqueItems": true
}
},
"required": [
"checked"
],
"type": "object"
},
"SeriesSummary": {
"properties": {
"compatible": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"inapplicable": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"incompatible": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"requires_adaptation": {
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"required": [
"compatible",
"requires_adaptation",
"incompatible"
],
"type": "object"
},
"SeriesVerdict": {
"properties": {
"results": {
"items": {
"$ref": "#/$defs/PinVerdict"
},
"type": "array"
},
"summary": {
"$ref": "#/$defs/SeriesSummary"
}
},
"required": [
"results",
"summary"
],
"type": "object"
},
"ShapeCheckTally": {
"description": "What the live qualified-call gate's return-shape check did with\neach first-party resolved call. Never reasons: a withhold is not a\nfinding, but a round where most calls are shape-blind must read\ndifferently from a round where all of them were compared.",
"properties": {
"compared": {
"description": "Both sides had a `-spec` that parsed to a known type; the shapes\nwere compared. Drift is visible in the reasons, not double-counted\nhere.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_imported": {
"description": "The call resolved through an `-import`: the callee's `-spec`\nis in another module, so the calling module's tables cannot\ncompare it. Local-call axis only.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_no_source": {
"description": "The callee module was not readable on the source side: no\ncheckout was supplied, or the checkout has no file at the\nmodule's path (a defaulted `--repo-dir-path` that is not the\nsource tree lands here, not in `withheld_no_spec`).",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_no_spec": {
"description": "One or both sides declare no `-spec` for the called function.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_unknown_type": {
"description": "Both sides have a spec but at least one parses to\n`SpecType::Unknown`.",
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"SnapshotSide": {
"description": "Which side of a snapshot comparison the data is missing from.",
"enum": [
"source",
"target",
"both"
],
"type": "string"
},
"SourceDelta": {
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"module": {
"type": "string"
},
"source_spec": {
"type": "string"
},
"target_spec": {
"type": "string"
}
},
"required": [
"module",
"function",
"arity",
"source_spec",
"target_spec"
],
"type": "object"
},
"SymbolRef": {
"oneOf": [
{
"properties": {
"kind": {
"const": "behaviour",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module"
],
"type": "object"
},
{
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "callback",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"function",
"arity"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "function",
"type": "string"
},
"mfa": {
"$ref": "#/$defs/Mfa"
}
},
"required": [
"kind",
"mfa"
],
"type": "object"
},
{
"description": "A function reference whose arity could not be determined from\nthe source line (the call's closing paren sits on a later\nline). Resolves against a snapshot when *any* export carries\nthe name; never produces an arity mismatch.",
"properties": {
"function": {
"type": "string"
},
"kind": {
"const": "function_any_arity",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"function"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "macro",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "record",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "type",
"type": "string"
},
"module": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"module",
"name",
"arity"
],
"type": "object"
}
],
"properties": {
"origin": {
"$ref": "#/$defs/RefOrigin"
}
},
"type": "object"
},
"TargetFindings": {
"description": "Symbol-axis findings for one row, resolved against the target tree.\nPresent exactly when a target context was supplied; independent of\nevery pin verdict, so an inapplicable row still carries its\nfindings.",
"properties": {
"reasons": {
"description": "Every reason the live-axis target checks produced for this row,\nin production order.",
"items": {
"$ref": "#/$defs/Reason"
},
"type": "array"
}
},
"required": [
"reasons"
],
"type": "object"
},
"TargetMatch": {
"description": "A target commit found to carry the candidate's patch. The subject\nis included so consumers can auto-fill exclusion reasons without\na second git query.",
"properties": {
"commit": {
"type": "string"
},
"subject": {
"type": "string"
},
"via": {
"$ref": "#/$defs/TargetMatchKind"
}
},
"required": [
"commit",
"via",
"subject"
],
"type": "object"
},
"TargetMatchKind": {
"description": "How a tier-1 already-present match against the target branch was\nestablished.",
"oneOf": [
{
"const": "trailer_intersection",
"description": "A walked target commit's `-x` trailer names the candidate (or\none of its trailer origins or inner PR commits).",
"type": "string"
},
{
"const": "trailer_ancestry",
"description": "One of the candidate's own trailer origins is already an\nancestor of the target tip.",
"type": "string"
},
{
"const": "patch_id",
"description": "A walked target commit's normalized patch hash equals the\ncandidate's.",
"type": "string"
}
]
},
"TestCallSite": {
"description": "One `Module:Function/Arity` reference inside a `_SUITE.erl` that\nresolves to a module absent on the target tree. Carries the line\nnumber so the operator can jump straight to the call site.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"required": [
"function",
"arity",
"line"
],
"type": "object"
},
"TouchedKinds": {
"description": "Per-pin tally of file kinds the patch touched. Lets `promote_inapplicable`\ntell a real green check from a diff with nothing analyzable to check.",
"properties": {
"app_src": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"ci_workflow": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"docs": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"erl": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"hrl": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"makefile": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"mix_exs": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"only_self_surface": {
"description": "The patch touches Erlang surface but references no tracked-dep\nAPI (every non-self pin has zero in-scope references). The CLI\nsets this after `evaluate_series` when a self-pin is present\nand every non-self pin's `tracked_refs` is empty; see\n`InapplicableReason::OnlySelfSurfaceTouched`.",
"type": "boolean"
},
"only_test_visibility": {
"description": "Every changed `.erl` hunk is a Variant A unwrap of test-only\n`-ifdef(TEST)` guards around an `-export` directive (see\n`InapplicableReason::OnlyTestVisibilityChanged`). When true,\nthe patch touches Erlang surface but adds no semantic\ncontent, so an empty reason set should promote to\n`Inapplicable` instead of `Compatible`.",
"type": "boolean"
},
"other": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"rebar_config": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"schema": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"tests": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"TranslationSource": {
"oneOf": [
{
"properties": {
"kind": {
"const": "config_stanza",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "external_file",
"type": "string"
},
"name": {
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"name"
],
"type": "object"
}
]
},
"Unanalyzed": {
"description": "Counts of call sites the analyzer could not resolve: `apply/3`-style\nBIFs, and dispatch through a variable module or function. Informational only.",
"properties": {
"apply": {
"default": 0,
"format": "uint",
"minimum": 0,
"type": "integer"
},
"variable_dispatch": {
"default": 0,
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"UnassessedReason": {
"description": "Why a path's apply outcome could not be assessed. The `Ord` only\nbreaks merge ties deterministically; it is not a severity.",
"oneOf": [
{
"const": "binary_file",
"description": "The diff marks the file binary; there is no hunk text to match.",
"type": "string"
},
{
"const": "target_not_text",
"description": "The target blob exists but is not valid UTF-8.",
"type": "string"
}
]
},
"Verdict": {
"oneOf": [
{
"properties": {
"verdict": {
"const": "compatible",
"type": "string"
}
},
"required": [
"verdict"
],
"type": "object"
},
{
"properties": {
"reasons": {
"items": {
"$ref": "#/$defs/Reason"
},
"type": "array"
},
"verdict": {
"const": "requires_adaptation",
"type": "string"
}
},
"required": [
"verdict",
"reasons"
],
"type": "object"
},
{
"properties": {
"reasons": {
"items": {
"$ref": "#/$defs/Reason"
},
"type": "array"
},
"verdict": {
"const": "incompatible",
"type": "string"
}
},
"required": [
"verdict",
"reasons"
],
"type": "object"
},
{
"properties": {
"reason": {
"$ref": "#/$defs/InapplicableReason"
},
"verdict": {
"const": "inapplicable",
"type": "string"
}
},
"required": [
"verdict",
"reason"
],
"type": "object"
}
]
},
"VerdictFingerprint": {
"description": "A verdict's stable identity for measurement: equal fingerprints\nmean the same patch against the same target and pins, whatever\nbackhopper version produced either side. Thirty-two lowercase hex\ncharacters: a truncated BLAKE3 digest, formatted here so\n`backhopper-core` takes no dependency on `blake3`.",
"type": "string"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Top-level payload of a `check batch` envelope.",
"properties": {
"fingerprint_version": {
"default": null,
"description": "The fingerprint generation this producer stamped. Lets a corpus\nspanning a bump segregate generations instead of reading an\nunexplained zero-match. `None` for a producer that predates it.",
"format": "uint32",
"minimum": 0,
"type": [
"integer",
"null"
]
},
"queried_against": {
"items": {
"$ref": "#/$defs/BatchQuery"
},
"type": "array"
},
"resolver_coverage": {
"anyOf": [
{
"$ref": "#/$defs/ResolverCoverage"
},
{
"type": "null"
}
],
"default": null,
"description": "Symbol classes this producer checks. A corpus row keeps it so the\nfold routes bug-vs-gap against the producing binary, not the one\nrunning the fold. `None` for a producer that predates the field."
},
"results": {
"items": {
"$ref": "#/$defs/BatchResult"
},
"type": "array"
},
"self_projects": {
"default": null,
"description": "Projects evaluated as the backport subject itself, excluded from\nthe tracked-dependency tally. `None` means the producing binary\npredates the field, not \"no self project\": a current producer\nalways emits `Some`, even when empty, so it is never skipped.",
"items": {
"type": "string"
},
"type": [
"array",
"null"
],
"uniqueItems": true
}
},
"required": [
"queried_against",
"results"
],
"title": "BatchPayload",
"type": "object"
},
"cache_list_payload": {
"$defs": {
"CacheLevel": {
"description": "Which workspace cache an entry belongs to.",
"oneOf": [
{
"const": "by_input",
"description": "`.verdict_cache/by-input/`: SHA-keyed verdict entries.",
"type": "string"
},
{
"const": "by_content",
"description": "`.verdict_cache/by-content/`: content-keyed verdict entries.",
"type": "string"
}
]
},
"CacheListRow": {
"description": "One row in `cache list`.",
"properties": {
"age_days": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"alias": {
"default": false,
"description": "True for `by-input` entries created from a content-level hit.",
"type": "boolean"
},
"bytes": {
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"commit": {
"description": "The evaluated commit, for verdict entries that carry one.",
"type": [
"string",
"null"
]
},
"key": {
"description": "The entry's key hash (the file-name stem after the format\nprefix); unique prefixes of it address entries in `show` and\n`evict`.",
"type": "string"
},
"level": {
"$ref": "#/$defs/CacheLevel"
},
"series": {
"description": "The series or pin target, when the pre-image names one.",
"type": [
"string",
"null"
]
}
},
"required": [
"key",
"level",
"age_days",
"bytes"
],
"type": "object"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "The `cache list` payload.",
"properties": {
"rows": {
"items": {
"$ref": "#/$defs/CacheListRow"
},
"type": "array"
}
},
"required": [
"rows"
],
"title": "CacheListPayload",
"type": "object"
},
"cache_mutation_payload": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Payload for `cache evict`, `cache prune`, and `cache clear`.",
"properties": {
"removed_bytes": {
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"removed_entries": {
"format": "uint64",
"minimum": 0,
"type": "integer"
}
},
"required": [
"removed_entries",
"removed_bytes"
],
"title": "CacheMutationPayload",
"type": "object"
},
"cache_show_payload": {
"$defs": {
"CacheLevel": {
"description": "Which workspace cache an entry belongs to.",
"oneOf": [
{
"const": "by_input",
"description": "`.verdict_cache/by-input/`: SHA-keyed verdict entries.",
"type": "string"
},
{
"const": "by_content",
"description": "`.verdict_cache/by-content/`: content-keyed verdict entries.",
"type": "string"
}
]
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "The `cache show` payload: one entry, pre-image included.",
"properties": {
"age_days": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"alias": {
"default": false,
"description": "True for `by-input` entries created as aliases of a\ncontent-level hit.",
"type": "boolean"
},
"bytes": {
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"created_at": {
"type": "string"
},
"key": {
"type": "string"
},
"key_inputs": {
"description": "The canonical-JSON key pre-image stored inside the entry."
},
"level": {
"$ref": "#/$defs/CacheLevel"
},
"value": {
"description": "The full stored value, under `--full` only."
},
"verdict_summary": {
"description": "Verdict counts for the stored evaluation."
}
},
"required": [
"key",
"level",
"created_at",
"age_days",
"bytes",
"key_inputs"
],
"title": "CacheShowPayload",
"type": "object"
},
"cache_stats_payload": {
"$defs": {
"CacheLevelStats": {
"description": "Per-level counters inside `cache stats`.",
"properties": {
"bytes": {
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"entries": {
"format": "uint64",
"minimum": 0,
"type": "integer"
}
},
"required": [
"entries",
"bytes"
],
"type": "object"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "The `cache stats` payload.",
"properties": {
"aliases": {
"description": "`by-input` entries created as aliases of a content-level hit.",
"format": "uint64",
"minimum": 0,
"type": "integer"
},
"by_content": {
"$ref": "#/$defs/CacheLevelStats"
},
"by_input": {
"$ref": "#/$defs/CacheLevelStats"
},
"newest_entry_at": {
"type": [
"string",
"null"
]
},
"oldest_entry_at": {
"description": "RFC3339 write times of the oldest and newest entries across\nevery level; absent when all caches are empty.",
"type": [
"string",
"null"
]
},
"total_bytes": {
"format": "uint64",
"minimum": 0,
"type": "integer"
}
},
"required": [
"by_input",
"by_content",
"aliases",
"total_bytes"
],
"title": "CacheStatsPayload",
"type": "object"
},
"command_family": "check",
"description": "v16 removes the `siblings doctor` verb and its wire surface: the `siblings_doctor_payload` document is gone, `CacheLevel` no longer has a `siblings` value, and `CacheStatsPayload` no longer carries a `siblings` level.",
"envelope": {
"$defs": {
"AlreadyPresent": {
"description": "Advisory: the patch's content appears to already exist on the\ntarget. Never affects the verdict; q-port and the operator own\nthe exclusion decision.",
"properties": {
"content": {
"anyOf": [
{
"$ref": "#/$defs/ContentPresence"
},
{
"type": "null"
}
],
"description": "Tier-2 tally: the post-image is (partly) present in the tree."
},
"identical": {
"anyOf": [
{
"$ref": "#/$defs/TargetMatch"
},
{
"type": "null"
}
],
"description": "Tier-1 hit: an identical patch landed on the target."
}
},
"type": "object"
},
"AlreadyPresentSkipped": {
"description": "Why already-present detection could not run. Emitted instead of\nsilence: an invisible skip would read as \"not present\".",
"oneOf": [
{
"description": "The candidate commit object is absent from the target object\nstore (an unfetched branch, usually).",
"properties": {
"reason": {
"const": "candidate_missing_from_target_odb",
"type": "string"
},
"sha": {
"type": "string"
}
},
"required": [
"reason",
"sha"
],
"type": "object"
},
{
"description": "The candidate and the target tip share no history.",
"properties": {
"reason": {
"const": "no_merge_base",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "The target-side walk failed (shallow clone, corrupt object).",
"properties": {
"detail": {
"type": "string"
},
"reason": {
"const": "target_walk_failed",
"type": "string"
}
},
"required": [
"reason",
"detail"
],
"type": "object"
}
]
},
"ApplyConflictKind": {
"description": "The apply outcomes a divergence predictor consumes, ordered by\nseverity: a higher variant outranks a lower one on the same path, so\ndedup to one conflict per path is a `max`.",
"enum": [
"postimage_collision",
"preimage_missing",
"file_absent"
],
"type": "string"
},
"ApplyForecast": {
"description": "Per-path apply prediction for one `(commit, series)` row, computed\nfrom the target tree. Present exactly when a target context was\nsupplied.",
"properties": {
"paths": {
"additionalProperties": {
"$ref": "#/$defs/PathApplyOutcome"
},
"description": "Every assessed touched path, including ones absent on the\ntarget (`Conflict { FileAbsent }`).",
"type": "object"
}
},
"required": [
"paths"
],
"type": "object"
},
"ArgShape": {
"oneOf": [
{
"description": "Variable identifier (starts with `_` or capital letter).",
"properties": {
"kind": {
"const": "variable",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Atom literal: `foo`, `'quoted atom'`.",
"properties": {
"kind": {
"const": "atom",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"description": "Integer literal.",
"properties": {
"kind": {
"const": "integer",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Float literal.",
"properties": {
"kind": {
"const": "float",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Binary literal: `<<...>>`.",
"properties": {
"kind": {
"const": "binary",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "List literal: `[...]`.",
"properties": {
"kind": {
"const": "list",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Tuple literal: `{...}` (size is the number of elements).",
"properties": {
"kind": {
"const": "tuple",
"type": "string"
},
"size": {
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"required": [
"kind",
"size"
],
"type": "object"
},
{
"description": "Record reference: `#name{...}`.",
"properties": {
"kind": {
"const": "record",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"description": "String literal: `\"...\"`.",
"properties": {
"kind": {
"const": "string",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Anonymous fun: `fun ... end` or `fun mod:f/A`.",
"properties": {
"kind": {
"const": "fun",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
},
{
"description": "Anything the extractor cannot classify. Always matches.",
"properties": {
"kind": {
"const": "unknown",
"type": "string"
}
},
"required": [
"kind"
],
"type": "object"
}
]
},
"ArtifactKind": {
"oneOf": [
{
"description": "`<<<<<<<`, `=======`, `>>>>>>>`, or `||||||| ` marker present in a\ntouched file. The cherry-pick driver left a conflict unresolved.",
"properties": {
"artifact_kind": {
"const": "conflict_marker",
"type": "string"
},
"marker": {
"$ref": "#/$defs/ConflictMarker"
}
},
"required": [
"artifact_kind",
"marker"
],
"type": "object"
},
{
"description": "`-export([f/N])` line without a matching clause defining `f/N`.\nCompiles, then crashes at runtime on the first call.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"artifact_kind": {
"const": "export_without_body",
"type": "string"
},
"function": {
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"artifact_kind",
"module",
"function",
"arity"
],
"type": "object"
}
]
},
"BumpStatus": {
"description": "Snapshot-store status of a bumped-to pin version.",
"oneOf": [
{
"description": "The bumped dep is not a tracked project; nothing to vet.",
"properties": {
"state": {
"const": "untracked",
"type": "string"
}
},
"required": [
"state"
],
"type": "object"
},
{
"description": "No snapshot for the bumped-to version; `note` carries the remedy.",
"properties": {
"note": {
"type": "string"
},
"state": {
"const": "snapshot_missing",
"type": "string"
}
},
"required": [
"state",
"note"
],
"type": "object"
},
{
"properties": {
"state": {
"const": "snapshot_present",
"type": "string"
}
},
"required": [
"state"
],
"type": "object"
}
]
},
"CheckPayload": {
"description": "The parsed payload of every `check`-family verb.",
"properties": {
"apply": {
"anyOf": [
{
"$ref": "#/$defs/ApplyForecast"
},
{
"type": "null"
}
],
"description": "Apply-axis prediction. Absent when no target context was\nsupplied: the axis was not evaluated, never \"clean\"."
},
"diagnostics": {
"$ref": "#/$defs/Diagnostics",
"description": "Series-wide diagnostics (untracked calls, suggested suites)."
},
"fingerprint_version": {
"default": null,
"description": "The fingerprint generation this binary stamped. Always emitted.",
"format": "uint32",
"minimum": 0,
"type": [
"integer",
"null"
]
},
"pr_commits": {
"default": null,
"description": "Inner PR-branch commits for 2-parent merge inputs, `None` for\neverything else. The `None` vs `Some(vec![])` distinction is\npart of the wire contract, so no `skip_serializing_if`.",
"items": {
"$ref": "#/$defs/PrCommit"
},
"type": [
"array",
"null"
]
},
"project_suggestions": {
"description": "Projects the untracked-call analysis suggests adding.",
"items": {
"$ref": "#/$defs/ProjectSuggestion"
},
"type": "array"
},
"queried_against": {
"$ref": "#/$defs/QueriedAgainst",
"description": "What the verb was queried against (a series or a pin)."
},
"resolver_coverage": {
"anyOf": [
{
"$ref": "#/$defs/ResolverCoverage"
},
{
"type": "null"
}
],
"default": null,
"description": "Symbol classes this binary checks, for the measurement fold.\nAlways emitted so a consumer tells it from an old binary."
},
"results": {
"$ref": "#/$defs/SeriesVerdict",
"description": "Per-pin verdicts plus summary."
},
"self_projects": {
"default": null,
"description": "Projects excluded from the tracked-dependency tally. Always\nemitted so a consumer can tell an empty set from an old binary.",
"items": {
"type": "string"
},
"type": [
"array",
"null"
],
"uniqueItems": true
},
"target_findings": {
"anyOf": [
{
"$ref": "#/$defs/TargetFindings"
},
{
"type": "null"
}
],
"description": "Symbol-axis target findings, `None` when no target context."
},
"verdict_fingerprint": {
"anyOf": [
{
"$ref": "#/$defs/VerdictFingerprint"
},
{
"type": "null"
}
],
"description": "Stable join key for this verdict, omitted for inputs with no\ncache key (patch, range, PR, or an unresolvable pin)."
}
},
"required": [
"queried_against",
"results"
],
"type": "object"
},
"ConflictMarker": {
"oneOf": [
{
"const": "ours",
"description": "`<<<<<<<` line: start of the local side.",
"type": "string"
},
{
"const": "divider",
"description": "`=======` line: divider between sides.",
"type": "string"
},
{
"const": "theirs",
"description": "`>>>>>>>` line: end of the incoming side.",
"type": "string"
},
{
"const": "ancestor",
"description": "`||||||| ` line: base ancestor marker from a 3-way diff.",
"type": "string"
}
]
},
"ContentPresence": {
"description": "Tier-2 advisory: how much of the patch's post-image already exists\nin the named pin's tree. A tally, never a boolean: partial presence\nis common and the fraction is the signal.",
"properties": {
"hunks_already_applied": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"hunks_ambiguous": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"hunks_considered": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"hunks_low_confidence": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"per_file": {
"additionalProperties": {
"$ref": "#/$defs/HunkTally"
},
"type": "object"
},
"pin": {
"description": "The pin whose evaluation produced the tally. In cross-branch\nmode the self pin resolves to the target branch, so its tally\nis the target-tree answer.",
"type": "string"
}
},
"required": [
"pin",
"hunks_already_applied",
"hunks_considered",
"hunks_ambiguous",
"hunks_low_confidence"
],
"type": "object"
},
"DepPinDivergence": {
"description": "A dependency whose `rabbitmq-components.mk` pin differs between\nthe source commit's tree and the target tree, and that an app\ntouched by the patch (transitively) depends on. Advisory only.",
"properties": {
"dep": {
"type": "string"
},
"source": {
"description": "Pin at the source commit, e.g. `hex 2.16.0`.",
"type": "string"
},
"target": {
"description": "Pin at the target tree, e.g. `hex 2.13.0`.",
"type": "string"
}
},
"required": [
"dep",
"source",
"target"
],
"type": "object"
},
"Diagnostics": {
"description": "Series-wide diagnostic envelope. Strictly separate from `Verdict`\nso untracked-call signals never leak into machine-readable verdicts.",
"properties": {
"already_present": {
"anyOf": [
{
"$ref": "#/$defs/AlreadyPresent"
},
{
"type": "null"
}
],
"description": "Advisory: the patch's content appears to already exist on the\ntarget (tier-1 identical patch, tier-2 content tally, or both)."
},
"already_present_skipped": {
"anyOf": [
{
"$ref": "#/$defs/AlreadyPresentSkipped"
},
{
"type": "null"
}
],
"description": "Why already-present detection was skipped, when it was."
},
"context_refs_missing": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"description": "In-scope references on *context* lines that do not resolve at\nsome pin, per module. Pre-existing target facts: never reasons.",
"type": "object"
},
"dep_pin_divergence": {
"description": "Dep pins that diverge between source and target trees and are\nreachable from the apps this patch touches.",
"items": {
"$ref": "#/$defs/DepPinDivergence"
},
"type": "array"
},
"indirect_call_checks": {
"$ref": "#/$defs/IndirectCallTally",
"description": "What the indirect-reference check (meck expectations and rpc\nforms) did with each recognized occurrence: resolved against the\ntarget module, or seen with an unreadable arity and withheld."
},
"local_call_shape_checks": {
"$ref": "#/$defs/ShapeCheckTally",
"description": "The same tally for local calls: resolved unqualified calls, compared or\nwithheld. Kept apart from the qualified tally so one axis's\ncoverage never reads as the other's."
},
"macro_value_checks": {
"$ref": "#/$defs/MacroValueTally",
"description": "Same-file `-define` value comparisons over macros the patch\nuses: compared, or withheld and why."
},
"missing_test_modules": {
"additionalProperties": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"type": "object"
},
"description": "Per-`_SUITE.erl` map of `helper_module -> call_site_count`. The\nalways-on diagnostic form of\n`Reason::TestModuleSymbolMissing`: emitted by the parse pass\neven without a target tree (which is why the inner key is the\n`ModuleName` rather than a resolved-or-not bit). When\n`--target-repo-dir-path` is supplied the resolver re-checks this\nmap and promotes the absent ones to typed reasons. The nested\n`BTreeMap` shape keeps the JSON envelope serialisable without\na custom composite-key encoder.",
"type": "object"
},
"pin_bumps": {
"description": "Dep pins this patch itself changes or introduces in the root\n`rabbitmq-components.mk`.",
"items": {
"$ref": "#/$defs/PinBump"
},
"type": "array"
},
"qualified_call_shape_checks": {
"$ref": "#/$defs/ShapeCheckTally",
"description": "What the live qualified-call gate's return-shape check did with\neach first-party resolved call: compared, or withheld and why."
},
"suggested_suites": {
"description": "SUITE names worth running for the patch, derived from touched paths.\nPopulated even when the verdict promotes to `Inapplicable` so that\nschema-only and config-only diffs still surface relevant suites.",
"items": {
"type": "string"
},
"type": "array"
},
"unanalyzed": {
"$ref": "#/$defs/Unanalyzed"
},
"unattributed_paths": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"description": "Touched paths no configured project owns, tallied by their\nfirst two path components. The evidence behind an\n`Inapplicable { Untracked }` verdict.",
"type": "object"
},
"untracked_calls": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"type": "object"
},
"untracked_records": {
"additionalProperties": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"type": "object"
}
},
"type": "object"
},
"EnvelopeWarning": {
"description": "A non-fatal warning carried alongside a payload.",
"properties": {
"code": {
"description": "Stable warning code, kebab-case (e.g. `stale-extractor`).",
"type": "string"
},
"message": {
"description": "Human-readable message.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"HunkTally": {
"description": "Per-file hunk counters for the content-presence check.",
"properties": {
"ambiguous": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"applied": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"considered": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"low_confidence": {
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"required": [
"applied",
"considered",
"ambiguous",
"low_confidence"
],
"type": "object"
},
"InapplicableReason": {
"oneOf": [
{
"properties": {
"reason": {
"const": "no_erlang_surface_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_docs_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_test_fixtures_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_schema_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_makefile_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_mix_exs_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_ci_workflow_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_app_src_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"properties": {
"reason": {
"const": "only_rebar_config_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "Every changed `.erl` hunk is a Variant A unwrap: dropping\n`-ifdef(TEST).` or `-endif.` around an `-export(...)` directive,\nor rewriting `-compile(export_all).` to an explicit\n`-export([...])`. No call sites, no specs, no bodies touched:\nonly test-visibility metadata.",
"properties": {
"reason": {
"const": "only_test_visibility_changed",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "The patch touches Erlang surface but every referenced symbol\nresolves to the self-pin or to a local definition: every\ntracked-dep pin has zero in-scope references. Without this\nreason the operator would see many vacuous `Compatible`\nrows for a patch that backhopper genuinely has no signal on.",
"properties": {
"reason": {
"const": "only_self_surface_touched",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "Every touched path is in a sibling project's scope, not this\npin's. The pin has nothing to say about the patch. `project`\nnames the first sibling project (alphabetical) that owns the\nout-of-scope paths.",
"properties": {
"project": {
"type": "string"
},
"reason": {
"const": "out_of_scope_for",
"type": "string"
}
},
"required": [
"reason",
"project"
],
"type": "object"
},
{
"description": "Every touched path is unclaimed by any configured project's\nscan_paths or app_roots. Vendored files, docs, build scripts.",
"properties": {
"reason": {
"const": "untracked",
"type": "string"
}
},
"required": [
"reason"
],
"type": "object"
},
{
"description": "`--target-repo-dir-path` was supplied and every touched path\nis missing from the target tree, with no configured\ntranslation mapping any of them. The patch as written does\nnot apply to the target.",
"properties": {
"paths": {
"items": {
"type": "string"
},
"type": "array"
},
"reason": {
"const": "paths_missing_on_target",
"type": "string"
}
},
"required": [
"reason",
"paths"
],
"type": "object"
}
]
},
"IncludeDirective": {
"description": "`-include` and `-include_lib` are syntactically distinct: the\nformer takes a relative-to-source path, the latter an\n`application/include/file.hrl` shape resolved through OTP's lib\npath. The variant preserves which form the source used so the\nremediation text can match.",
"oneOf": [
{
"properties": {
"form": {
"const": "include",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"form",
"path"
],
"type": "object"
},
{
"properties": {
"form": {
"const": "include_lib",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"form",
"path"
],
"type": "object"
}
]
},
"IndirectCallForm": {
"description": "Which recognized call form carried an indirect MFA reference. Names\nthe innermost form: a meck expectation reached through an rpc helper\nis `MeckExpect`, not the helper.",
"enum": [
"meck_expect",
"rpc_call",
"erpc_call",
"ct_broker_helper_rpc",
"rabbit_misc_rpc_call"
],
"type": "string"
},
"IndirectCallTally": {
"description": "What the indirect-reference check did with each recognized form\noccurrence. `checked` counts deduplicated resolved sites, the same\ndedup the reasons use; flagged sites are visible in the reasons,\nnot double-counted here.",
"properties": {
"checked": {
"description": "Module first-party, export and definition sets readable: the\nmembership check ran.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_dynamic": {
"description": "Module and function were literal atoms but the arity source was\nnot statically readable: a variable argument list, a list with a\ncons tail, or a non-literal arity argument.",
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"MacroValueTally": {
"description": "What the macro-value check did with each `?MACRO` the patch uses:\ncompared, or withheld and why. Same-file `-define`s only; anything\nreached another way is withheld, never guessed.",
"properties": {
"compared": {
"description": "Defined exactly once same-file on both sides; values compared.\nDrift is visible in the reasons, not double-counted here.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_definition_elsewhere": {
"description": "Not defined same-file on both sides: the definition is in an\ninclude, or moved between files across the trees.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_multiple_defines": {
"description": "Defined more than once in the file on either side (`-ifdef`\nbranches): either value could be live.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_no_source": {
"description": "The touched file was not readable on the source side.",
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"Mfa": {
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"module",
"function",
"arity"
],
"type": "object"
},
"NeedsPin": {
"description": "The minimum pin that satisfies a missing-symbol reason: the typed\nordering payload q-port turns into a \"bump must land first\" edge.",
"properties": {
"project": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"project",
"tag"
],
"type": "object"
},
"PathApplyOutcome": {
"description": "How one touched path is predicted to apply to the target tree.\nRanked by [`PathApplyOutcome::severity`]; payload-carrying variants\nkeep the enum out of `Ord`.",
"oneOf": [
{
"description": "Every hunk's preimage matches at its expected line.",
"properties": {
"outcome": {
"const": "clean_exact",
"type": "string"
}
},
"required": [
"outcome"
],
"type": "object"
},
{
"description": "Applies, but at least one hunk's preimage was found at a shifted\nline. `line_delta` is the largest-magnitude shift.",
"properties": {
"line_delta": {
"format": "int64",
"type": "integer"
},
"outcome": {
"const": "clean_drifted",
"type": "string"
}
},
"required": [
"outcome",
"line_delta"
],
"type": "object"
},
{
"description": "The path could not be assessed; stated, never silent.",
"properties": {
"outcome": {
"const": "unassessed",
"type": "string"
},
"reason": {
"$ref": "#/$defs/UnassessedReason"
}
},
"required": [
"outcome",
"reason"
],
"type": "object"
},
{
"description": "At least one hunk predicts a conflict. `kind` is the worst\nconflict kind across the path's hunks.",
"properties": {
"kind": {
"$ref": "#/$defs/ApplyConflictKind"
},
"outcome": {
"const": "conflict",
"type": "string"
}
},
"required": [
"outcome",
"kind"
],
"type": "object"
}
]
},
"Pin": {
"properties": {
"project": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"project",
"tag"
],
"type": "object"
},
"PinBump": {
"description": "A dep pin the candidate commit itself changes or introduces in the\nroot `rabbitmq-components.mk`. Advisory only: the verdict on a\nbump-only diff stays `Inapplicable`, this is the evidence behind it.",
"properties": {
"dep": {
"type": "string"
},
"from": {
"description": "Pin before the commit, e.g. `hex 2.16.0`; `None` when the\ncommit introduces the pin.",
"type": [
"string",
"null"
]
},
"status": {
"anyOf": [
{
"$ref": "#/$defs/BumpStatus"
},
{
"type": "null"
}
],
"description": "Snapshot-store assessment of the bumped-to version. Detection\nis a pure function of the patch and may be cached; the store's\ncontents are not a cache-key input, so this field is filled\npost-cache and cached values carry `None`."
},
"to": {
"description": "Pin after the commit, e.g. `hex 2.17.1`.",
"type": "string"
}
},
"required": [
"dep",
"to"
],
"type": "object"
},
"PinPayload": {
"description": "On-wire pin shape used inside `BatchQuery`. Distinct from\n`crate::model::pin::Pin` because the wire form is a `(project, tag)`\nprojection without the resolution logic.",
"properties": {
"project": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"project",
"tag"
],
"type": "object"
},
"PinVerdict": {
"properties": {
"pin": {
"$ref": "#/$defs/Pin"
},
"source_delta_details": {
"items": {
"$ref": "#/$defs/SourceDelta"
},
"type": "array"
},
"touched": {
"$ref": "#/$defs/TouchedKinds"
},
"tracked_ref_details": {
"items": {
"$ref": "#/$defs/SymbolRef"
},
"type": "array"
},
"tracked_refs": {
"default": 0,
"format": "uint",
"minimum": 0,
"type": "integer"
},
"verdict": {
"$ref": "#/$defs/Verdict"
}
},
"required": [
"pin",
"verdict"
],
"type": "object"
},
"PrCommit": {
"description": "One commit on the PR-branch side of a 2-parent merge.",
"properties": {
"author_date": {
"type": "string"
},
"kind": {
"$ref": "#/$defs/PrCommitKind"
},
"sha": {
"type": "string"
},
"subject": {
"type": "string"
}
},
"required": [
"sha",
"subject",
"author_date",
"kind"
],
"type": "object"
},
"PrCommitKind": {
"description": "Classification of a PR-branch commit's role.\n\n`#[non_exhaustive]` so future, richer taxonomies (test-only,\ndocs-only, dependency-bump, etc.) can add variants without a\nbreaking change.",
"oneOf": [
{
"const": "substantive",
"description": "Default: substantive change worth reviewing.",
"type": "string"
},
{
"const": "conflict_resolution",
"description": "Subject matched the conflict-resolution catalog AND the file\nset was a strict subset of prior PR-branch commits.",
"type": "string"
},
{
"const": "review_feedback",
"description": "Subject indicated the commit applied code-review feedback.",
"type": "string"
},
{
"const": "fixup",
"description": "`git --fixup` auto-generated or the manual `fixup:` convention.",
"type": "string"
},
{
"const": "wip_or_cleanup",
"description": "Subject was `WIP` or bare `Cleanup`.",
"type": "string"
}
]
},
"ProjectSuggestion": {
"description": "A project the untracked-call analysis suggests adding to config so its\ncalls become tracked-dependency evidence.",
"properties": {
"call_sites": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"modules": {
"items": {
"type": "string"
},
"type": "array"
},
"name": {
"type": "string"
}
},
"required": [
"name",
"modules",
"call_sites"
],
"type": "object"
},
"QueriedAgainst": {
"description": "What a `check`-family verb was queried against: a single pin or a\nwhole series.",
"oneOf": [
{
"description": "`check ... --project NAME --tag TAG`.",
"properties": {
"kind": {
"const": "pin",
"type": "string"
},
"project": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"kind",
"project",
"tag"
],
"type": "object"
},
{
"description": "`check ... --series NAME`.",
"properties": {
"kind": {
"const": "series",
"type": "string"
},
"name": {
"type": "string"
},
"pins": {
"items": {
"$ref": "#/$defs/PinPayload"
},
"type": "array"
}
},
"required": [
"kind",
"name",
"pins"
],
"type": "object"
}
]
},
"Reason": {
"oneOf": [
{
"properties": {
"first_seen_at_tag": {
"description": "Earliest snapshot tag strictly later than the pin where the\nsymbol appears. `Some` reclassifies the reason as\nadaptable: land the dep pin bump first.",
"type": [
"string",
"null"
]
},
"kind": {
"const": "missing_symbol",
"type": "string"
},
"needs_pin_at_least": {
"anyOf": [
{
"$ref": "#/$defs/NeedsPin"
},
{
"type": "null"
}
]
},
"suggested_replacement": {
"anyOf": [
{
"$ref": "#/$defs/SymbolRef"
},
{
"type": "null"
}
]
},
"symbol": {
"$ref": "#/$defs/SymbolRef"
}
},
"required": [
"kind",
"symbol"
],
"type": "object"
},
{
"properties": {
"expected": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"expected_available_at": {
"description": "Earliest snapshot tag strictly later than the pin exporting\nthe expected arity. Same bump-first semantics as\n`MissingSymbol::first_seen_at_tag`.",
"type": [
"string",
"null"
]
},
"found": {
"items": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"type": "array"
},
"function": {
"type": "string"
},
"kind": {
"const": "arity_changed",
"type": "string"
},
"module": {
"type": "string"
},
"needs_pin_at_least": {
"anyOf": [
{
"$ref": "#/$defs/NeedsPin"
},
{
"type": "null"
}
]
}
},
"required": [
"kind",
"module",
"function",
"expected",
"found"
],
"type": "object"
},
{
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"expected_spec": {
"type": "string"
},
"found_spec": {
"type": "string"
},
"function": {
"type": "string"
},
"kind": {
"const": "signature_changed",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"function",
"arity",
"expected_spec",
"found_spec"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "file_absent",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path"
],
"type": "object"
},
{
"properties": {
"hunk_index": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "context_drift",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"hunk_index"
],
"type": "object"
},
{
"description": "The contiguous preimage block (Context and Removed lines from\nthe hunk) was found verbatim at a different starting line.\nCherry-pick adapters handle this with the `-x` trailer; the\noperator just needs the delta to confirm the patch's intent\nstill applies.",
"properties": {
"hunk_index": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "preimage_drifted",
"type": "string"
},
"line_delta": {
"format": "int",
"type": "integer"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"hunk_index",
"line_delta"
],
"type": "object"
},
{
"description": "The hunk's preimage matches, but its added lines land at a file\nedge where the target already has divergent content the base\nlacked: an add/add a contiguous preimage match cannot detect. The\n3-way cherry-pick conflicts where the preimage-only check reads\nclean. Non-blocking: the operator resolves the overlap.",
"properties": {
"hunk_index": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "postimage_collision",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"hunk_index"
],
"type": "object"
},
{
"description": "The preimage block does not appear anywhere in the file. The\npatch was authored against a tree where the lines existed; on\nthis pin they don't. Structurally inapplicable: the operator\nneeds an excerpt to reason about why.",
"properties": {
"hunk_index": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "preimage_missing",
"type": "string"
},
"path": {
"type": "string"
},
"preimage_excerpt": {
"type": "string"
}
},
"required": [
"kind",
"path",
"hunk_index",
"preimage_excerpt"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "deprecated_usage",
"type": "string"
},
"replacement": {
"anyOf": [
{
"$ref": "#/$defs/SymbolRef"
},
{
"type": "null"
}
]
},
"since": {
"type": [
"string",
"null"
]
},
"symbol": {
"$ref": "#/$defs/SymbolRef"
}
},
"required": [
"kind",
"symbol"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "now_hidden",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module"
],
"type": "object"
},
{
"properties": {
"expected": {
"items": {
"type": "string"
},
"type": "array"
},
"found": {
"items": {
"type": "string"
},
"type": "array"
},
"kind": {
"const": "record_fields_changed",
"type": "string"
},
"record": {
"type": "string"
}
},
"required": [
"kind",
"record",
"expected",
"found"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "unsupported_file_type",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "untracked_module_missing",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module"
],
"type": "object"
},
{
"description": "Call-site argument shapes don't satisfy any clause head at the\npin. Emitted when both the call and the pin's clause patterns\nare concrete enough to compare; `Unknown` on either side\nsuppresses the reason.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"call_args": {
"items": {
"$ref": "#/$defs/ArgShape"
},
"type": "array"
},
"function": {
"type": "string"
},
"kind": {
"const": "clause_mismatch",
"type": "string"
},
"module": {
"type": "string"
},
"pin_clauses": {
"items": {
"items": {
"$ref": "#/$defs/ArgShape"
},
"type": "array"
},
"type": "array"
}
},
"required": [
"kind",
"module",
"function",
"arity",
"call_args",
"pin_clauses"
],
"type": "object"
},
{
"description": "Patch references an MFA owned by the self-project but absent from the\nresolved self-snapshot. `suggested_source_for_prereq` is filled only\nwith `--suggest-prereqs`.",
"properties": {
"kind": {
"const": "missing_prereq",
"type": "string"
},
"self_branch": {
"type": "string"
},
"suggested_source_for_prereq": {
"type": [
"string",
"null"
]
},
"symbol": {
"$ref": "#/$defs/SymbolRef"
}
},
"required": [
"kind",
"symbol",
"self_branch"
],
"type": "object"
},
{
"description": "Pre-flight syntactic damage in a touched file: an unresolved\nmerge-conflict marker, an exported function with no definition, etc.",
"properties": {
"artifact": {
"$ref": "#/$defs/ArtifactKind"
},
"kind": {
"const": "syntactic_artifact",
"type": "string"
},
"line": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"line",
"artifact"
],
"type": "object"
},
{
"description": "Patch changes a `-callback` signature; an implementer still has the old one.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"expected_after_patch": {
"type": "string"
},
"implementer": {
"type": "string"
},
"implementer_signature": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_signature_changed",
"type": "string"
}
},
"required": [
"kind",
"behaviour",
"callback",
"arity",
"expected_after_patch",
"implementer",
"implementer_signature"
],
"type": "object"
},
{
"description": "Patch removes a required callback; implementer still exports it.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"implementer": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_removed",
"type": "string"
}
},
"required": [
"kind",
"behaviour",
"callback",
"arity",
"implementer"
],
"type": "object"
},
{
"description": "Patch adds a required callback; implementer is missing the export.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"implementer": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_added",
"type": "string"
}
},
"required": [
"kind",
"behaviour",
"callback",
"arity",
"implementer"
],
"type": "object"
},
{
"description": "Patch touches a path absent on pin, but a module of the same basename exists elsewhere.",
"properties": {
"kind": {
"const": "module_relocated",
"type": "string"
},
"module": {
"type": "string"
},
"patch_path": {
"type": "string"
}
},
"required": [
"kind",
"module",
"patch_path"
],
"type": "object"
},
{
"description": "Wire-bearing macro value differs between source and pin.",
"properties": {
"after": {
"type": "string"
},
"before": {
"type": "string"
},
"kind": {
"const": "wire_constant_changed",
"type": "string"
},
"macro_name": {
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"macro_name",
"before",
"after"
],
"type": "object"
},
{
"description": "`version/0` advanced without the matching historical-implementation module.",
"properties": {
"advertised_version_after": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"advertised_version_before": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"expected_historical_module": {
"type": "string"
},
"kind": {
"const": "historical_implementation_missing",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"advertised_version_before",
"advertised_version_after",
"expected_historical_module"
],
"type": "object"
},
{
"description": "Function bodies drifted at the same advertised `version/0`. Mixed-version cluster risk.",
"properties": {
"advertised_version": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"functions": {
"items": {
"type": "string"
},
"type": "array"
},
"kind": {
"const": "wire_contract_body_drift",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"functions",
"advertised_version"
],
"type": "object"
},
{
"description": "`version/0` decreased pin → patch.",
"properties": {
"kind": {
"const": "wire_contract_regression",
"type": "string"
},
"module": {
"type": "string"
},
"patch_version": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"pin_version": {
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"required": [
"kind",
"module",
"pin_version",
"patch_version"
],
"type": "object"
},
{
"description": "Spec return shape differs between source and pin for a referenced MFA.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "return_shape_mismatch",
"type": "string"
},
"module": {
"type": "string"
},
"pin_signature": {
"type": "string"
},
"source_signature": {
"type": "string"
}
},
"required": [
"kind",
"module",
"function",
"arity",
"source_signature",
"pin_signature"
],
"type": "object"
},
{
"description": "A type-reference inside a `-spec`, `-callback`, `-type`, or\n`-opaque` attribute resolves to a name and arity that the pin\ndoes not expose via `-export_type`. Non-blocking: a missing\ntype alias is a dialyzer-level concern, not a load-time crash.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "missing_type",
"type": "string"
},
"module": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"module",
"name",
"arity"
],
"type": "object"
},
{
"description": "A touched path is absent from the target tree, but a\nconfigured `[[path_translation]]` rewrites it to a path that\ndoes exist on the target. Non-blocking: the operator (or the\ncherry-pick driver) rewrites the path before applying.",
"properties": {
"kind": {
"const": "path_rename",
"type": "string"
},
"source_path": {
"type": "string"
},
"target_path": {
"type": "string"
},
"translation": {
"$ref": "#/$defs/TranslationSource"
}
},
"required": [
"kind",
"source_path",
"target_path",
"translation"
],
"type": "object"
},
{
"description": "A touched path is absent on the target while others are present\nand no `[[path_translation]]` rewrites it. Non-blocking: dropping\nthe hunks for this path lets the rest apply. The all-absent case\nis `InapplicableReason::PathsMissingOnTarget`.",
"properties": {
"kind": {
"const": "target_path_absent",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path"
],
"type": "object"
},
{
"description": "A `_SUITE.erl` file in the patch references `missing_module:f/n`\nwhere `missing_module` resolves to no source file under any\nconfigured `FamilyDefaults.test_helper_search_paths` on the\ntarget tree. The cherry-pick compiles and the SUITE may even\nload, but every call to the missing helper crashes at runtime:\nthe failure pattern seen in the Jun 2026 v4.1.x → v4.0.x round\n(the `amqp_utils:connection_config/1` undef in\n`amqp10_connection_max_SUITE`). Non-blocking by default: the\ndiagnostic equivalent (`Diagnostics.missing_test_modules`)\nalways fires; the `Reason` variant fires only when\n`--target-repo-dir-path` is supplied and the resolution is\nauthoritative.",
"properties": {
"call_sites": {
"items": {
"$ref": "#/$defs/TestCallSite"
},
"type": "array"
},
"kind": {
"const": "test_module_symbol_missing",
"type": "string"
},
"missing_module": {
"type": "string"
},
"suite_path": {
"type": "string"
}
},
"required": [
"kind",
"suite_path",
"missing_module",
"call_sites"
],
"type": "object"
},
{
"description": "A touched `.erl` declares `-behaviour(behaviour)` (or\n`-behavior(...)`) where `behaviour` resolves to no source\nmodule on the target tree. `erlc` compiles with a warning,\nthen hook dispatch crashes at runtime. The `BehaviourCallback*`\nvariants model implementer drift; this one catches the\nmissing-behaviour-module case they do not.",
"properties": {
"behaviour": {
"type": "string"
},
"kind": {
"const": "behaviour_module_missing",
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"behaviour"
],
"type": "object"
},
{
"description": "A touched `.erl` or `.hrl` declares `-include(path)` or\n`-include_lib(app/include/file.hrl)` against a target tree that\ndoes not ship the resolved header. Compile-time failure rather\nthan runtime, but same user-facing shape as\n`TestModuleSymbolMissing`: looked fine on source, broken on\ntarget.",
"properties": {
"attempted_paths": {
"items": {
"type": "string"
},
"type": "array"
},
"include_directive": {
"$ref": "#/$defs/IncludeDirective"
},
"kind": {
"const": "header_file_missing",
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"include_directive",
"attempted_paths"
],
"type": "object"
},
{
"description": "A touched `.erl` or `.hrl` file references `?MACRO` on an added\nline, but `MACRO` is defined nowhere the target tree reaches (not\nin the file, its includes, or the patch itself) and is not\npredefined. Compiles on source, dangles on target. Non-blocking:\nthe operator drops or adapts the reference.",
"properties": {
"kind": {
"const": "macro_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"macro_name": {
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"macro_name",
"line"
],
"type": "object"
},
{
"description": "A touched `.erl` or `.hrl` file uses `#record{}` on an added\nline, but `record` is defined nowhere the target tree reaches and\nis not added by the patch. Same check as `MacroUndefinedOnTarget`\nfor the record namespace; non-blocking.",
"properties": {
"kind": {
"const": "record_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"record_name": {
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"record_name",
"line"
],
"type": "object"
},
{
"description": "A touched `.erl` file calls an unqualified `f/a` on an added line\nthat the target version of the same module neither defines,\nexports, imports, nor inherits as an auto-imported BIF. The\nsame check for the function namespace; non-blocking.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "local_call_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"function",
"arity",
"line"
],
"type": "object"
},
{
"description": "A touched `.erl` file calls a qualified `m:f/a` on an added line\nwhose module is a first-party module present on the target tree,\nbut the target version of that module does not export `f/a` (and\nthe patch does not add it). The qualified form of\n`LocalCallUndefinedOnTarget`, resolved against the called\nmodule's exports. Withheld when any pin snapshot already covers\nthe module, when it is absent from the tree, or when its export\nsurface is not fully readable. Non-blocking.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "qualified_call_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"module": {
"type": "string"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"module",
"function",
"arity",
"line"
],
"type": "object"
},
{
"description": "A qualified `m:f/a` call that resolves against the target tree\nhas a target-tree `-spec` return shape that disagrees with its\nsource-tree `-spec`. Same comparison as `ReturnShapeMismatch` on\nthe live, snapshot-free first-party axis: same comparator,\nnon-blocking like the rest of that axis. Only evaluated once the\ncall is confirmed to resolve; withheld when either side lacks a\n`-spec`.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "qualified_call_return_shape_drift",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"module": {
"type": "string"
},
"source_path": {
"type": "string"
},
"source_signature": {
"type": "string"
},
"target_signature": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"module",
"function",
"arity",
"source_signature",
"target_signature",
"line"
],
"type": "object"
},
{
"description": "An unqualified call that resolves against the target module's\nown definitions has a target-tree `-spec` return shape that\ndisagrees with its source-tree `-spec`. The local-call form of\n`QualifiedCallReturnShapeDrift`; imported resolutions are\nwithheld, since the callee's spec is in another module.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "local_call_return_shape_drift",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
},
"source_signature": {
"type": "string"
},
"target_signature": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"function",
"arity",
"source_signature",
"target_signature",
"line"
],
"type": "object"
},
{
"description": "A `?MACRO` the patch uses is defined in the touched file itself\non both trees, exactly once each, and the normalized `-define`\nbodies disagree: the compile-clean, behavior-divergent class.\nWithheld for definitions reached any other way. Non-blocking.",
"properties": {
"kind": {
"const": "macro_value_drift",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"macro_name": {
"type": "string"
},
"source_path": {
"type": "string"
},
"source_value": {
"type": "string"
},
"target_value": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"macro_name",
"source_value",
"target_value",
"line"
],
"type": "object"
},
{
"description": "The target's version of a behaviour the patch declares requires\na callback the source's version does not, and the target does\nnot list it as optional: an implementation written against the\nsource is missing it. `line` is the `-behaviour` attribute's\nline in the touched file. Non-blocking.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_added_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"behaviour",
"callback",
"arity",
"line"
],
"type": "object"
},
{
"description": "A callback both trees' versions of a declared behaviour declare\nhas a different normalized signature on the target. The whole\nsignature is compared, not just the return half: a callback\ncontract's argument types are the implementer's obligation.\nNon-blocking.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"behaviour": {
"type": "string"
},
"callback": {
"type": "string"
},
"kind": {
"const": "behaviour_callback_drift_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
},
"source_signature": {
"type": "string"
},
"target_signature": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"behaviour",
"callback",
"arity",
"source_signature",
"target_signature",
"line"
],
"type": "object"
},
{
"description": "Declared versioned-machine module is touched but the snapshot\nhas no recorded `versioned_machine_version` on `side`.\nNon-blocking.",
"properties": {
"kind": {
"const": "versioned_machine_snapshot_missing",
"type": "string"
},
"module": {
"type": "string"
},
"side": {
"$ref": "#/$defs/SnapshotSide"
}
},
"required": [
"kind",
"module",
"side"
],
"type": "object"
},
{
"description": "Declared wire constants are touched but the snapshot's\n`wire_constants` vector lacks the listed macros on `side`.\n`macros` is sorted alphabetically. Non-blocking.",
"properties": {
"kind": {
"const": "wire_constant_bindings_missing",
"type": "string"
},
"macros": {
"items": {
"type": "string"
},
"type": "array"
},
"module": {
"type": "string"
},
"side": {
"$ref": "#/$defs/SnapshotSide"
}
},
"required": [
"kind",
"module",
"macros",
"side"
],
"type": "object"
},
{
"description": "A first-party `m:f/a` referenced as arguments to a mocking or\nrpc form (a meck expectation, `rpc:call`, `erpc:call`, or a CT\nbroker rpc helper) is neither exported nor defined by the target\ntree's module. Non-blocking: a meck expectation can install a\nfunction the module never had, so absence proves drift, not\nfailure.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "indirect_call_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"module": {
"type": "string"
},
"source_path": {
"type": "string"
},
"via": {
"$ref": "#/$defs/IndirectCallForm"
}
},
"required": [
"kind",
"source_path",
"module",
"function",
"arity",
"via",
"line"
],
"type": "object"
},
{
"description": "A touched `.erl` file adds an `-export_type([t/a])` entry naming\na type neither the target version of the same module declares\nnor the patch adds. An `erlc` error, unlike `MissingType`, which\nis dialyzer-level; non-blocking regardless, being a target-tree\nfinding rather than a pin verdict. Withheld when the target file\nis unreadable or declares a `parse_transform`, or when the added\nlist names a macro.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "exported_type_undefined_on_target",
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"source_path": {
"type": "string"
},
"type_name": {
"type": "string"
}
},
"required": [
"kind",
"source_path",
"type_name",
"arity",
"line"
],
"type": "object"
}
]
},
"RefOrigin": {
"description": "Which side of the hunk a reference was extracted from. `Added`\nlines are requirements the patch introduces; `Context` lines are\npre-existing facts about the target and never drive verdicts.\n`Added` orders first so a kind-level dedup keeps the stronger\norigin.",
"enum": [
"added",
"context"
],
"type": "string"
},
"ResolverClass": {
"description": "A class of symbol whose presence a backport can dangle on.",
"enum": [
"macro",
"include",
"behaviour",
"qualified_call",
"record",
"local_call",
"type",
"indirect_call"
],
"type": "string"
},
"ResolverCoverage": {
"description": "The set of classes a producer checks, stamped on a verdict envelope\nso a corpus row self-describes its producer's coverage. Stores only\nthe checked set: `unchecked` is derived, so a class can never be in\nboth or neither.",
"properties": {
"checked": {
"items": {
"$ref": "#/$defs/ResolverClass"
},
"type": "array",
"uniqueItems": true
}
},
"required": [
"checked"
],
"type": "object"
},
"SeriesSummary": {
"properties": {
"compatible": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"inapplicable": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"incompatible": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"requires_adaptation": {
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"required": [
"compatible",
"requires_adaptation",
"incompatible"
],
"type": "object"
},
"SeriesVerdict": {
"properties": {
"results": {
"items": {
"$ref": "#/$defs/PinVerdict"
},
"type": "array"
},
"summary": {
"$ref": "#/$defs/SeriesSummary"
}
},
"required": [
"results",
"summary"
],
"type": "object"
},
"ShapeCheckTally": {
"description": "What the live qualified-call gate's return-shape check did with\neach first-party resolved call. Never reasons: a withhold is not a\nfinding, but a round where most calls are shape-blind must read\ndifferently from a round where all of them were compared.",
"properties": {
"compared": {
"description": "Both sides had a `-spec` that parsed to a known type; the shapes\nwere compared. Drift is visible in the reasons, not double-counted\nhere.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_imported": {
"description": "The call resolved through an `-import`: the callee's `-spec`\nis in another module, so the calling module's tables cannot\ncompare it. Local-call axis only.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_no_source": {
"description": "The callee module was not readable on the source side: no\ncheckout was supplied, or the checkout has no file at the\nmodule's path (a defaulted `--repo-dir-path` that is not the\nsource tree lands here, not in `withheld_no_spec`).",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_no_spec": {
"description": "One or both sides declare no `-spec` for the called function.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"withheld_unknown_type": {
"description": "Both sides have a spec but at least one parses to\n`SpecType::Unknown`.",
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"SnapshotSide": {
"description": "Which side of a snapshot comparison the data is missing from.",
"enum": [
"source",
"target",
"both"
],
"type": "string"
},
"SourceDelta": {
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"module": {
"type": "string"
},
"source_spec": {
"type": "string"
},
"target_spec": {
"type": "string"
}
},
"required": [
"module",
"function",
"arity",
"source_spec",
"target_spec"
],
"type": "object"
},
"SymbolRef": {
"oneOf": [
{
"properties": {
"kind": {
"const": "behaviour",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module"
],
"type": "object"
},
{
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"kind": {
"const": "callback",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"function",
"arity"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "function",
"type": "string"
},
"mfa": {
"$ref": "#/$defs/Mfa"
}
},
"required": [
"kind",
"mfa"
],
"type": "object"
},
{
"description": "A function reference whose arity could not be determined from\nthe source line (the call's closing paren sits on a later\nline). Resolves against a snapshot when *any* export carries\nthe name; never produces an arity mismatch.",
"properties": {
"function": {
"type": "string"
},
"kind": {
"const": "function_any_arity",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"module",
"function"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "macro",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "record",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"kind": {
"const": "type",
"type": "string"
},
"module": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"module",
"name",
"arity"
],
"type": "object"
}
],
"properties": {
"origin": {
"$ref": "#/$defs/RefOrigin"
}
},
"type": "object"
},
"TargetFindings": {
"description": "Symbol-axis findings for one row, resolved against the target tree.\nPresent exactly when a target context was supplied; independent of\nevery pin verdict, so an inapplicable row still carries its\nfindings.",
"properties": {
"reasons": {
"description": "Every reason the live-axis target checks produced for this row,\nin production order.",
"items": {
"$ref": "#/$defs/Reason"
},
"type": "array"
}
},
"required": [
"reasons"
],
"type": "object"
},
"TargetMatch": {
"description": "A target commit found to carry the candidate's patch. The subject\nis included so consumers can auto-fill exclusion reasons without\na second git query.",
"properties": {
"commit": {
"type": "string"
},
"subject": {
"type": "string"
},
"via": {
"$ref": "#/$defs/TargetMatchKind"
}
},
"required": [
"commit",
"via",
"subject"
],
"type": "object"
},
"TargetMatchKind": {
"description": "How a tier-1 already-present match against the target branch was\nestablished.",
"oneOf": [
{
"const": "trailer_intersection",
"description": "A walked target commit's `-x` trailer names the candidate (or\none of its trailer origins or inner PR commits).",
"type": "string"
},
{
"const": "trailer_ancestry",
"description": "One of the candidate's own trailer origins is already an\nancestor of the target tip.",
"type": "string"
},
{
"const": "patch_id",
"description": "A walked target commit's normalized patch hash equals the\ncandidate's.",
"type": "string"
}
]
},
"TestCallSite": {
"description": "One `Module:Function/Arity` reference inside a `_SUITE.erl` that\nresolves to a module absent on the target tree. Carries the line\nnumber so the operator can jump straight to the call site.",
"properties": {
"arity": {
"format": "uint8",
"maximum": 255,
"minimum": 0,
"type": "integer"
},
"function": {
"type": "string"
},
"line": {
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"required": [
"function",
"arity",
"line"
],
"type": "object"
},
"TouchedKinds": {
"description": "Per-pin tally of file kinds the patch touched. Lets `promote_inapplicable`\ntell a real green check from a diff with nothing analyzable to check.",
"properties": {
"app_src": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"ci_workflow": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"docs": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"erl": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"hrl": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"makefile": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"mix_exs": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"only_self_surface": {
"description": "The patch touches Erlang surface but references no tracked-dep\nAPI (every non-self pin has zero in-scope references). The CLI\nsets this after `evaluate_series` when a self-pin is present\nand every non-self pin's `tracked_refs` is empty; see\n`InapplicableReason::OnlySelfSurfaceTouched`.",
"type": "boolean"
},
"only_test_visibility": {
"description": "Every changed `.erl` hunk is a Variant A unwrap of test-only\n`-ifdef(TEST)` guards around an `-export` directive (see\n`InapplicableReason::OnlyTestVisibilityChanged`). When true,\nthe patch touches Erlang surface but adds no semantic\ncontent, so an empty reason set should promote to\n`Inapplicable` instead of `Compatible`.",
"type": "boolean"
},
"other": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"rebar_config": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"schema": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"tests": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"TranslationSource": {
"oneOf": [
{
"properties": {
"kind": {
"const": "config_stanza",
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"kind",
"name"
],
"type": "object"
},
{
"properties": {
"kind": {
"const": "external_file",
"type": "string"
},
"name": {
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path",
"name"
],
"type": "object"
}
]
},
"Unanalyzed": {
"description": "Counts of call sites the analyzer could not resolve: `apply/3`-style\nBIFs, and dispatch through a variable module or function. Informational only.",
"properties": {
"apply": {
"default": 0,
"format": "uint",
"minimum": 0,
"type": "integer"
},
"variable_dispatch": {
"default": 0,
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"UnassessedReason": {
"description": "Why a path's apply outcome could not be assessed. The `Ord` only\nbreaks merge ties deterministically; it is not a severity.",
"oneOf": [
{
"const": "binary_file",
"description": "The diff marks the file binary; there is no hunk text to match.",
"type": "string"
},
{
"const": "target_not_text",
"description": "The target blob exists but is not valid UTF-8.",
"type": "string"
}
]
},
"Verdict": {
"oneOf": [
{
"properties": {
"verdict": {
"const": "compatible",
"type": "string"
}
},
"required": [
"verdict"
],
"type": "object"
},
{
"properties": {
"reasons": {
"items": {
"$ref": "#/$defs/Reason"
},
"type": "array"
},
"verdict": {
"const": "requires_adaptation",
"type": "string"
}
},
"required": [
"verdict",
"reasons"
],
"type": "object"
},
{
"properties": {
"reasons": {
"items": {
"$ref": "#/$defs/Reason"
},
"type": "array"
},
"verdict": {
"const": "incompatible",
"type": "string"
}
},
"required": [
"verdict",
"reasons"
],
"type": "object"
},
{
"properties": {
"reason": {
"$ref": "#/$defs/InapplicableReason"
},
"verdict": {
"const": "inapplicable",
"type": "string"
}
},
"required": [
"verdict",
"reason"
],
"type": "object"
}
]
},
"VerdictFingerprint": {
"description": "A verdict's stable identity for measurement: equal fingerprints\nmean the same patch against the same target and pins, whatever\nbackhopper version produced either side. Thirty-two lowercase hex\ncharacters: a truncated BLAKE3 digest, formatted here so\n`backhopper-core` takes no dependency on `blake3`.",
"type": "string"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "The `{schema_version, command, data, exit_code[, warnings]}` frame.\n\n`command` and `warnings` are lenient on the read side (an older\nproducer may omit either); `warnings` is dropped from the wire when\nempty, matching the CLI, which does not emit it today.",
"properties": {
"command": {
"default": null,
"type": [
"string",
"null"
]
},
"data": {
"$ref": "#/$defs/CheckPayload"
},
"exit_code": {
"default": 0,
"format": "int32",
"type": "integer"
},
"schema_version": {
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"warnings": {
"items": {
"$ref": "#/$defs/EnvelopeWarning"
},
"type": "array"
}
},
"required": [
"schema_version",
"data"
],
"title": "WireEnvelope",
"type": "object"
},
"schema_version": 16,
"suite_plan_payload": {
"$defs": {
"BroadImpactModule": {
"description": "A modified module whose suite fanout is an outsized share of all\ndiscovered suites. The cap drops the suites this module alone pulled\nin and records this row instead, so a near-full selection driven by\none helper is never silent.",
"properties": {
"application": {
"type": [
"string",
"null"
]
},
"module": {
"type": "string"
},
"suite_fanout": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"total_suites": {
"format": "uint",
"minimum": 0,
"type": "integer"
}
},
"required": [
"module",
"suite_fanout",
"total_suites"
],
"type": "object"
},
"SuiteInclusionReason": {
"description": "Why a suite was included in the plan. A suite can appear under\nmultiple reasons when more than one rule fires.",
"oneOf": [
{
"description": "The suite file itself appears in the diff.",
"properties": {
"kind": {
"const": "test_modified",
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"kind",
"path"
],
"type": "object"
},
{
"description": "Fast unit or property suite swept because its application has\nmodified source and the suite references at least one of the\nmodified modules.",
"properties": {
"application": {
"type": "string"
},
"kind": {
"const": "unit_or_prop_sweep",
"type": "string"
},
"triggering_modules": {
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"kind",
"application",
"triggering_modules"
],
"type": "object"
},
{
"description": "Suite is in the same application as a modified module and\nreferences that module by name.",
"properties": {
"application": {
"type": "string"
},
"kind": {
"const": "same_app_caller",
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"application",
"module"
],
"type": "object"
},
{
"description": "Suite is in a different application from a modified library\nmodule and references that module by name.",
"properties": {
"kind": {
"const": "cross_app_caller",
"type": "string"
},
"library_application": {
"type": "string"
},
"module": {
"type": "string"
}
},
"required": [
"kind",
"library_application",
"module"
],
"type": "object"
},
{
"description": "Suite was included by a user-configured rule.",
"properties": {
"kind": {
"const": "configured_rule",
"type": "string"
},
"rule_name": {
"type": "string"
},
"triggering_path": {
"type": "string"
}
},
"required": [
"kind",
"rule_name",
"triggering_path"
],
"type": "object"
},
{
"description": "A modified `.erl` is itself a behaviour module; this suite\nreferences one of its implementers.",
"properties": {
"behaviour": {
"type": "string"
},
"implementer": {
"type": "string"
},
"kind": {
"const": "behaviour_implementer_sweep",
"type": "string"
}
},
"required": [
"kind",
"behaviour",
"implementer"
],
"type": "object"
}
]
},
"SuitePlanEntry": {
"description": "One entry in the plan: the suite plus every rule that included it.",
"properties": {
"reasons": {
"items": {
"$ref": "#/$defs/SuiteInclusionReason"
},
"type": "array"
},
"suite": {
"$ref": "#/$defs/SuiteRef"
}
},
"required": [
"suite",
"reasons"
],
"type": "object"
},
"SuiteRef": {
"description": "A test-suite module reference. `module` ends in `_SUITE` by\nconvention but the constructor does not enforce this.",
"properties": {
"application": {
"type": "string"
},
"module": {
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"application",
"module",
"path"
],
"type": "object"
},
"UncoveredApplication": {
"description": "An application with modified source modules that no plan entry\ncovers. Advisory only: the operator picks suites from `suites`\n(or finds the application has none) instead of discovering the\ngap from a silent empty plan.",
"properties": {
"application": {
"type": "string"
},
"discovered_suites": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"modified_modules": {
"format": "uint",
"minimum": 0,
"type": "integer"
},
"suites": {
"description": "The application's discovered suites: the operator's candidate\nlist. Empty means the application has no tests at all.",
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"application",
"modified_modules",
"discovered_suites",
"suites"
],
"type": "object"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Output of `plan()`. Entries are sorted by suite; reasons within\neach entry are in rule-application order.",
"properties": {
"broad_impact": {
"description": "Modules whose suite fanout was capped: each removed the suites it\nalone pulled in, replaced by this row.",
"items": {
"$ref": "#/$defs/BroadImpactModule"
},
"type": "array"
},
"entries": {
"items": {
"$ref": "#/$defs/SuitePlanEntry"
},
"type": "array"
},
"unattributed_paths": {
"description": "Modified paths that resolve to no application, so a plan with\nfewer reasons than inputs is still fully accounted for.",
"format": "uint",
"minimum": 0,
"type": "integer"
},
"uncovered": {
"items": {
"$ref": "#/$defs/UncoveredApplication"
},
"type": "array"
}
},
"required": [
"entries"
],
"title": "SuitePlan",
"type": "object"
},
"summary_row": {
"$defs": {
"TouchedKinds": {
"description": "Per-pin tally of file kinds the patch touched. Lets `promote_inapplicable`\ntell a real green check from a diff with nothing analyzable to check.",
"properties": {
"app_src": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"ci_workflow": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"docs": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"erl": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"hrl": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"makefile": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"mix_exs": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"only_self_surface": {
"description": "The patch touches Erlang surface but references no tracked-dep\nAPI (every non-self pin has zero in-scope references). The CLI\nsets this after `evaluate_series` when a self-pin is present\nand every non-self pin's `tracked_refs` is empty; see\n`InapplicableReason::OnlySelfSurfaceTouched`.",
"type": "boolean"
},
"only_test_visibility": {
"description": "Every changed `.erl` hunk is a Variant A unwrap of test-only\n`-ifdef(TEST)` guards around an `-export` directive (see\n`InapplicableReason::OnlyTestVisibilityChanged`). When true,\nthe patch touches Erlang surface but adds no semantic\ncontent, so an empty reason set should promote to\n`Inapplicable` instead of `Compatible`.",
"type": "boolean"
},
"other": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"rebar_config": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"schema": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"tests": {
"default": 0,
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"type": "object"
},
"VerdictKind": {
"description": "Kind-only projection of `Verdict`: drops the variant payloads so a\nsummary row stays single-line.",
"enum": [
"compatible",
"requires_adaptation",
"incompatible",
"inapplicable"
],
"type": "string"
}
},
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "One row in the summary output: a compact projection of a single\n`SeriesEvaluation` result. JSON and text formatters share the type.",
"properties": {
"apply_conflicts": {
"default": 0,
"description": "Paths the apply forecast predicts will conflict on the target.\nZero when the forecast is clean or was not evaluated; the\nverdict kind never reflects it, so the row states it itself.",
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"parent_count": {
"default": null,
"description": "Parent count of the evaluated commit; `None` for patch and PR\ninputs (no commit identity) and pre-v7 envelopes.",
"format": "uint32",
"minimum": 1,
"type": [
"integer",
"null"
]
},
"series": {
"default": null,
"description": "The series the row was evaluated against. `None` for\npin-targeted single evaluations and pre-v7 envelopes.",
"type": [
"string",
"null"
]
},
"sha": {
"type": "string"
},
"subject": {
"type": "string"
},
"target_findings": {
"default": 0,
"description": "Symbol-axis findings on the target. Zero when the axis found\nnothing or was not evaluated; the verdict kind on an\nall-inapplicable row never reflects it, so the row states it.",
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"touched": {
"$ref": "#/$defs/TouchedKinds"
},
"tracked": {
"description": "Total tracked-dep symbol references summed over every evaluated\npin. Zero means the patch references no tracked-dep API; the\nrow is safe to skip at a glance.",
"format": "uint32",
"minimum": 0,
"type": "integer"
},
"verdict": {
"$ref": "#/$defs/VerdictKind"
}
},
"required": [
"sha",
"verdict",
"touched",
"tracked",
"subject"
],
"title": "SummaryRow",
"type": "object"
},
"title": "backhopper envelope v16"
}