Skip to content

Unify match/analyze/audit warnings with the typed detection warning channel #340

Description

@bomly-guy

Follow-up from #335 (which unified the detection-stage warnings; see #247 for the original motivation).

#335 replaced detection's three ad-hoc warning paths with one type, sdk.DetectorWarning{Type, Code, Source, Subproject, Manifest, Message}, collected into PipelineResult.DetectorWarnings. That list reaches every surface: the warnings collection of the scan/diff/explain JSON documents, the text and Markdown reports, progress children, -v logs, and MCP diagnostics. DetectorWarningType.DegradesCoverage is the single predicate policy branches on — baselineMutationWarningCount uses it so an advisory warning does not block recording a baseline while a failed detector chain still does.

The other three stages were left as they were:

  • PipelineResult.MatchWarnings, AnalyzeWarnings, and AuditWarnings are still []engine.PipelineWarning{Source, Message} — no type, no location, and the source is a free-text name parsed out of error strings by PipelineWarningsFromError.
  • They surface only as progress children and MCP diagnostics. They are absent from every response document, so a --format json consumer cannot see that OSV timed out or that an analyzer degraded, and -q hides them entirely.
  • baselineMutationWarningCount counts all of them unconditionally, which is the safe default but means it cannot distinguish "the matcher failed, so findings may be missing" from a purely advisory matcher note.

Proposal

Give the remaining stages the same treatment. Sketch, not a prescription:

  • A stage-carrying warning type in sdk (the name cannot be DetectorWarning — something like sdk.Warning{Stage, Type, Code, Source, Message} with detection keeping its richer Subproject/Manifest fields, or DetectorWarning becoming a specialization).
  • Matchers, analyzers, and auditors return warnings as data rather than the engine parsing them out of joined error text, so Source stops depending on error-message formatting.
  • One warnings collection per response document covering every stage, with the stage on each entry.
  • DegradesCoverage extended per stage: a matcher that failed outright degrades coverage; a matcher that skipped an ineligible package does not.

Considerations

  • The compact MCP shape already tags diagnostics with a stage, so that surface needs no contract change — only the CLI JSON documents grow.
  • Response-schema change: warnings[] gains entries from stages that never appeared there. Regenerating docs/schemas/* and any smoke golden whose run has a matcher/auditor warning is part of the work.
  • Worth deciding at the same time whether detection's Type/Code pair should collapse into one field. Code is populated only for package-manager warnings today, so the split may not pay for itself once a second stage adopts the type.

Acceptance

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions