Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,39 @@ impl DiffIndex {
.is_some_and(|rs| rs.iter().any(|r| *r.start() <= end && start <= *r.end()))
}

/// New-side lines on `path` whose canonical text contains `needle`, in
/// ascending order. This is the same text the model was shown, so a lookup
/// answers "where in this file does the construct the finding names
/// actually appear" without re-reading the worktree.
///
/// The comparison ignores case. Callers use this to decide whether to
/// distrust a finding, so a case difference between prose and source must
/// count as corroboration rather than as evidence against the anchor.
pub fn new_side_lines_containing(&self, path: &str, needle: &str) -> Vec<u32> {
if needle.is_empty() {
return Vec::new();
}
let needle = needle.to_ascii_lowercase();
let mut lines: Vec<u32> = self
.new_evidence
.iter()
.filter(|((candidate, _), text)| {
candidate == path && text.to_ascii_lowercase().contains(&needle)
})
.map(|((_, line), _)| *line)
.collect();
lines.sort_unstable();
lines
}

/// True when the diff carries any new-side text for `path`. A path with no
/// new-side coverage cannot corroborate or contradict an anchor.
pub fn has_new_side_text(&self, path: &str) -> bool {
self.new_evidence
.keys()
.any(|(candidate, _)| candidate == path)
}

pub fn is_empty(&self) -> bool {
self.ranges.is_empty()
}
Expand Down
12 changes: 12 additions & 0 deletions src/envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,18 @@ pub enum SuppressionReason {
BelowSeverity,
BelowConfidence,
MaxFindings,
/// The finding's prose names a construct that the diff places elsewhere on
/// the same path than the line it cites. A reader cannot verify a claim
/// against the wrong code, so the finding is not publishable as written.
AnchorMismatch,
/// The finding restates a claim that another, retained finding already
/// makes about a different location. Only the retained copy is published,
/// and it names the other affected locations.
DuplicateRootCause,
/// A content-policy claim built on top of a finding that was itself
/// suppressed as mis-anchored. It inherits the misreading and cannot stand
/// on its own.
DerivedFromSuppressed,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down
Loading
Loading