M3/E5/#17 — SoLEXS parsers - #20
Merged
Merged
Conversation
Canonical: Milestone M3 · Epic E5 · Issue #17. Deps: #12, #15 (both complete). Eligibility recomputed by parsing origin/main:docs/tis/TIS-v1.0.md §15 — complete {1..16}, eligible {#17, #22, #23, #25, #26, #27, #39}; lowest Order selects #17. Three parsers, one per SoLEXS product, each implementing its section of SPEC-parsers@r6. That document is a CONTRACT: "a deviation requires a logged amendment, not a code change." lc §2.1 total-band counts per second. NaN is data, not an error. pi §2.2 340-channel PI spectra per second. Ordinal channels; keV is prohibited. gti §2.3 inclusive second-marks; Σ(STOP−START+1) == EXPOSURE, exactly. NO DEFAULT ON A MISSING KEY — THE RULE THE WHOLE SPEC OPENS WITH §5: "No default-on-missing-key (header.get(K, default) is banned for any physically meaningful key — that idiom is the direct cause of v1's thirty-sprint failure)." The concrete failure was F-05: v1 defaulted MJDREF to 58484 where the archive declares 40587, a ~49-YEAR timestamp error nothing detected. So `_fits.py` has no `get`. Every lookup raises. Five tests delete a keyword and require the parse to abort. NaN IS DATA. ZERO IS A MEASUREMENT. THEY NEVER MEET. §2.1 r2, binding: SoLEXS COUNTS uses NaN as the missing-data sentinel; NaN values pass through unchanged, are never imputed, never converted to zero, never removed; zero remains a valid physical count. Mapped onto the domain exactly: NaN -> None (observed to be absent, ADR-0017/L-07), 0.0 -> 0.0. The property is quantified over every position and both directions, because collapsing the two is the one error that would be undetectable in every downstream artifact. No interpolate/smooth/fill/impute/resample/repair function exists in any of the three modules, and a test asserts none appears. F-19 is checked AFTER the NaN branch, which is what makes §2.1's note true that the rule is "inherently NaN-safe (NaN < 0 is False)". THE keV PROHIBITION, ENFORCED BY ABSENCE §2.2: no RMF/ARF exists anywhere in the archive, so PI-channel -> keV is impossible from archive contents alone, and "no v2 artifact may state a SoLEXS energy in keV until a response file is acquired". There is no keV field, no conversion, no calibration constant — a test scans the module and its three classes for any of them. A comment is not a constraint; an absent field is. EXACT MEANS EXACT F-09 requires Σ(STOP−START+1) == EXPOSURE with tolerance 0 s. §5 says why: "the relation is definitional, and a tolerance would re-admit the ambiguity that produced CONTRADICTION-001". A one-second discrepancy — precisely what the superseded exclusive reading produces — aborts. The convention is verified for 2024-05-14 SDD2 only (§8 A-8) and is NOT widened here; §2.3 requires any deviation to terminate validation. VERIFIED AGAINST THE REAL ARCHIVE — EVERY OBSERVED VALUE REPRODUCED Re-measured from the 2024-05-14 SDD2 products, the X8.7 flare day: 86,400 rows §2.1 NAXIS2 5 NaN at offsets [0, 5, 30072, 30078, 83951] §2.1 OBSERVED, exactly 86,395 finite §2.1 == EXPOSURE 5 GTI intervals, Σ(STOP−START+1) = 86395.0 §2.3, zero error GTI-excluded set == NaN set §2.1 OBSERVED, this day SDD1 GTI NAXIS2 = 0 -> detector_active=False F-12, the one non-fatal rule TSTART 1715644800.0 = 2024-05-14T00:00:00Z §2.1 epoch anchor DETCHANS 340, CHANTYPE PI, channel map 0..339 §2.2 .pi TSTART[0] == .lc TSTART V-PI-3 / F-06 These are the specification's own OBSERVED claims, independently reproduced by this code. A drift in either the parser or the archive is now a red test rather than a quiet disagreement between a document and reality. astropy GRANTED TO INGEST — THE LINE #13 PREDICTED Reading FITS needs a FITS reader. M2/E4/#13 declined to pre-grant third-party roots and said why: "a context that later needs `astropy` should add one reviewable line rather than inherit a blanket permission nobody voted for (STD-11)." Three existing tests pinned `contexts.ingest.allow == {contracts, domain, kernel}` and went red — the mechanism working. They are updated to be STRICTER, not looser: internal grants must still equal ADR-0026's exactly, and a new test enumerates every third-party grant and refuses any that names a governed root of this repository. SCOPE .hk (§2.4, v1.1 only, 5 of 436 days) is NOT implemented: TIS E5 §5 lists this epic's SoLEXS modules as parsers/solexs/{lc,pi,gti} and assigns no .hk module to any issue. Reported as an Engineering Plan Defect rather than filled by guessing at scope. No aggregation to the 1-minute grid — §3's T1/T2 contract is the write path's (#19). No `NaN => GTI-excluded` evaluation — §2.1 places it at the day-assembly layer explicitly, "not inside the single-file .lc parser". No HEL1OS, no curation, no registry. VERIFICATION unit (kernel + domain + contexts) 470 passed (+65) tests/architecture 563 passed (+1) tests/integration 128 passed (+14) research/tests/v2 188 passed links / imports / contracts gates clean imports gate: 46 modules, 211 imports, 9 policies Eight real-corpus tests run where the archive is present and skip where it is not (STD-12, E5 §17). The guard tests for .gz PRODUCTS, never a directory: five v1.1 archive directories exist in a clean checkout because their quicklook PNGs are tracked. CI: numpy + astropy added to the unit and integration jobs. No new job, no new context; still eight. Co-Authored-By: Claude Opus 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.
Canonical identifier: Milestone M3 · Epic E5 · Issue #17 — SoLEXS parsers
Dependencies: #12 ✔, #15 ✔
Selection: eligibility from
origin/main:docs/tis/TIS-v1.0.md§15 — complete{1…16}, eligible{#17, #22, #23, #25, #26, #27, #39}; lowest Order selects #17.Three parsers, one per SoLEXS product, each implementing its section of
SPEC-parsers@r6— a document that is a contract: "a deviation requires a logged amendment, not a code change."No default on a missing key — the rule the spec opens with
§5: "No default-on-missing-key (
header.get(K, default)is banned for any physically meaningful key — that idiom is the direct cause of v1's thirty-sprint failure)."The concrete failure was F-05: v1 defaulted
MJDREFto 58484 where the archive declares 40587 — a ~49-year timestamp error that nothing detected. So_fits.pyhas noget. Every lookup raises. Five tests delete a keyword and require the parse to abort.NaN is data. Zero is a measurement. They never meet.
§2.1 as amended at r2, binding: NaN is the missing-data sentinel; NaN values pass through unchanged, are never imputed, never converted to zero, never removed; zero remains a valid physical count.
Mapped onto the domain exactly:
NaN → None(observed to be absent, ADR-0017/L-07),0.0 → 0.0. The property is quantified over every position and in both directions, because collapsing the two is the one error that would be undetectable in every downstream artifact. Nointerpolate/smooth/fill/impute/resample/repairexists in any of the three modules, and a test asserts none appears.F-19 is checked after the NaN branch, which is what makes §2.1's note true that the rule is "inherently NaN-safe (
NaN < 0isFalse)".The keV prohibition, enforced by absence
§2.2: no RMF/ARF exists anywhere in the archive, so PI-channel → keV is impossible from archive contents alone, and "no v2 artifact may state a SoLEXS energy in keV until a response file is acquired."
There is no keV field, no conversion function and no calibration constant — a test scans the module and its three classes for any of them. A comment is not a constraint; an absent field is.
Exact means exact
F-09 requires
Σ(STOP−START+1) == EXPOSUREwith tolerance 0 s. §5 says why: "the relation is definitional, and a tolerance would re-admit the ambiguity that produced CONTRADICTION-001." A one-second discrepancy — precisely what the superseded exclusive reading produces — aborts. The convention is verified for 2024-05-14 SDD2 only (§8 A-8) and is not widened here.Verified against the real archive — every
OBSERVEDvalue reproducedRe-measured from the 2024-05-14 SDD2 products, the X8.7 flare day:
NAXIS2[0, 5, 30072, 30078, 83951]OBSERVED, exactly== EXPOSUREΣ(STOP−START+1) = 86395.0==NaN setOBSERVED, this dayNAXIS2 = 0→detector_active=FalseTSTART 1715644800.0=2024-05-14T00:00:00ZDETCHANS 340,CHANTYPE PI, map0..339.pi TSTART[0] == .lc TSTARTThese are the specification's own
OBSERVEDclaims, independently reproduced by this code. A drift in either the parser or the archive is now a red test rather than a quiet disagreement between a document and reality.astropygranted to Ingest — the line #13 predictedReading FITS needs a FITS reader. M2/E4/#13 declined to pre-grant third-party roots and said why: "a context that later needs
astropyshould add one reviewable line rather than inherit a blanket permission nobody voted for (STD-11)."Three existing tests pinned
contexts.ingest.allow == {contracts, domain, kernel}and went red — the mechanism working. They are updated to be stricter, not looser: internal grants must still equal ADR-0026's exactly, and a new test enumerates every third-party grant and refuses any that names a governed root of this repository.Scope
.hk(§2.4, v1.1 only, 5 of 436 days) is not implemented: TIS E5 §5 lists this epic's SoLEXS modules asparsers/solexs/{lc,pi,gti}and assigns no.hkmodule to any issue. Reported as an Engineering Plan Defect rather than filled by guessing at scope.No aggregation to the 1-minute grid — §3's T1/T2 contract is the write path's (#19). No
NaN ⇒ GTI-excludedevaluation — §2.1 places it at the day-assembly layer explicitly, "not inside the single-file.lcparser." No HEL1OS, no curation, no registry.Verification
CI impact
numpy+astropyadded to theunitandintegrationjobs — without them the parser suites would error at import rather than run. No new job, no new required context; still eight.🤖 Generated with Claude Code