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.
Parent: #250
Recommended tier: strong
Depends on: #251
Goal
Extend
rust/crates/own-diagnosticsfrom data-only verdict types to the full normalized diagnostic contract needed before report/SARIF and bridge cutover:Python remains the source of truth. A divergence is a Rust bug unless changed separately Python-first.
Sources of truth
ownlang/diagnostics.pyownlang/evidence.pyownlang/analysis.pyspec/Diagnostics.mdDeliverable
Rust model
Add or complete data structures for:
Diagnostics remain data, not
Result/errors.Rendering
Implement the normalized human-message contract used by the current Python core:
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
(path,line,code)but distinct by subject/evidence;Architecture guardrails
own-diagnosticsmay depend only on the agreed location/span leaf, neverown-syntax,own-cfgorown-analysis.own-analysismay construct diagnostics but owns no presentation logic.Fixture discipline
The PR must document:
Unexplained countmust be zero.Acceptance
cargo fmt --check, workspace clippy and tests pass.