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
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 intoPipelineResult.DetectorWarnings. That list reaches every surface: thewarningscollection of the scan/diff/explain JSON documents, the text and Markdown reports, progress children,-vlogs, and MCP diagnostics.DetectorWarningType.DegradesCoverageis the single predicate policy branches on —baselineMutationWarningCountuses 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, andAuditWarningsare still[]engine.PipelineWarning{Source, Message}— no type, no location, and the source is a free-text name parsed out of error strings byPipelineWarningsFromError.--format jsonconsumer cannot see that OSV timed out or that an analyzer degraded, and-qhides them entirely.baselineMutationWarningCountcounts 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:
sdk(the name cannot beDetectorWarning— something likesdk.Warning{Stage, Type, Code, Source, Message}with detection keeping its richerSubproject/Manifestfields, orDetectorWarningbecoming a specialization).Sourcestops depending on error-message formatting.warningscollection per response document covering every stage, with the stage on each entry.DegradesCoverageextended per stage: a matcher that failed outright degrades coverage; a matcher that skipped an ineligible package does not.Considerations
warnings[]gains entries from stages that never appeared there. Regeneratingdocs/schemas/*and any smoke golden whose run has a matcher/auditor warning is part of the work.Type/Codepair should collapse into one field.Codeis populated only forpackage-managerwarnings today, so the split may not pay for itself once a second stage adopts the type.Acceptance
-qand non-terminal CI runs can still see them (report and/or JSON, matching what feat(engine): report CI-readiness hints for package-manager mismatches #335 did for detection).🤖 Generated with Claude Code