Skip to main content

Deterministic, rule-based linter for Adobe Customer Journey Analytics and Adobe Analytics implementations.

Project description

sdr-grader

PyPI Tests Lint Version Sync Python 3.11+ Coverage Tests Ruff uv License: MIT

A deterministic, rule-based linter for Adobe Customer Journey Analytics (CJA) and Adobe Analytics (AA) implementations. It consumes JSON snapshots from cja_auto_sdr and aa_auto_sdr, evaluates them against a versioned, pluggable YAML rubric, and produces a single self-contained HTML report card plus a machine-readable JSON output. No LLMs, no API calls — same input + same rubric always yields the same grade.

sdr-grader report card: a CJA implementation graded F at 51%, with per-category scores

What it grades

sdr-grader ships two rubric packs:

  • strict — master-cert-grade opinion; tight thresholds. For teams who want every finding the rubric can produce.
  • pragmatic — looser thresholds, same rule IDs. For teams who want a sanity check rather than an audit.

Both packs cover the same six categories — schema hygiene, naming consistency, segment complexity, calculated metric maintainability, attribution coverage, and governance posture — and share the same rule IDs; pragmatic just loosens thresholds and demotes severities. Every rule in the default packs grades against data the snapshot itself carries, so out-of-the-box runs need no extra files. A few additional check functions ship registered but unwired — they read JSON the operator attaches at run time and are intended for forked rubrics. See Supplementary inputs for the attachment mechanism and docs/RUBRIC_FORMAT.md for the pack format.

How it grades

A grade run is a one-way pipeline over typed data:

  1. Adapt — the platform adapter (adapters/cja.py or adapters/aa.py) normalizes the JSON snapshot into an Implementation (metrics, dimensions, segments, calculated metrics, governance signals).
  2. Run rules — the engine loops over every rule in the active rubric pack and calls its registered Python check function; each check returns zero or more Findings.
  3. Score — for each non-zero-weight category the subtotal is round((1 − fired_severity / total_severity) × 100), where the severity weights come from the pack's _meta.yaml. The overall score is the category-weighted average, rounded.
  4. Letter — the score maps to a letter via the rubric's descending grade_scale bands.

Because the rubric (category weights, severity weights, grade bands, rule list) is data, swapping packs swaps the opinion without changing a line of grader code. The scoring algorithm itself is in src/sdr_grader/core/grade_calc.py.

Quickstart

# 1. Install (uv tool, pipx, or any other Python installer).
uv tool install sdr-grader

# 2. Generate a snapshot of your data view (CJA) or report suite (AA).
cja_auto_sdr dv_prod_web --include-all-inventory --format json --output snapshot.json   # CJA
aa_auto_sdr  prod_us                              --format json --output snapshot.json   # AA

# 3. Grade it (platform auto-detected from the snapshot).
sdr-grader snapshot.json --output grade.html

# 4. Open the report.
open grade.html  # macOS; xdg-open on Linux

--include-all-inventory makes cja_auto_sdr ship calculated metrics and segments alongside the dimensions/metrics SDR. Without it, the calc-metric and segment rule packs grade against empty inputs and stay silent. aa_auto_sdr includes both inventories by default, so no equivalent flag is needed on the AA side. See the upstream Component Inventory Overview for the full set of --include-* switches.

Or pipe directly without writing a file to disk:

# CJA
cja_auto_sdr dv_prod_web --include-all-inventory --format json --output - | \
  sdr-grader - --output grade.html

# AA
aa_auto_sdr prod_us --format json --output - | \
  sdr-grader - --output grade.html

Input modes

Mode Invocation When to use
File sdr-grader path/to/snapshot.json One-off grade of a single snapshot you already have on disk.
Directory sdr-grader path/to/snapshots/ Point at a folder of dated snapshots; picks the most recent by filename timestamp (falls back to mtime).
sdr-grader path/to/snapshots/ --at 2026-04-01 Same folder, but grade the snapshot closest to (and not after) the given ISO-8601 date — useful for retro grading or reproducing a prior report.
Trend sdr-grader path/to/snapshots/ --trend Grade every dated snapshot in the folder and emit a single trend HTML with sparklines and findings churn.
Shell-out sdr-grader --dataview dv_prod_web Pull a fresh CJA snapshot live via cja_auto_sdr and grade it in one shot — no intermediate file. Requires cja_auto_sdr on PATH; --include-all-inventory is passed automatically so calc-metric and segment rule packs grade against populated inputs.
sdr-grader --rsid prod_us Same idea against AA via aa_auto_sdr. Requires aa_auto_sdr on PATH.
Stdin … | sdr-grader - Stream JSON in from another tool without touching disk — pairs with cja_auto_sdr --include-all-inventory … --output - for ephemeral CI runs.

