Skip to content
Open the dashboard
Developer docs

Output formats

Developers

groundrule check reports its results in four formats: terminal for people, JSON for scripts, SARIF for code-scanning tools, and Markdown for pull-request comments and CI job summaries. This page shows each one with a real example and lists every field.

Choose the format with -f / --format, and write it to a file with -o / --output:

Terminal window
npx @groundrule/cli check # terminal
npx @groundrule/cli check -f json -o groundrule.json
npx @groundrule/cli check -f sarif -o groundrule.sarif
npx @groundrule/cli check -f markdown -o groundrule.md
npx @groundrule/cli check --summary "$GITHUB_STEP_SUMMARY" # terminal, plus a Markdown summary
Format For Includes legacy findings Includes excepted findings
terminal People Counted; listed with --verbose Counted; listed with --verbose
json Scripts and dashboards Yes, with isNew: false Yes, with suppressedBy
sarif GitHub code scanning and other SARIF tools Yes, with isNew: false Yes, marked as suppressed
markdown PR comments and job summaries Counted only Counted only

With legacy: ignore in the config, legacy findings are left out of every format. With -o, the report goes to the file and the CLI prints one line, for example Wrote sarif report to groundrule.sarif (failed). The exit code is the same in every format. See Exit codes.

Configuration warnings and errors go to standard error in the json, sarif and markdown formats, so they never corrupt the report. The terminal format prints them at the top.

All examples on this page come from one run: a change that adds a direct Stripe import (ACME-004, a blocker) and a console.log (TS-001, a warning), in a repository without a lockfile (SEC-005, already there before the change).

The default. Written for people, with failing findings first and a fix on every finding.

groundrule check · 36 standards · 1 file changed
✕ ACME-004 Route all Stripe calls through the gateway
BLOCKER · deterministic (regex)
src/http/refunds.ts:1
Stripe imported outside the payments gateway
1: import Stripe from "stripe";
→ Import from src/payments/gateway.ts and call its functions.
→ groundrule explain ACME-004
⚠ TS-001 No console.log in application code
warning · deterministic (regex)
src/http/refunds.ts:2
console.log in application code
2: console.log("refunding");
→ Replace it with the project's logger, or remove it.
→ groundrule explain TS-001
○ 1 legacy finding not introduced by this change (show with --verbose)
Failed ✓ 20 passed ✕ 1 failed ⚠ 1 warning ◇ 14 guidance · 0.1s
Part What it shows
Headline The number of standards, and N files changed (with vs <base> when you passed --base), or N files (full audit) with --all.
Config lines ✕ Config error and ! warnings from loading, with file, line and field.
One block per standard with findings An icon, the ID and title; the severity and the source (deterministic (regex), static analysis (semgrep)); up to five locations, each with the message and up to two lines of evidence; the fix (→); and → groundrule explain <ID>.
○ line Legacy findings and findings covered by exceptions that are hidden. --verbose lists them, tagged legacy or excepted by EX-1042.
– lines Standards not evaluated or partly evaluated, with the reason, such as a missing tool.
Summary Passed or Failed, then the counts, then the time taken.
Icon Meaning
✕ (severity in capitals) At least one finding fails the check.
⚠ Findings that don’t fail: below failOn, legacy, or from a rule at Advise.
? A possible finding: a concern, below the check’s minConfidence.
Summary count Meaning
✓ N passed Standards checked with no failing or warning findings.
✕ N failed Standards with at least one failing finding.
⚠ N warnings Standards with new findings that don’t fail.
– N not evaluated Standards whose checks couldn’t run.
◇ N guidance Standards with no checks.
N not applicable Standards that don’t apply to this repository, or are disabled or not active.

When a standard has more than five findings, the rest are summed up as … 12 more in 4 files (show all with --verbose). Colors follow NO_COLOR and FORCE_COLOR; see Environment and files.

A stable, machine-readable report. schemaVersion changes only on a breaking change.

