Repository navigation
Canonical PAX/RTP data model, corrected 2024/2026 data, SCCA classification, and automated updates - #1
Merged
Conversation
The old scraper discarded rename annotations (e.g. "ST (STS)", "AST(STR)"), truncated values by string slicing, and swallowed every parse error, so bad pages produced silently wrong data. The generator merged into rtp.json with an append strategy, which duplicated a year on every re-run and could not apply a revised page, and its regex-derived categories were wrong for XP, XS and 31 other classes. The form generator never ran. The scraper now parses each page strictly into typed values (year, class code, verbatim label, exact decimal index, "Last update" date) and fails loudly on anything unexpected. It honors solotime.info's 10 s crawl delay, restricts redirects to the source host, and bounds response size and time. A revised page replaces its whole year. The generator rebuilds every output from the canonical CSV, so running it twice is a no-op, and JSON Schemas describe the published files. Dependencies move to uv: pyproject.toml plus a hash-locked uv.lock with a one-week release-age limit and source builds disabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… rules The per-year JSON had drifted from the source: solotime.info revised the 2024 index on 2023-12-20, ten days after it was scraped (XS and SSR removed, XU 0.869 added, EVX 0.830 -> 0.834, XA 0.842 -> 0.844), and 2026 was never added. Every year 1995-2026 was re-fetched; apart from those changes the only differences are verbatim labels now recorded (2006, 2007, 2009, 2010, 2025). CSV/rtp.csv holds each index exactly as published plus its page label. CSV/sources.csv records the URL, the page's own "Last update" date, the fetch time and a SHA-256 for each year, so later revisions are detectable. CSV/classes.csv assigns SCCA class names and categories by year from the National Solo Rules (and SCCA's own web excerpts before 2005), with a citation and a verified/unverified status: 1,092 of 1,311 class-years are verified. Notable: Stock became Street in 2014 (the old Stock classes ran one year as Street-R). The 2024 rulebooks independently confirm the December 2023 revision. CSV/lineage.csv links renamed and redistributed classes (2008 Formula Junior, 2009 ST/STS/SSM, 2014 Street-R, 2023 EVX, 2025 Street Touring), because SCCA reuses class codes and a code's history alone is misleading. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Consumers, expected to be other clubs' scoring software, get corrected data and a combined file that can be queried by year: - JSON/<year>.json keeps its shape. 2024 reflects the December 2023 revision, 2026 is added, and 2025 keys drop the "(STR)"-style suffixes (AST, BST, DST, EST, GST) that were scraping artifacts. - JSON/latest.json and YAML/latest.yaml always hold the newest year. - YAML year keys are now strings, matching JSON (they were integers). - rtp.json / rtp.yaml (SchemaVersion 2) map each class's years to Index, Name, SoloCategory and ClassificationVerified, replacing a list of single-key objects that allowed duplicates, and add Predecessors / Successors plus per-year source metadata. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
solotime.info publishes a new year each autumn and revises indices into the season; the 2024 revision went unnoticed for almost three years. A weekly workflow now fetches the newest published year and the one before it and opens a reviewable PR when anything changes. PRs that introduce an unclassified class open as drafts labeled needs-classification. Security design (audited over several passes): - A read-only "build" job runs uv, the scraper, the generator and tests and hands off a git patch. The write-scoped "open-pr" job runs no third-party Python; it applies the patch with a stdlib-only guard that inspects git's index (byte-exact paths, regular-file modes only) so a compromised build cannot touch workflows or plant symlinks, then sanitizes the PR body. - Actions and the uv binary are pinned by SHA/checksum; workflow inputs reach the shell only through validated env vars. CI runs the tests and fails if generated files differ from the CSV. Dependabot tracks actions and uv.lock with a seven-day cooldown. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Third-party software needs to know which files are canonical vs generated, stable URLs, what Name/SoloCategory/ClassificationVerified mean (including null for classes no source names), and that class codes are reused across SCCA restructures. The CHANGELOG lists the breaking v2 changes and data corrections for existing consumers. Maintainer notes cover the GITHUB_TOKEN CI caveat, scheduled-workflow auto-disable, required repository settings, and bumping the pinned uv version with its checksum. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
master added 2026 on 2026-01-04, before solotime.info revised the 2026 index (page "Last update March 20, 2026"): CAM-C 0.827 -> 0.828, GS 0.793 -> 0.809, SS 0.837 -> 0.840, XU 0.869 -> 0.872. Conflicts in JSON/2026.json, YAML/2026.yaml, rtp.json and rtp.yaml are resolved by regenerating from the canonical CSV, which holds the current page's values and the AST/BST/DST/ EST/GST keys without "(STR)"-style suffixes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
master already carried 2026 data from January 4; this branch updates it to the March 20, 2026 revision of the source page, which changed four indices. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
master's 2026 files used the same suffixed keys, so consumers reading 2026 are affected by the rename too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem / background
This repository turns the hand-maintained PAX/RTP pages at solotime.info/pax into machine-readable files. A review against the live source found that the data and tooling had drifted:
XS/SSRwere removed,XU0.869 was added,EVXwent 0.830 → 0.834 andXA0.842 → 0.844. The repo never picked this up. The same thing happened to 2026:masteradded it on 2026-01-04, and the page was then revised on 2026-03-20 (CAM-C0.827 → 0.828,GS0.793 → 0.809,SS0.837 → 0.840,XU0.869 → 0.872). This branch mergesmasterand supersedes those values.ST (STS)(2009) andAST(STR)(2025) mark renames and redistributions. The scraper either dropped the annotation, which spliced unrelated classes into one series (STSbefore and after 2009 are different classes), or kept it in the key (AST(STR)). All errors were swallowed.rtp_files_generator.pymerged with anappendstrategy, so every re-run duplicated a year and a revised page could not replace one.XPin Xtreme Street andXSin Street, and left 31 classes blank.rtp_form_generator.pydid not run, and nothing was automated.What is changing
CSV/):rtp.csv: each index exactly as published, plus its verbatim label.sources.csv: URL, the page's "Last update" date, fetch time and SHA-256 for each year.classes.csv: SCCA name and category per year, with a citation andverified/unverifiedstatus.lineage.csv: renamed and derived classes.Scripts/rtp_model.pyparses CSVs into domain types (Parse, don't validate).JSON/<year>.jsonkeeps its shape.JSON/latest.json/YAML/latest.yaml.rtp.jsonv2 maps each class's years toIndex,Name,SoloCategory,ClassificationVerified, plusPredecessors/Successorsand per-year source metadata. JSON Schemas are inSchema/.ci.ymlruns the tests and checks that generated files match the CSV.update-rtp.ymlruns weekly and opens a PR on any source change. PRs that need a new class classified open as drafts labeledneeds-classification.pyproject.toml+ hash-lockeduv.lock(one-weekexclude-newer,no-build) replacerequirements.txt. Dependabot covers actions and uv.Why
AS–HSwere reused for the new Street category.STRwent toCST, while the ND MX-5 went toAST.Expected outcome
null.Breaking changes for consumers (see
CHANGELOG.md):rtp.json/rtp.yamlhave a new shape.AST(STR)etc. becomeASTetc.Actions / tests
uv run pytest: 183 tests covering:main()modes, including year rollover;uv sync --locked.security-auditor), repeated until nothing Medium or above remained. The resolutions include:Owner follow-ups after merge (repository settings):
masterand require theCI / testcheck, because bot PRs opened withGITHUB_TOKENdon't trigger CI on their own.workflow_dispatchto confirm the end-to-end flow.References
rtp<year>.html).robots.txtsetsCrawl-delay: 10.CSV/classes.csv.🤖 Generated with Claude Code