Skip to content

feat(sarif): emit SARIF 2.1.0 + let the oracle read own-check through it#42

Merged
PhysShell merged 2 commits into
mainfrom
claude/sarif-export
Jun 19, 2026
Merged

feat(sarif): emit SARIF 2.1.0 + let the oracle read own-check through it#42
PhysShell merged 2 commits into
mainfrom
claude/sarif-export

Conversation

@PhysShell

@PhysShell PhysShell commented Jun 19, 2026

Copy link
Copy Markdown
Owner

Add own-check … --format sarif, a SARIF 2.1.0 log alongside human/github/
msbuild, and teach scripts/oracle_compare.py to ingest own-check SARIF through
the SAME parse_sarif it already uses for Infer#/CodeQL — retiring the bespoke
own-check text parser from the oracle's critical path (the parser-drift class of
bug that silently dropped findings on the ScreenToGif run).

Slice 1 — emitter (ownlang/ownir.py): build_sarif(findings, severity) builds one
run whose tool.driver is Own.NET (rules catalogue = the OWN codes present, titled
from diagnostics.TITLES) and one result per finding (ruleId = OWN code, C#
file/line as physicalLocation, message with the [resource:] tag, kind +
subscription triple in properties). Wired as a fourth --format; JSON to stdout,
summary to stderr, exit code unchanged. SARIF's note level carries advisory
OWN050 (a coverage skip, not a warning-tier leak) — semantics the flat surfaces
cannot express.

Slice 2 — oracle ingestion (scripts/oracle_compare.py): build_own sniffs SARIF
vs text; _oracle_class classifies tool=="own" by OWN code so the two own input
formats bucket identically. Selftest pins a hand-built own-SARIF case (23/23);
tests/test_ownir.py pins the real round-trip build_sarif -> parse_sarif -> leak
(88/88). ruff + mypy --strict clean.

Realizes the first step of the SARIF-exporter backlog item; design + follow-ups
(flip oracle.yml to feed SARIF, mine_report parser->aggregator, code-scanning
upload) in docs/notes/sarif-export.md.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01Rg8kSk1YT14x7A1vo5zgED

Summary by CodeRabbit

Release Notes

  • New Features

    • Added SARIF 2.1.0 machine-readable output support via ownlang (--format sarif).
    • Oracle comparison tool now accepts SARIF logs as input, matching existing OWN.NET classification behavior.
  • Documentation

    • Added SARIF export notes and backlog documentation.
    • Updated oracle documentation to clarify SARIF input support.
  • Bug Fixes / Reliability

    • Improved SARIF-to-class bucketing consistency and reduced format-drift handling.
  • Tests

    • Added/extended SARIF export and oracle round-trip coverage.

Add `own-check … --format sarif`, a SARIF 2.1.0 log alongside human/github/
msbuild, and teach scripts/oracle_compare.py to ingest own-check SARIF through
the SAME parse_sarif it already uses for Infer#/CodeQL — retiring the bespoke
own-check text parser from the oracle's critical path (the parser-drift class of
bug that silently dropped findings on the ScreenToGif run).

Slice 1 — emitter (ownlang/ownir.py): build_sarif(findings, severity) builds one
run whose tool.driver is Own.NET (rules catalogue = the OWN codes present, titled
from diagnostics.TITLES) and one result per finding (ruleId = OWN code, C#
file/line as physicalLocation, message with the [resource:] tag, kind +
subscription triple in properties). Wired as a fourth --format; JSON to stdout,
summary to stderr, exit code unchanged. SARIF's note level carries advisory
OWN050 (a coverage skip, not a warning-tier leak) — semantics the flat surfaces
cannot express.

Slice 2 — oracle ingestion (scripts/oracle_compare.py): build_own sniffs SARIF
vs text; _oracle_class classifies tool=="own" by OWN code so the two own input
formats bucket identically. Selftest pins a hand-built own-SARIF case (23/23);
tests/test_ownir.py pins the real round-trip build_sarif -> parse_sarif -> leak
(88/88). ruff + mypy --strict clean.

Realizes the first step of the SARIF-exporter backlog item; design + follow-ups
(flip oracle.yml to feed SARIF, mine_report parser->aggregator, code-scanning
upload) in docs/notes/sarif-export.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rg8kSk1YT14x7A1vo5zgED
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5193ea65-80a2-4c8d-998f-46c6c1d3fd02

📥 Commits

Reviewing files that changed from the base of the PR and between 1d4f417 and 3a8430d.

📒 Files selected for processing (2)
  • docs/notes/sarif-export.md
  • scripts/oracle_compare.py
✅ Files skipped from review due to trivial changes (1)
  • docs/notes/sarif-export.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/oracle_compare.py

📝 Walkthrough

Walkthrough

Adds SARIF 2.1.0 output support to own-check via a new build_sarif function in ownlang/ownir.py, exposes it as --format sarif in the CLI, and extends oracle_compare.py to accept Own.NET SARIF logs through the shared parse_sarif path. Tests and documentation covering the full feature are also added.

