Classification
- Change type: enhancement / foundational contract
- Priority: P0
- Expected value: very high — prerequisite for lifecycle tracking, evidence aggregation and honest calibration
- Implementation risk: medium — schema compatibility and identity drift
- Canonical owner:
Own.NET/audit/ while the audit pipeline remains canonical there
Problem
The current FP-judge finding_id is intentionally line-independent and pattern-level:
sha1(path + rule + message)[:16]
That is correct for deduplicating repeated instances before an expensive judge call, but it is not enough for lifecycle tracking. One pattern ID can represent several physical findings in the same file. If one occurrence is fixed and another remains, a single identity cannot represent both outcomes honestly.
The audit pipeline needs three distinct identities:
pattern_id — the existing line-independent logical pattern; backward-compatible with today's finding_id.
occurrence_id — one concrete physical finding emitted by one producer run.
lineage_id — the best-supported cross-commit identity for following an occurrence through line drift, rename or movement.
Required contract
pattern_id
- Preserve the current FP-judge recipe and semantics.
- Keep accepting legacy overlays keyed by
finding_id during a documented compatibility window.
- Make the intentional many-occurrences-to-one-pattern relationship explicit.
occurrence_id
Derive from stable run-local inputs, including at minimum:
producer_run_id
producer/tool identity
rule
path
physical anchor
Requirements:
- two identical findings at different physical sites receive distinct IDs;
- rerendering the same normalized run is deterministic;
- presentation-only ordering does not change the ID;
- occurrence identity never pretends to survive an unrelated producer run.
lineage_id
- Link occurrences across commits only when supported by explicit mapping evidence.
- Prefer symbol/context/AST fingerprints plus Git diff/rename mapping over raw line numbers.
- Represent ambiguity as unresolved or one-to-many evidence; never guess a single lineage merely to keep dashboards tidy.
- Store the mapping evidence and confidence class separately from the ID.
Provenance fields
Each occurrence must carry enough provenance to reproduce or reject it:
producer_run_id
producer_name
producer_version
input_digest
config_digest
source_commit
schema_version
Unknown/missing provenance must remain visible as a coverage limitation, not silently synthesized.
Compatibility and migration
- Version the normalized finding schema.
- Existing
findings.json and fp-verdicts.json fixtures remain readable.
- Existing
finding_id consumers either map it to pattern_id or fail with an actionable version error.
- No existing diagnostic code, severity, message or analyzer verdict changes in this issue.
Required controls
- Two identical messages/rules in one file on different lines:
- same
pattern_id;
- different
occurrence_id.
- Pure line drift between commits:
- new occurrence;
- same supported lineage.
- One repeated occurrence fixed, another retained:
- lineage outcomes remain independent.
- File rename with unchanged symbol/context:
- lineage may continue with rename evidence.
- Ambiguous copy/move:
- lineage remains unresolved or explicitly branched, never guessed.
- Producer/config/input digest changes:
- provenance changes are observable.
- Legacy FP overlay:
- still expands one pattern verdict to all matching current occurrences only when the input digest contract is valid.
Acceptance
Non-goals
- No Evidence Ledger implementation beyond the identity/provenance seam.
- No ranking, probability or calibration model.
- No auto-suppression or merge blocking.
- No analyzer precision/soundness changes.
- No forced lift-out from
Own.NET/audit/ to OwnAudit.
Classification
Own.NET/audit/while the audit pipeline remains canonical thereProblem
The current FP-judge
finding_idis intentionally line-independent and pattern-level:That is correct for deduplicating repeated instances before an expensive judge call, but it is not enough for lifecycle tracking. One pattern ID can represent several physical findings in the same file. If one occurrence is fixed and another remains, a single identity cannot represent both outcomes honestly.
The audit pipeline needs three distinct identities:
pattern_id— the existing line-independent logical pattern; backward-compatible with today'sfinding_id.occurrence_id— one concrete physical finding emitted by one producer run.lineage_id— the best-supported cross-commit identity for following an occurrence through line drift, rename or movement.Required contract
pattern_idfinding_idduring a documented compatibility window.occurrence_idDerive from stable run-local inputs, including at minimum:
Requirements:
lineage_idProvenance fields
Each occurrence must carry enough provenance to reproduce or reject it:
Unknown/missing provenance must remain visible as a coverage limitation, not silently synthesized.
Compatibility and migration
findings.jsonandfp-verdicts.jsonfixtures remain readable.finding_idconsumers either map it topattern_idor fail with an actionable version error.Required controls
pattern_id;occurrence_id.Acceptance
pattern_id,occurrence_idandlineage_idhave distinct tested semantics.finding_idcompatibility is explicit and tested.Non-goals
Own.NET/audit/to OwnAudit.