tester: harden _entry_from_dict against NaN/+Inf fitness (PKT-980) - #623
Open
bugsyhewitt wants to merge 1 commit into
Open
bugsyhewitt wants to merge 1 commit into
bugsyhewitt wants to merge 1 commit into
Conversation
PKT-980 closes the unfixed LOAD-boundary seam between PKT-618 (callback
injection defense at generation.py:_make_entry L54) and PKT-690 (sync/pull.ts
network-write guard). Without this guard a poisoned entries/*.json file with
NaN/+Inf/-Inf/null/non-numeric/out-of-range fitness silently poisons the
entire Population for that martian_type — compute_from_entries() then crashes
on statistics.stdev() with 'inf or nan encountered in data' (Python 3.14
statistics module raises ValueError on NaN inputs).
Fix:
src/alienclaw/evolution/storage.py:_entry_from_dict
+ import math
+ isfinite-and-in-range guard mirroring population.py:125-126
+ non-numeric / None rejection (covers JSON.stringify NaN→null sentinel
that float() would otherwise raise mid-loop with TypeError)
Tests:
test/evolution/test_storage.py:TestEntryFromDictFitnessValidation
+ 19 new tests covering NaN/+Inf/-Inf/null/str/out-of-range rejection,
canonical-fitness acceptance, error-message diagnostics, and end-to-end
poisoned-JSON-on-disk propagation via read_all_entries().
Ship-gate (observed 2026-10-02T15:02:00Z on branch
tester/pkt-980-storage-fitness-finite-guard):
vitest: 3410 passed | 46 skipped (3456) — 20.67s
pytest: 1865 passed | 125 skipped (+19 from PKT-980; was 1846) — 413.06s
check-testvectors: OK — no drift detected
check-seed-drift: OK — 16/16 seeds reproduce byte-for-byte
Zero regressions. PKT-618 callback guard, PKT-690 network guard, and the
PKT-935 atomicWrite fence all remain intact (no overlap).
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.
What
Closes the unfixed LOAD-boundary seam between PKT-618 (callback injection defense at
L54) and PKT-690 ( network-write guard).
Without this guard, a poisoned file (NaN/+Inf/-Inf/null/non-numeric/out-of-range
fitness) silently poisons the entire for that martian_type —
then crashes on with
inf or nan encountered in data(Python 3.14 statistics module raises ValueError on NaN inputs).Why
Reproduced live on origin/main (cycle 587):
json.loads('{"fitness": NaN}')→{'fitness': nan}(Python json extension)float(NaN)→ no error,nanpropagates into PopulationEntry.fitnessstatistics.stdev([0.5, nan, 0.9])→ValueError: inf or nan encountered in dataevaluate_and_evolve()mid-loop, terminating the entire evolutionpipeline for the affected martian_type.
The fix
src/alienclaw/evolution/storage.py:_entry_from_dict+import math+isfinite-and-in-range guardmirroringpopulation.py:125-126+non-numeric / None rejection(covers the JSON.stringify NaN→null sentinelthat float() would otherwise raise mid-loop with TypeError —
pull.tsL127comment explicitly notes this edge)
Tests
test/evolution/test_storage.py:TestEntryFromDictFitnessValidation:canonical-fitness acceptance [0.0, 0.0001, 0.5, 0.9999, 1.0],
error-message diagnostics (entry_id + actual value present),
and end-to-end poisoned-JSON-on-disk propagation via
read_all_entries().Ship-gate (observed 2026-10-02T15:02:00Z on branch)
Total: 5275 tests PASS, 0 FAIL.
Behavior matrix
0.0 <= fit <= 1.0finiteNaN+Infinity-Infinity-0.0001/2.0/-1.0/10.0null"0.5"(string)Diff size
+23 source / +111 tests, 1 substitution (float() → validated). ~134 LOC total.
Cycle context
Cycle 587 (2026-10-02T14:57:07Z). Origin/main HEAD was 57c2138 (PR #622
PKT-981 merged since cycle 586). Branch
tester/pkt-980-storage-fitness-finite-guard,commit
ec59488c, NEVER merged (CI + Bugsy gate the merge per tester-prompt).