One run grades one platform. CJA and AA snapshots are not mixed: the platform is auto-detected per snapshot from its JSON shape, and the normalized model holds exactly one platform. In single-file or directory mode, only one snapshot is graded per invocation (siblings in a directory are ignored). In --trend mode, the runner explicitly errors out (snapshots in {dir} mix platforms …) on a mismatch — keep CJA and AA snapshots in separate folders.

Output

  • HTML report card at --output PATH (default grade-{timestamp}.html) — single self-contained file, no external CSS/JS, prints in black-and-white, screenshots cleanly into decks.
  • JSON output at --json PATH — machine-readable representation of the same Report. Suitable for CI dashboards and leaderboards.

Sample report cards (rendered from the bundled fixtures):

Clean (A) Messy (F)
CJA examples/grade-cja-clean.html examples/grade-cja-messy.html
AA examples/grade-aa-clean.html examples/grade-aa-messy.html

Trend reports

Pointed at a directory of timestamped snapshots, --trend grades each one chronologically and renders a single self-contained HTML with the overall trajectory, per-category sparklines, and a findings-churn summary. See docs/TREND_REPORTS.md for the filename conventions and flag interactions, or examples/trend-example.html for a rendered sample.

Supplementary inputs

Rules can optionally grade against data the snapshot doesn't carry by reading from Implementation.supplementary_data. Operators feed that map via --extra-input KEY=PATH (repeatable); rules whose key is absent stay silent, so attaching extra inputs only matters for rules that ask for them. See docs/SUPPLEMENTARY_INPUTS.md.

Internal leaderboards

Teams grading many implementations can build their own percentile reference from collected --json outputs and pass it back as --distribution-data to render comparative context in the report. See docs/LEADERBOARDS.md.

Customizing the rubric

Every layer is tunable: silence a single rule, fork a pack to shift thresholds, write a new check function, or add a whole new platform. The lightest mechanism that works is usually a .sdr-grader.yaml suppression — but heavier moves (forking a pack, adding rules) are supported and documented. See docs/CUSTOMIZATION.md for the full customization spectrum and which mechanism fits which need.

Claude Code skill

The repo ships a Claude Code skill bundle at skills/sdr-grader/ for asking follow-up questions about a sdr-grader --json output without re-running the grader — filter findings by severity / category / rule, pull up the body and remediation for one rule, or diff two grades from different snapshot dates. Install as a plugin (/plugin install brian-a-au/sdr-grader) or as a personal skill; the bundled helper script also runs as plain Python with no extra dependencies. See skills/sdr-grader/README.md for install and usage details, or skills/sdr-grader/SKILL.md for the trigger phrases and helper command reference.

Develop

Requires Python 3.11+ and uv.

uv sync                # set up environment
uv run pytest          # run the test suite
uv run ruff check      # lint
uv run python scripts/generate_examples.py   # regenerate examples/

Documentation

Start here:

Customizing the rubric:

Calibration and audit:

Running and reporting:

Tooling:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sdr_grader-1.1.4.tar.gz (275.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sdr_grader-1.1.4-py3-none-any.whl (111.4 kB view details)

Uploaded Python 3

File details

Details for the file sdr_grader-1.1.4.tar.gz.

File metadata

  • Download URL: sdr_grader-1.1.4.tar.gz
  • Upload date:
  • Size: 275.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sdr_grader-1.1.4.tar.gz
Algorithm Hash digest
SHA256 97041c123c22a0f3ec22a96260cc2f8d077863beef44bfda0444d1a7a33ba5a3
MD5 bbaec9158303b08fc5726223238a4812
BLAKE2b-256 b24604bfec7f2c98d86df33e649593e00840a17c4248f34a41f42f16fe29dcc1

See more details on using hashes here.

Provenance

The following attestation bundles were made for sdr_grader-1.1.4.tar.gz:

Publisher: release.yml on brian-a-au/sdr-grader

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sdr_grader-1.1.4-py3-none-any.whl.

File metadata

  • Download URL: sdr_grader-1.1.4-py3-none-any.whl
  • Upload date:
  • Size: 111.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sdr_grader-1.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 7cd4c0cedab9ec205f933d6336f6f21f12f93be5df1a840c9c0a6b6ef9e6d93b
MD5 722caceac08fec5c918a44fec79ef927
BLAKE2b-256 f135885205df87eb07af1c1270d0d7b179c4735d937f1c41e3f3c80e7ad11ce3

See more details on using hashes here.

Provenance

The following attestation bundles were made for sdr_grader-1.1.4-py3-none-any.whl:

Publisher: release.yml on brian-a-au/sdr-grader

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page