Releases: hneogy/gp-omm-conformance
Release list
v0.2.0 — writer-side case
What this release adds. The first writer-side case. v0.1.0 tested code that reads orbital data across the five-digit catalog-number boundary; v0.2.0 asks the same of code that writes TLEs, which every newly catalogued object now forces into the Alpha-5 form and which amateur tools generate for new launches. The sixteen cases of v0.1.0 and their expected values are unchanged.
What it covers. Case tle-writer-alpha5: 606 records already frozen in the corpus, 603 Alpha-5 ids (257 with letter A, 346 with letter T) and three five-digit ids (the first ISS record at a 1998 epoch, 69999 with a negative BSTAR, analyst 81011 with a blank designator), are handed to the writer under test, and the lines it returns are checked for the Alpha-5 catalog field on both lines, 69-character lines with valid checksums, and a round trip through the corpus's reference reader at each TLE field's resolution, by truncation or by rounding half up, since CelesTrak truncates the eccentricity and Space-Track rounds it; the convention observed is reported. Three further inputs carry numbers the TLE field cannot represent (340000, 799501621, -1: real elements, vector ids): the correct output for them is a refusal, and the runner reports that refusal as a pass. Fields an orbit-fitting tool regenerates by design (derivatives, element set, revolution, name) are reported for information, never failed. Writers plug in through a write_tle(record) adapter hook or --write-cmd; a file written by a tool that cannot be wrapped, such as strf's interactive rffit, is checked with python3 -m gpconf check-tle FILE [--against RECORDS].
Headline findings. A writer that formats the catalog number through an integer conversion (%05d) fails every Alpha-5 input: six digits, a 70-character line, a checksum over shifted columns, and no refusal above 339999. python-sgp4 2.27's export_tle writes Alpha-5 correctly and refuses 340000 and nine-digit numbers; its only failure is the synthetic -1 input, written as -0001. strf's rffit, exercised at function level in an isolated build (the binary needs PGPLOT, X11 and GSL and was not built), writes Alpha-5 correctly across the representable range; above 339999 its helper has no range check and the lines carry a blank catalog field, on a route only the interactive Satellite ID entry takes and that no real catalog number reaches today. No bug is claimed for the binary; a short hardening suggestion is drafted in docs/upstream/ and has not been sent. Across all seventeen cases the reference passes exactly, the deliberately typical parser fails 14, and python-sgp4 fails 7, one of them the writer case on that synthetic input alone.
Verification and audit. The reference writer is the renderer that reproduces 304 of 304 CelesTrak TLE lines byte for byte and round-trips 1,208 records; the writer case passes it exactly and runs offline, since its inputs are the corpus's own frozen records. The test suite (37 tests) passes in a fresh clone of this release. The independent audit in AUDIT.md covered v0.1.0; the writer-side case has not been separately audited. Every design choice is in the append-only DECISIONS.md (D-095 onward), and docs/WRITERS.md labels each claim about an external tool as tested or inferred and gives the reproduction recipe.
What is not included. As before, no raw CelesTrak data (tools/fetch.py rebuilds it locally under CelesTrak's usage policy) and no Space-Track data. Also no strf code (strf is GPL-3.0) and no output of any external tool: every fixture line in the writer case was rendered by the corpus itself from records whose provenance is in manifest.json.
How to run.
git clone https://github.com/hneogy/gp-omm-conformance.git && cd gp-omm-conformance
python3 tools/fetch.py
python3 -m gpconf run --adapter tests.adapters.reference:Parser # the control, 17 cases
python3 -m gpconf run --adapter tests.adapters.naive:Parser # the parser and writer most projects have
python3 -m gpconf check-tle output.tle --against records.csv # a TLE file your own tool wroteThen add a write_tle hook to your adapter (see README, "Writing an adapter"). Standard library only, Python 3.9+.
MIT licence, copyright NEOGY LLC. Cite via CITATION.cff; the Zenodo version DOI for this release is added there once minted. Full change list in CHANGELOG.md.
v0.1.0 — initial release
What this is. A conformance corpus for orbital-data parsers crossing the five-digit catalog-number boundary: Alpha-5 TLEs, six- and nine-digit NORAD_CAT_IDs, and the CCSDS Orbit Mean-Elements Message (OMM) in CSV, JSON, XML and KVN as served by CelesTrak. Point the runner at your parser and it reports, case by case, what breaks and why, with every expected value traceable to a provider response whose URL, retrieval time and SHA-256 are recorded.
What it covers. Sixteen cases: the first six-digit object (100000), a group that is entirely six-digit, analyst objects with empty OBJECT_ID and the literal name UNKNOWN, nine-digit launch-nominal ids in supplemental data, CelesTrak supplemental records (classification C, extra columns), drag-term encodings, the legacy SATCAT cutoff at 69999, omitted constant metadata in CSV/JSON, the mean-motion-derivative convention, TLE-versus-OMM precision loss, OMM XML schema validity, Alpha-5 encoding vectors, 604 derived Alpha-5 lines (letters A and T), and six CCSDS-legal KVN variants.
Headline findings. CelesTrak's last-30-days TLE request returns HTTP 404 because every recent object is six-digit. python-sgp4 2.27 and Skyfield 1.55 cannot load live nine-digit records from OMM data. Space-Track and CelesTrak render the same element set into different TLE bytes: the sign written for a zero second derivative, and eccentricity rounding versus truncation, confirmed on 21 records. A deliberately typical parser fails 13 of the 16 cases.
Verification and audit. Expected values were produced by reference readers written from the format documents and cross-checked record by record against python-sgp4 and Skyfield; the renderer behind the derived lines reproduces 304 of 304 CelesTrak TLE lines byte for byte; a TLE→OMM→TLE round-trip test covers 1,208 records. The corpus was built with AI assistance under human direction with an append-only decision log (DECISIONS.md), and independently audited before release by a separate AI session with no access to the building context; the audit found no wrong expected value, and every finding and its resolution is in AUDIT.md.
What is not included. No raw CelesTrak data is redistributed: tools/fetch.py rebuilds it locally under CelesTrak's usage policy (each URL once, cached, never looped) and SHA-256 hashes tell the runner whether you hold the exact bytes that were tested. No Space-Track data; anyone with their own account can run tools/verify_against_spacetrack.py.
How to run.
git clone https://github.com/hneogy/gp-omm-conformance.git && cd gp-omm-conformance
python3 tools/fetch.py
python3 -m gpconf run --adapter tests.adapters.reference:Parser # the control
python3 -m gpconf run --adapter tests.adapters.naive:Parser # the parser most projects haveThen write an adapter for your own parser (see README, "Writing an adapter"). Standard library only, Python 3.9+.
MIT licence, copyright NEOGY LLC. Cite via CITATION.cff; a Zenodo DOI is minted for this release.