Changes

SARIF Export and Oracle Integration

Layer / File(s) Summary
SARIF 2.1.0 builder in ownir.py
ownlang/ownir.py
Adds TITLES import and introduces _sarif_level, _sarif_result helpers and the public build_sarif function that assembles a complete SARIF 2.1.0 log with a rule catalog populated from distinct Finding.code values and per-finding result objects containing physicalLocation, ruleId, message, and structured properties.
CLI sarif format wiring
ownlang/__main__.py
Adds sarif to _FORMATS, imports build_sarif, updates cmd_ownir to route fmt == "sarif" to a single JSON document emitted on stdout with summary redirected to stderr, and updates CLI help text and docstring.
oracle_compare.py Own.NET SARIF input
scripts/oracle_compare.py
Extends _oracle_class with a tool == "own" classification path, updates build_own to detect JSON-like content and delegate to parse_sarif(tool="own") returning unparsed=0, adds Own.NET SARIF round-trip selftest validation including rule classification and drift detection, and updates --own help text.
Unit and round-trip tests
tests/test_ownir.py
Adds TITLES and build_sarif imports and a comprehensive test block validating SARIF envelope structure, tool driver metadata, rule catalog, result location/message/properties, severity level mapping (advisory→note, warning, error), empty findings handling, and oracle round-trip classification.
SARIF export and oracle docs
docs/notes/sarif-export.md, docs/notes/oracle.md
Adds sarif-export.md covering rationale, implementation slices, severity mapping decisions, and follow-up items; updates oracle.md --own documentation to describe SARIF acceptance alongside human-text logs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PhysShell/Own.NET#10: Adds github/msbuild format options to ownlang/__main__.py and ownlang/ownir.py — the same --format dispatch and rendering infrastructure that this PR extends with sarif.
  • PhysShell/Own.NET#21: Introduces the oracle harness in scripts/oracle_compare.py including the parse_sarif/build_own pipeline that this PR extends with tool="own" SARIF support.
  • PhysShell/Own.NET#26: Changes scripts/oracle_compare.py's classification logic and _selftest() — the main PR adds SARIF ingestion for --own, while the retrieved PR adjusts Infer leak classification and scope behavior validation.

Poem

🐇 Hoppity-hop, I emit JSON now,
A SARIF log with rules — take a bow!
ruleId maps to OWN codes clean,
The oracle reads what the emitter has been.
No parser drift, no bespoke text to parse —
Just one shared path, end to end, not sparse! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main changes: adding SARIF 2.1.0 emission to own-check and enabling the oracle to ingest own-check findings through SARIF format.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/sarif-export

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/notes/sarif-export.md`:
- Around line 13-14: The phrase "dropped 38 of ~36 findings" on line 13 contains
contradictory numbers where the dropped count exceeds the total findings count.
Correct this inconsistency by either reducing the number of dropped findings to
be less than or equal to the total, or by increasing the total findings count to
be greater than the dropped count, ensuring the statement becomes logically
consistent and unambiguous.

In `@scripts/oracle_compare.py`:
- Around line 148-149: The condition checking if text starts with "{" currently
treats any JSON as SARIF and returns parse_sarif with unparsed=0, which can mask
invalid input. Instead of relying solely on the opening brace, validate that the
JSON contains the required SARIF structure (such as checking for the presence of
a "runs" key) before calling parse_sarif with unparsed=0. If the JSON does not
conform to the SARIF schema, fall back to text-based parsing instead to avoid
returning zero findings for malformed input.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 80ddc037-ac58-4914-8781-1254960edf9e

📥 Commits

Reviewing files that changed from the base of the PR and between 9eacbaa and 1d4f417.

📒 Files selected for processing (6)
  • docs/notes/oracle.md
  • docs/notes/sarif-export.md
  • ownlang/__main__.py
  • ownlang/ownir.py
  • scripts/oracle_compare.py
  • tests/test_ownir.py

Comment thread docs/notes/sarif-export.md Outdated
Comment thread scripts/oracle_compare.py Outdated
Addresses the two CodeRabbit review comments on #42.

- oracle_compare.build_own: a leading `{` no longer blindly means SARIF. Parse
  and require a `runs` array before routing to parse_sarif; otherwise (a wrong
  file or malformed JSON) fall through to the text parser, so bad input surfaces
  as unparsed drift instead of a silent "0 findings, clean" — and a malformed-JSON
  crash is avoided too. Pinned by a new selftest case (24/24).
- docs/notes/sarif-export.md: "dropped 38 of ~36 findings" was self-contradictory;
  the real incident is 38 lines left unparsed, so only 3 of ~36 findings reached
  the diff.

ruff + mypy --strict clean; ownir 88/88; oracle selftest 24/24.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rg8kSk1YT14x7A1vo5zgED
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants