Skip to content

P-022 step 5a: port diagnostic messages and ordered Evidence with Python parity #255

Description

@PhysShell

Parent: #250
Recommended tier: strong
Depends on: #251

Goal

Extend rust/crates/own-diagnostics from data-only verdict types to the full normalized diagnostic contract needed before report/SARIF and bridge cutover:

  • canonical message;
  • severity;
  • subject;
  • resource kind;
  • primary source location;
  • ordered Evidence records;
  • stable diagnostic identity and ordering.

Python remains the source of truth. A divergence is a Rust bug unless changed separately Python-first.

Sources of truth

Deliverable

Rust model

Add or complete data structures for:

  • diagnostic code and severity;
  • primary span/path/line;
  • subject and resource kind;
  • message arguments or another representation that reproduces Python exactly;
  • ordered Evidence steps;
  • evidence labels/roles and related source locations;
  • deterministic normalized comparison keys.

Diagnostics remain data, not Result/errors.

Rendering

Implement the normalized human-message contract used by the current Python core:

  • canonical message text;
  • deterministic formatting;
  • stable ordering for equal-location findings;
  • path normalization matching Python;
  • Unicode-safe identifiers and paths;
  • no presentation dependency on the parser or solver.

Python-authored fixture

Add an explicit generator producing a frozen fixture containing, at minimum:

{
  "path": "...",
  "line": 42,
  "code": "OWN001",
  "severity": "warning",
  "message": "...",
  "subject": "...",
  "resource_kind": "...",
  "evidence": [
    {"path": "...", "line": 10, "kind": "...", "label": "..."}
  ]
}

Rust steady-state replay must run with zero Python.

Required controls

  • same code on different lines;
  • same line/code with different subjects;
  • multiple evidence steps with order significance;
  • missing optional evidence;
  • multi-file findings;
  • Windows and Unix path forms;
  • non-ASCII paths and identifiers;
  • fallback/unknown resource kinds;
  • diagnostics tied on (path,line,code) but distinct by subject/evidence;
  • DI004 and DI005 primary anchors;
  • equal-line effect storms in different files;
  • duplicate-site last-wins cases already pinned by feat(rust): P-022 step 4 — port own-analysis (worklist solver + ownership/lifetime/effect/DI) with layered parity (#214) #249;
  • every currently emitted OWN/DI/EFF family represented.

Architecture guardrails

  • own-diagnostics may depend only on the agreed location/span leaf, never own-syntax, own-cfg or own-analysis.
  • own-analysis may construct diagnostics but owns no presentation logic.
  • No SARIF or report JSON in this issue.
  • No OwnIR bridge.
  • No new diagnostic codes, severity changes or analyzer heuristics.
  • Do not change Python output merely to simplify Rust.

Fixture discipline

The PR must document:

Python source of truth:
Fixture path:
Regeneration command:
Rust replay command:
Python-only count:
Rust-only count:
Changed count:
Ordering-only count:
Unexplained count:

Unexplained count must be zero.

Acceptance

  • Exact normalized parity for path, line, code, severity, message, subject, resource kind and ordered Evidence.
  • Rust replay runs without Python.
  • Fixture regeneration is explicit and reviewed as a semantic diff.
  • Existing verdict fixtures remain unchanged unless the new fixture references them without modifying acceptance.
  • Cargo DAG fitness tests remain green.
  • cargo fmt --check, workspace clippy and tests pass.
  • Python test/lint gates pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions