Table of Contents generated with DocToc
pr-management-stats reference implementation
Capability: substrate:analytics
Harness: agnostic
Deterministic reference implementation of the data-fetch +
classification contract that backs the
pr-management-stats skill.
The skill’s agent-emitted render is the default — this script exists for two reasons:
-
Anti-skip insurance. Agents under context pressure can be tempted to omit panels from the dashboard (line charts, CODEOWNERS table, triager-activity table). The skill specifies all 11 panels; agents must render them all. This script encodes the canonical data-fetch shape so the agent has a single source of truth to read the fields from — there is no “the skill says X, the agent guessed Y” drift.
-
CI-renderable artefact. Adopters who want a daily dashboard rendered by CI (rather than an interactive agent session) can run this script on a schedule, extend it with the full render per
render.md, and publish the HTML as a build artefact or gist.
Prerequisites
- Runtime: Python 3.11+, stdlib-only; run as
python3 reference.py/python3 dashboard.py. - CLIs:
gh(GitHub CLI) for the GraphQL fetch;bash+awkfor the optionalgen_charts.shSVG helper. - Credentials / auth: an authenticated
ghsession (gh auth statusmust succeed for the viewer against<upstream>). - Network:
api.github.comviaghGraphQL. (The test suite stubs everyghcall — no network.) - Optional:
pytest(dev-only) viauv run pytestorpython3 -m pytest.
Layout
tools/pr-management-stats/
├── README.md (this file)
├── pyproject.toml (pins the pytest harness; the tool itself is stdlib-only)
├── reference.py (Python implementation: fetch + classify + emit intermediates)
├── dashboard.py (full HTML render extending reference.py — all 11 panels)
└── tests/ (pytest suite: pagination, aggregations, render, JSON parity)
The full HTML dashboard render (per render.md) lives in
dashboard.py; it imports the fetch + classify
primitives from reference.py and inlines its own SVG / CSS helpers.
The tool is directory-portable, not single-file or installable: the
two scripts plus their resources travel together as one directory, and
dashboard.py imports its sibling reference.py by name. Run it as a
script (python3 dashboard.py …) — the script’s own directory is on
sys.path[0], so the sibling import resolves from any working directory.
Because the directory name (pr-management-stats) is not a valid Python
module identifier, the tool is not a package and cannot be run with
python3 -m. The only third-party dependency is pytest, and that is
dev-only (for the test suite); the scripts themselves are stdlib-only.
Invocation
# Reference (fetch + classify + JSON sidecar only)
python3 tools/pr-management-stats/reference.py \
--repo <upstream> \
--viewer <maintainer-handle> \
--since 2026-04-12 \
--out /tmp/dashboard.html
# Full dashboard (all 11 panels rendered as self-contained HTML)
python3 tools/pr-management-stats/dashboard.py \
--repo <upstream> \
--viewer <maintainer-handle> \
--since 2026-04-12 \
--out /tmp/dashboard.html
The script:
- Fetches all open PRs with the full engagement schema
(
comments,latestReviews,reviewThreads,timelineItemswithLABELED_EVENT/READY_FOR_REVIEW_EVENT/CONVERT_TO_DRAFT_EVENT). - Fetches closed/merged PRs since the cutoff.
- Fetches
.github/CODEOWNERS+ changed-file paths for each currently-ready PR. - Classifies each PR per
classify.md—is_engagedrequires ANY maintainer touch (issue comment, review, review-thread comment, label add, draft conversion). - Writes a JSON sidecar with all the counts that feed the dashboard.
Configuration and vendor neutrality
The default triage marker, AI footer, ready-label, and area-prefix are example values for the reference instance these scripts were built against — they are not vendor-neutral, and they do not need to be: every one is a CLI override, so an adopter for another project supplies their own without editing the tool. (The framework’s placeholder convention governs repo slugs and URLs in prose, not these runtime config defaults.) Override per invocation:
python3 dashboard.py --repo <upstream> --viewer <handle> \
--triage-marker "<your quality-criteria marker>" \
--ai-footer "<your bot footer>" \
--ready-label "<your ready label>" \
--area-prefix "<your area label prefix>"
When pagination is cut short (a gh error, a rate limit, or the page
cap is reached), the run does not silently publish a truncated view: a
visible INCOMPLETE DATA banner is added to the HTML and partial: true is written to the JSON sidecar. Transient 5xx / RATE_LIMITED
failures are retried once with backoff before that happens.
Tests
# from the tool directory
uv run pytest # or: python3 -m pytest
The suite is stdlib + pytest only and stubs all gh calls — no
network access:
tests/test_pagination.py— guards the cursor-pagination fix, the retry/backoff path, and the partial-fetch signal.tests/test_aggregations.py— pure aggregation functions (compute_hero_counts,compute_pressure_by_area,compute_recommendations, weekly velocity).tests/test_classify_partial.py— the explicit partial closed-PR classify contract.tests/test_html_render.py— render helpers, including the incomplete-data banner toggle and HTML escaping.tests/test_json_parity.py— runs bothreference.pyanddashboard.pyover one fixture and asserts the dashboard sidecar is a superset of reference’s with identical values on every shared key.
Contract for the agent
When the agent invokes the skill, it MUST:
- Use the GraphQL templates from
fetch.mdverbatim. In particular, the open-PRs query MUST includereviewThreadsandlatestReviewsandtimelineItems— without those, theis_engagedpredicate is undercounted and untriaged numbers blow up artificially. (Earlier iterations offetch.mdclaimed those fields were not needed for stats; that was a documentation bug and has been corrected.) - Implement ALL 11 sections per
render.md. Skipping panels (e.g. dropping the line charts, CODEOWNERS table, triager-activity table) is not an acceptable simplification. - If panel data is unavailable, the panel renders a stub with a one-line explanation of WHY the data is missing — never omit a section silently.
Parity implementations
reference.py provides fetch + classify only. dashboard.py
extends it with the aggregation + HTML emission for all 11 panels
declared in render.md, and is the recommended path for CI-rendered
dashboards. Adopters who want a different language target are
welcome to add additional parity implementations.
Cross-references
pr-management-stats/SKILL.md— skill entry point.pr-management-stats/classify.md—is_engaged/is_triaged/is_untriagedpredicates.pr-management-stats/fetch.md— GraphQL templates.pr-management-stats/aggregate.md— per-panel computations.pr-management-stats/render.md— dashboard layout, recommendation rules.tools/dashboard-generator/— sibling reference implementation forissue-reassess-stats.