{
"schemaVersion": 1,
"tool": { "name": "groundrule", "version": "0.1.0" },
"passed": false,
"context": {
"mode": "changes",
"files": 6,
"changedFiles": 1,
"languages": ["typescript"],
"frameworks": ["fastify"],
"durationMs": 64
},
"summary": {
"standards": 3,
"passed": 1,
"failed": 1,
"warned": 1,
"notEvaluable": 0,
"guidance": 0,
"skipped": 0,
"violations": 3,
"concerns": 0,
"suppressed": 0,
"legacy": 1,
"blocking": 1
},
"outcomes": [
{
"id": "ACME-004",
"title": "Route all Stripe calls through the gateway",
"severity": "blocker",
"violations": 1,
"concerns": 0,
"status": "failed"
},
{
"id": "SEC-005",
"title": "Commit a dependency lockfile",
"severity": "warning",
"violations": 1,
"concerns": 0,
"status": "passed"
},
{
"id": "TS-001",
"title": "No console.log in application code",
"severity": "warning",
"violations": 1,
"concerns": 0,
"status": "warned"
}
],
"findings": [
{
"standardId": "ACME-004",
"standardVersion": 1,
"evaluator": "regex",
"source": "deterministic",
"status": "violation",
"severity": "blocker",
"confidence": "certain",
"location": { "file": "src/http/refunds.ts", "startLine": 1 },
"message": "Stripe imported outside the payments gateway",
"evidence": ["1: import Stripe from \"stripe\";"],
"remediation": "Import from src/payments/gateway.ts and call its functions.",
"isNew": true,
"fingerprint": "d9a7534a9e17467c3eaa7bd3b33c27cd",
"blocking": true
},
{
"standardId": "SEC-005",
"standardVersion": 1,
"evaluator": "files",
"source": "deterministic",
"status": "violation",
"severity": "warning",
"confidence": "certain",
"message": "No dependency lockfile is committed",
"evidence": ["No file matches **/package-lock.json", "No file matches **/pnpm-lock.yaml"],
"remediation": "Run your package manager's install and commit the lockfile it creates.",
"isNew": false,
"fingerprint": "879a72640ddf11beba4aff6b71bfbe8f",
"blocking": false
}
],
"diagnostics": []
}

This run used --only ACME-004,TS-001,SEC-005; the TS-001 finding is left out above, and the SEC-005 evidence is shortened.

Field Type Description
schemaVersion number 1.
tool object name (groundrule) and version (the CLI version).
passed boolean false when at least one finding fails the check.
context object What was checked.
summary object Counts.
outcomes list One entry per standard.
findings list One entry per finding, failing ones first, then by severity, file and line.
diagnostics list Configuration warnings and errors.
Field Description
mode changes or all.
base The --base ref, when given.
files Files in the repository that checks could read.
changedFiles Changed files (0 in all mode).
languages, frameworks What the CLI detected.
durationMs How long the run took.
Field Counts
standards Standards considered.
passed, failed, warned Standards by outcome.
notEvaluable Standards whose checks couldn’t run.
guidance Standards with no checks.
skipped Standards not applicable, disabled, or not active.
violations, concerns Findings not covered by an exception.
suppressed Findings covered by exceptions.
legacy Findings not introduced by the change.
blocking Findings that fail the check.
Field Description
id, title, severity The standard. severity reflects overrides and, in a connected repository, Advise (blockers become warnings).
status passed, failed, warned, not-evaluable, guidance or skipped.
reason Why it was skipped or not (fully) evaluated, for example Not applicable: framework react not found. or Disabled by config override: <reason>.
violations, concerns Its findings not covered by exceptions.

Each finding follows the published finding.schema.json, plus blocking.

Field Type Description
standardId string The standard’s ID.
standardVersion number The standard’s metadata.version.
evaluator string Which evaluator found it, for example regex.
source enum Where the verdict came from: deterministic, static-analysis, ai or external.
status enum violation (not met), concern (possibly not met, below the confidence needed), pass, or not-evaluable.
severity enum blocker, warning, advisory or info.
confidence enum low, medium, high or certain.
location object file (relative to the repository), startLine, and optionally endLine, startColumn, endColumn. Missing for repository-level findings, such as a missing file.
message string One sentence: what is wrong.
evidence list of strings Why the evaluator believes it, such as the matching line.
remediation string How to fix it, from the check or the standard.
isNew boolean true if introduced by the change, false if legacy.
suppressedBy string The ID of the exception that covers it, such as EX-1042.
fingerprint string A stable identity across runs, based on the standard, evaluator, file and code, not the line number.
blocking boolean true if this finding fails the check.
Field Description
severity error or warning.
file The file, relative to the repository when it is inside it.
line, column Where, when known.
path The field, for example spec.checks[0].pattern.
message What is wrong.

SARIF 2.1.0, the format GitHub code scanning and many other tools read. It holds every violation and concern, new and legacy.

