Result adapters

All adapters produce the same Result Protocol and reporting path.

Exit code

Omit results to map a successful command to passed and any other outcome to a distinct command failure. No report file is required.

An exit-code adapter may optionally read captured UTF-8 command output:

run: |
  mkdir -p reports
  set -o pipefail
  make check 2>&1 | tee reports/check.log
results:
  exit-code: reports/check.log
policy:
  approvals:
    node: true

The captured output becomes bounded diagnostic detail rendered as text. Enabling node approval adds the corresponding /qg ignore <node> and /qg remove-ignore <node> controls to the Job Summary and managed dashboard. These controls cannot approve command or adapter failures; approvals only suppress quality findings.

Native JSON

results:
  native: reports/result.json

Identity and provenance must match the declared node and current workflow attempt.

Native producers own domain data: custom summary Markdown, metrics, findings, annotations, diagnostics, and notes. They must not construct the complete Job Summary, stable finding labels, or /qg commands. Quality Graph replaces report-supplied controls with semantic controls derived from the findings and compiled node approval policy, then composes the provider presentation.

SARIF

results:
  sarif: reports/lint.sarif

SARIF levels map to notice, warning, and error. The adapter reads rule IDs, text or Markdown messages, partial fingerprints, and the first physical source location.

JUnit XML

results:
  junit: reports/tests.xml

Both testsuite and testsuites roots are accepted. Failures and errors become stable findings; skipped and total counts become metrics. XML is parsed through defusedxml. A repository-relative testcase file attribute becomes a source location, enabling file approvals. The location uses line 1 because JUnit producers do not share a line-number convention. Absolute paths and parent traversal are rejected. At most 10,000 findings and 100 test traces are serialized; summary and metrics retain full failure counts, and notes state how many findings or traces were omitted.

Reports must exist inside the repository workspace and remain below 10 MiB. Missing, malformed, oversized, and traversal reports create adapter failures rather than rewriting the underlying command outcome.

Producer data contract

For a custom check, use results.native with producer report v0. The input schema is producer-v0.schema.json, also available through qg result schema --producer. This is a data-only input to collection; the published artifact remains Result v0.

{
  "reportVersion": 0,
  "status": "failed",
  "failureKind": "quality",
  "metrics": [{"label": "Files checked", "value": "5"}],
  "findings": [{
    "id": "invalid-setting",
    "severity": "error",
    "message": "The enabled setting must be true.",
    "group": "Configuration"
  }],
  "diagnostics": [{
    "kind": "command",
    "message": "Expected enabled=true",
    "detail": "Observed enabled=false"
  }]
}

reportVersion and terminal status are required; failureKind is required exactly for failed or cancelled results. Metrics, findings, annotations, diagnostics, notes and optional summary content use the existing Result v0 field definitions and limits. Finding IDs must be stable and unique within the report. Unknown fields, unsupported versions, nonterminal states, invalid locations and inconsistent outcomes fail validation. A passing report cannot hide a failed command.

Producers must omit nodeId, title, provenance, controls and schemaVersion. Collection supplies identity and provenance from its execution context, derives controls from graph policy, and validates the resulting artifact. Supplying these fields in a producer report is an error. Complete native Result v0 input remains supported with its existing exact provenance checks.

Quality Graph builds the headings, metric tables, finding groups, diagnostic code blocks, source locations, bounds and administrator controls. Producers supply values and messages, not table layout, status banners or /qg commands. Optional custom summary content remains available for compatibility; it is not needed to produce a complete report.

A runnable custom producer is check_settings.py:

run: python examples/producers/check_settings.py settings.json --output reports/settings.json
results:
  native: reports/settings.json

JUnit and SARIF are standard producer formats converted through the same result and rendering path. JUnit findings include the test name, and diagnostics preserve bounded failure/error traces. For commands without a structured format, captured output is diagnostic text; the framework does not infer source findings or test counts from arbitrary stdout.

v0.2.0