{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "Groundrule",
"informationUri": "https://groundrule.dev",
"semanticVersion": "0.1.0",
"rules": [
{
"id": "ACME-004",
"name": "ACME004",
"shortDescription": { "text": "Route all Stripe calls through the gateway" },
"fullDescription": { "text": "Never import stripe outside src/payments/gateway.ts. Call the gateway's functions, such as createPaymentIntent, instead." },
"help": { "text": "Never import stripe outside src/payments/gateway.ts. Call the gateway's functions, such as createPaymentIntent, instead.\n\nWhy: One place for retries, idempotency keys, and audit logging of payments.\n\nFix: Import from src/payments/gateway.ts and call its functions." },
"defaultConfiguration": { "level": "error" },
"properties": { "tags": ["groundrule", "payments"], "owner": "team:payments" }
}
]
}
},
"originalUriBaseIds": { "%SRCROOT%": { "uri": "file:///" } },
"results": [
{
"ruleId": "ACME-004",
"ruleIndex": 0,
"level": "error",
"message": { "text": "Stripe imported outside the payments gateway\nFix: Import from src/payments/gateway.ts and call its functions." },
"locations": [
{
"physicalLocation": {
"artifactLocation": { "uri": "src/http/refunds.ts", "uriBaseId": "%SRCROOT%" },
"region": { "startLine": 1 }
}
}
],
"partialFingerprints": { "groundrule/v1": "d9a7534a9e17467c3eaa7bd3b33c27cd" },
"properties": {
"source": "deterministic",
"evaluator": "regex",
"confidence": "certain",
"isNew": true,
"blocking": true,
"standardVersion": 1
}
}
]
}
]
}

How Groundrule maps to SARIF:

SARIF From
rules[] One per standard with findings: id, name (the ID without dashes), the title, the requirement, help text (requirement, Why: intent, Fix: remediation), and properties.tags (groundrule and the standard’s category) and owner.
defaultConfiguration.level, results[].level blocker → error, warning → warning, advisory and info → note. Concerns are always note.
message.text The finding’s message, and Fix: with the remediation.
locations The file and lines, relative to the repository root. A finding without a file points at line 1 of the standard’s file.
partialFingerprints["groundrule/v1"] The finding’s fingerprint, so code scanning tracks it across commits.
suppressions For a finding covered by an exception: kind: external, justification Groundrule exception EX-1042.
properties source, evaluator, confidence, isNew, blocking, standardVersion.

To show findings in GitHub code scanning, upload the file with GitHub’s upload-sarif action. The job needs the security-events: write permission:

- run: npx @groundrule/cli check --base origin/${{ github.base_ref }} -f sarif -o groundrule.sarif
env:
GROUNDRULE_TOKEN: ${{ secrets.GROUNDRULE_TOKEN }}
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: groundrule.sarif

if: always() uploads the report even when the check step fails. See Run it in CI.

A short summary for a pull-request comment or a CI job summary. It lists only new findings that aren’t covered by an exception.

### Groundrule · ✕ 1 standard failed
| | Standard | Finding | Where | Source |
|---|---|---|---|---|
| ✕ | **ACME-004** Route all Stripe calls through the gateway | Stripe imported outside the payments gateway<br>**Fix:** Import from src/payments/gateway.ts and call its functions. | `src/http/refunds.ts:1` | deterministic |
| ⚠ | **TS-001** No console.log in application code | console.log in application code<br>**Fix:** Replace it with the project's logger, or remove it. | `src/http/refunds.ts:2` | deterministic |
✓ 1 passed · 1 legacy finding
<sub>Groundrule 0.1.0 · run `groundrule explain <ID>` for details</sub>
Part What it shows
Headline ✕ N standards failed, ⚠ Passed with N warnings, or ✓ All standards passed.
Table One row per new finding, up to 50: an icon (✕ fails, ⚠ doesn’t, ? concern), the standard, the message and fix, the location (repository when there is no file), and the source (deterministic, static analysis, or AI · <confidence>). After 50 rows, a last row says how many more there are.
Notes Counts that apply: passed, guidance, not evaluated, not applicable, legacy findings, and findings covered by exceptions.
Not fully evaluated A collapsed list of standards whose checks couldn’t all run, with the reason.
Footer The CLI version and a pointer to explain.

Two ways to use it:

  • A job summary. --summary <file> appends the Markdown to a file, in addition to the main report. In GitHub Actions, pass $GITHUB_STEP_SUMMARY and the summary appears on the run’s page. You can combine it with any --format.
  • A pull-request comment. Write it with -f markdown -o groundrule.md, and post the file with your CI’s tools. Groundrule doesn’t post pull-request comments or checks itself yet.