prompt: complete covariance-interpolator-rng-seed (PyAutoFit#1451 merged) - #128
Merged
Merged
Conversation
…ged) Advances the task to complete/2026/08/ and removes it from active.md. PyAutoFit#1451 merged as 282d8e1e, auto-closing issue #1450; the Class B release blocker that killed 2026.8.2.1 is cleared, green on 3.12 and 3.13. The record leads with the finding rather than the fix: the prompt's premise was wrong. The unseeded np.random.random() it blamed is a minor contributor - seeding only it leaves std at 1.95 of 2.05 and the test still fails. The dominant source is dynesty's rstate (Generator(PCG64(None)), OS entropy, reachable from neither np.random nor a local Generator), with the stdlib random module used by initializer.py third. Measured pre-fix failure rate 1.65% (33/2000, 95% CI 1.18-2.31%). Also recorded: the tolerance is NOT mis-calibrated (a full search recovers 25.0496 +/- 0.0039, 500x tighter) so abs=5.0 must not be loosened; the sibling test_single_variable was flaking worse at 3.6% with no random call of its own; and the LinAlgError guards are a separate defect (rank-deficient fixture matrix, deterministic input) rather than the same nondeterminism. The known limitation is recorded so nobody later reads "seeded" as "the assertion is now meaningful" - under maxcall=1 both are frozen-RNG regression checks. The real fix stays open as draft/feature/autofit/search_seed_reproducibility.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016vdGab4C5rWumTCXkWHPyh
…erpolator-rng-seed-8zexp3 # Conflicts: # complete/index.md
Jammy2211
pushed a commit
that referenced
this pull request
Aug 16, 2026
…mentation The clip-count work is written and tested against PyAutoFit 1f4b66a, but push access to PyAutoFit was denied in this session, so it lands as a patch rather than a PR. Prompt updated to say so and to carry the verification evidence. Corrects a wrong premise in the prompt as first filed. It claimed search.summary had "no search-specific channel at all". That is false: search_summary_from_samples (text_util.py:115-161) already reads samples.samples_info and already emits Resurrections, Value-NaN Lane-Steps, Gradient-NaN Lane-Steps and both rates, key-guarded so other searches are unaffected. I had read search_summary_to_file and not the function it calls. Left uncorrected it would have sent an implementer off to build a routing mechanism that already exists. The real gap is narrow: n_clipped_lane_steps never reaches samples_info, and n_constrained_lane_steps reaches it but is never emitted — so PyAutoFit#1475's trapped-lane counter has been invisible in search.summary since it shipped. As built (tmp/clipper-search-summary.patch, gitignored, 4 files +243/-0): multistart publishes clipper name + n_clipped_lane_steps into samples_info; bfgs publishes the clipper name and deliberately no count, since it is declarative and scipy enforces, so a 0 would read as "never fired" when it means "cannot know"; text_util grows _clipper_summary_from handling the three cases plus the owed Constrained Lane-Steps line; 6 new tests. Verified on 3.13: non_linear + text = 501 passed, 3 skipped, 1 failed, the failure (nautilus single-core pool) reproduced identically on a stashed clean tree, as was the astropy collection error — both already recorded under complete/2026/08/frozen-lane-counter.md. Also verified end-to-end against the search.summary files four real searches actually wrote, giving Clipped Lane-Steps = 414 at rate 0.958 on the clipped multistart arm. Incidental, worth keeping: on that toy 3-parameter Gaussian the unclipped arm showed Value-NaN Lane-Steps = 378 (94.5%) and the clipped arm 0 — the #128 mechanism reproducing on a model with nothing astrophysical in it, which makes a far cheaper regression fixture than the imaging/mge cell. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FzF2XmKQaqZRWZfZMxvTNR
Jammy2211
added a commit
that referenced
this pull request
Aug 16, 2026
… what was owed (#190) * prompt: file the three follow-ups the lane-death investigation left owed Closes out the Clipper handover. Three findings from autolens_profiling#128 were living only inside other prompt files, where nothing indexes them and nobody can pick them up. All three are now filed prompts. Two incidental PyAutoFit bugs, split out of prior_support_clipper.md's "do not lose these" section, which asked for them to be filed separately once confirmed. Both confirmed against PyAutoFit main 1f4b66a93: - save_json_numpy_scalar_typeerror.md — paths/directory.py:80 is a bare json.dump with no default= hook, and there is no JSON encoder anywhere in autofit/. numpy float32 raises TypeError at the END of a successful run. It did not fire while 14/16 lanes were dead, so it fires exactly when lane survival improves — any fix to the prior-support problem will surface it. - crashed_run_poisons_resume.md — the chain, each link read on main: directory.py:79 opens "w+" (truncates, no atomic rename), so the crash above leaves a partial file; is_complete (directory.py:180) tests only the .completed marker, so abstract_search.py:582 dispatches to resume; the resume reads the truncated JSON; and JSONDecodeError subclasses ValueError, so the guard at multi_start_gradient/search.py:720 catching (FileNotFoundError, TypeError, KeyError) does not fall through to the fresh-start branch. Result is a zero-step no-op reported as a clean run — the phase-2 campaign currently documents this as a trap to work around. One research task, follow-up (2) owed by active/mge_lane_death.md: - ell_comps_trapping_unmasked.md — the plateau was masked, not cleared. The baseline n_constrained_lane_steps = 0 meant "nothing got that far"; lanes died of prior-exit first. Records that the 27.79% came from the prior-neutered diagnostic arm and is NOT a citable production number, so the task sequences after phase 1 and measures the clipped run instead. active.md now points at all five filed prompts (these three plus the two Clipper phases) so the thread is followable from the ledger. dashboard.md regenerated; lifecycle check OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FzF2XmKQaqZRWZfZMxvTNR * prompt: retire the shipped Clipper phase 1, file the clip-count reporting gap Phase 1 has landed. PyAutoFit#1477 merged as 1f4b66a — the current tip of PyAutoFit main — shipping AbstractClipper / ClipperNone / ClipperPriorBox in autofit/non_linear/clipper.py, wired into both AbstractMultiStartGradient and AbstractBFGS, opt-in, default ClipperNone, bit-identical under it, 22 tests. The Mind had not noticed: prior_support_clipper.md was still sitting in draft/ as a high-priority backlog item on a dashboard people pick work from. Retired to complete/2026/08/prior-support-clipper.md via lifecycle.py record, with the original prompt folded in and the findings worth keeping written up (the inset keyed on bound kind rather than unguarded upper-lower; the LogGaussianPrior support mismatch; scipy reading a bounds tuple as (min, max) pairs and silently mis-fitting two-parameter models). Clip-count reporting, filed as clipper_usage_in_search_summary.md. The counting half already exists — n_clipped_lane_steps is accumulated per-lane (not per-coordinate) at multi_start_gradient/search.py:863, written to search_internal and restored on resume as a lifetime total. The storing half does not, and the gap is not where it looks: - search.summary is written by text_util.search_summary_to_file, which only ever sees samples and timings. There is no search-specific channel at all, for any counter — save_summary never sees search_internal. Routing is the work, not the arithmetic, which is why the prompt asks for a general hook serving the other multi-start counters rather than one threaded parameter. - LBFGS produces no count whatsoever. It hands optimize.Bounds to scipy and never calls project, so there is no mask to count. Emitting 0 there would read as "never fired" when it means "cannot know". Phase 2 (clipper_validation_campaign.md) marked UNBLOCKED with what phase 1 changed for it: record n_clipped_lane_steps as a fourth counter from search_internal; a ClipperPriorBox arm reporting zero clips has not exercised the clipper and its "no change" result is meaningless; the momentum-reset arm needs writing since nothing yet consumes the mask; and the float32 save_json crash was NOT fixed by phase 1 (verified at 1f4b66a), so that trap stands and will start firing precisely because clipping keeps lanes alive. Repointed all seven references to the moved prompt. lifecycle check + index check OK; dashboard regenerated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FzF2XmKQaqZRWZfZMxvTNR * prompt: correct the search.summary premise, record the verified implementation The clip-count work is written and tested against PyAutoFit 1f4b66a, but push access to PyAutoFit was denied in this session, so it lands as a patch rather than a PR. Prompt updated to say so and to carry the verification evidence. Corrects a wrong premise in the prompt as first filed. It claimed search.summary had "no search-specific channel at all". That is false: search_summary_from_samples (text_util.py:115-161) already reads samples.samples_info and already emits Resurrections, Value-NaN Lane-Steps, Gradient-NaN Lane-Steps and both rates, key-guarded so other searches are unaffected. I had read search_summary_to_file and not the function it calls. Left uncorrected it would have sent an implementer off to build a routing mechanism that already exists. The real gap is narrow: n_clipped_lane_steps never reaches samples_info, and n_constrained_lane_steps reaches it but is never emitted — so PyAutoFit#1475's trapped-lane counter has been invisible in search.summary since it shipped. As built (tmp/clipper-search-summary.patch, gitignored, 4 files +243/-0): multistart publishes clipper name + n_clipped_lane_steps into samples_info; bfgs publishes the clipper name and deliberately no count, since it is declarative and scipy enforces, so a 0 would read as "never fired" when it means "cannot know"; text_util grows _clipper_summary_from handling the three cases plus the owed Constrained Lane-Steps line; 6 new tests. Verified on 3.13: non_linear + text = 501 passed, 3 skipped, 1 failed, the failure (nautilus single-core pool) reproduced identically on a stashed clean tree, as was the astropy collection error — both already recorded under complete/2026/08/frozen-lane-counter.md. Also verified end-to-end against the search.summary files four real searches actually wrote, giving Clipped Lane-Steps = 414 at rate 0.958 on the clipped multistart arm. Incidental, worth keeping: on that toy 3-parameter Gaussian the unclipped arm showed Value-NaN Lane-Steps = 378 (94.5%) and the clipped arm 0 — the #128 mechanism reproducing on a model with nothing astrophysical in it, which makes a far cheaper regression fixture than the imaging/mge cell. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FzF2XmKQaqZRWZfZMxvTNR * prompt: the search.summary clip-count work is in flight as PyAutoFit#1478 Advance to complete/ on merge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FzF2XmKQaqZRWZfZMxvTNR * prompt: both incidental PyAutoFit bugs are in flight (#1479, #1480) save_json_numpy_scalar_typeerror -> PyAutoFit#1479. Reproduced against the unfixed tree before fixing. Fixed with a NumpyEncoder wired into BOTH output writers -- save_json and, which this prompt did not name, Samples.info_to_json. That second site is the more dangerous: samples_info is a search's own diagnostic channel, so every counter added to it could reintroduce the crash. crashed_run_poisons_resume -> PyAutoFit#1480, and carries a CORRECTION. The prompt claimed the poisoned rerun is "a 4-second no-op that reads as a clean result". That did not reproduce. What reproduces is a hard JSONDecodeError on every rerun of the same search name, naming no file and offering no remedy. The no-op variant presumably needs a surviving search_internal whose restored total_steps short-circuits the loop; the crash path deletes it first. Same root cause, fix covers both, but only the crash is evidenced -- recorded so the unobserved symptom is not cited as fact. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FzF2XmKQaqZRWZfZMxvTNR --------- Co-authored-by: Claude <noreply@anthropic.com>
Jammy2211
added a commit
that referenced
this pull request
Aug 16, 2026
The cloud session did everything this campaign needs except run it. Adds a SESSION HANDOVER block to the campaign prompt itself rather than a separate handover doc, so the context travels with the file a GPU session will actually open -- the same property #188 was merged to preserve. What it carries: - The three PyAutoFit changes that landed AFTER phase 1 (#1478 clip count in search.summary, #1479 NumpyEncoder, #1480 atomic writes), and the fact that all four are UNRELEASED. The task must run against a checkout at or after b6e89cd with autofit.__file__ verified, never a PyPI wheel. - Which of this prompt's traps are now fixed rather than live -- and why the mitigations stay anyway: the step-count assertion catches every no-op cause, not only the float32 one. - That the clip count is now a VALIDITY CHECK, not a statistic. A ClipperPriorBox arm reporting zero clips has not exercised the clipper and its "no change" result is meaningless -- a broken arm, not a null result. - A seconds-long smoke test discovered while verifying #1478: the #128 mechanism reproduces on a toy 3-parameter Gaussian (378 value-NaN lane-steps unclipped, 0 clipped, 414 clips at rate 0.958). Cheap way to confirm the clipper is wired up and firing before spending GPU time on imaging/mge. - The mge-lane-death GPU/float64/multi-seed confirmation and the owed hazard-index entry, which want the same session and share these arms. - Sequencing: this campaign, then ell_comps_trapping_unmasked.md on the same arms, which must not re-derive 27.79% from the prior-neutered arm. Claude-Session: https://claude.ai/code/session_01FzF2XmKQaqZRWZfZMxvTNR Co-authored-by: Claude <noreply@anthropic.com>
Jammy2211
added a commit
that referenced
this pull request
Aug 16, 2026
All three merged today, so they leave draft/. Left in place they would read as unstarted high-priority backlog on the dashboard people pick work from -- the exact drift this session opened by finding phase 1 still sitting there after it had shipped. - clipper-usage-in-search-summary PyAutoFit#1478 bbceff6 - save-json-numpy-scalar-typeerror PyAutoFit#1479 b6e89cd - crashed-run-poisons-resume PyAutoFit#1480 5c9244b Each record carries what implementing it taught, including two corrections to what the prompts asserted: - The search.summary prompt claimed there was "no search-specific channel at all". False. search_summary_from_samples already read samples_info and already emitted the NaN counters; the real gap was two omissions, not a missing mechanism. Recorded because it nearly caused a rebuild of something that existed. - The poisoned-resume prompt claimed the rerun was "a zero-step no-op that reads as a clean result". That did not reproduce; a hard JSONDecodeError on every rerun did. The no-op variant presumably needs a surviving search_internal, which the crash path deletes first. Only the crash is evidenced, and the record says so. Also kept: the second unguarded JSON writer the float32 prompt never named (Samples.info_to_json, the more dangerous one, since samples_info gains a counter every time a search does); the resume-guard leg found by audit rather than by the prompt; the test trap where a run short-circuited as already-complete passes an end-to-end resume test while asserting nothing; and the toy 3-parameter Gaussian that reproduces the #128 mechanism in seconds, which is a far cheaper regression fixture than the imaging/mge cell. active.md updated to shipped state with both corrections. Four dangling references repointed at the new records. lifecycle check + index check OK; dashboard regenerated (141 -> 138 drafts). Claude-Session: https://claude.ai/code/session_01FzF2XmKQaqZRWZfZMxvTNR Co-authored-by: Claude <noreply@anthropic.com>
Jammy2211
pushed a commit
that referenced
this pull request
Aug 16, 2026
…tart_workspace Phase 2 of the prior-support work. Absorbs the GPU/float64/multi-seed confirmation and the hazard-index entry owed from mge-lane-death (#128), which share this campaign's arms. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VRG2X7Af8zdF3vnsWoiK4U
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.
Closes out the task now that PyAutoLabs/PyAutoFit#1451 is merged (
282d8e1e,auto-closing PyAutoLabs/PyAutoFit#1450). The Class B release blocker that killed
the 2026.8.2.1 live release is cleared, green on Python 3.12 and 3.13.
Branch restarted from
main— the previous PR (#127) is merged, so this is freshwork rather than commits stacked on merged history. The force-with-lease that
repointed the branch discarded only
e3419110, the commit squash-merged asacc4a7dd; verified the tree diff againstmainfor every touched path is emptybefore pushing.
What changed
All four edits produced by
scripts/lifecycle.py record ... --apply— the shipskills' own primitive, not hand-editing:
complete/2026/08/covariance-interpolator-rng-seed.md— new rich completionrecord, with the original prompt folded in under
## Original prompt.active/covariance_interpolator_test_unseeded_rng.md— removed (folded intothe record).
active.md—covariance-interpolator-rng-seedsection removed.complete/index.md— regenerated (890 records).lifecycle.py check→ OK ·lifecycle.py index --check→ OK.Why the record leads with the finding, not the fix
The prompt's premise was wrong, and that is the part worth surviving:
np.random.random()in the test body and called seeding"a one-liner". Seeding only that leaves std at 1.95 of 2.05 — the test still
fails. The dominant source is dynesty's
rstate(
Generator(PCG64(None)), OS entropy, reachable from neithernp.randomnor alocal
Generator), with the stdlibrandommodule used byinitializer.pythird. All three must be seeded.
before any change, as the prompt's step 2 required.
25.0496 ± 0.0039 — 500× tighter — so
abs=5.0is correct and must not beloosened.
limit_maxcallis what turns the assertion into a coin flip.test_single_variablehas no random call of its ownyet was flaking at 3.6%, more than double the test that got blamed.
LinAlgErrorguards are a separate defect — rank-deficient fixturematrix (rank 6 of 9, cond 1.3e17), deterministic input — not the same
nondeterminism in disguise.
The record also carries the known limitation, so nobody later reads "seeded" as
"the assertion is now meaningful": under
maxcall=1both are frozen-RNGregression checks, with the measured cost of restoring real convergence.
It also notes this closes the "gate said GREEN, then the live release
contradicted it" question in
draft/triage/nightly_release_blocked_eight_nights.md— the gate's evidence was not stale; the release run drew a different random
sample. That removes the motive for a gate-vs-release redesign this evidence was
about to justify.
Still open
draft/feature/autofit/search_seed_reproducibility.mdstays indraft/— thereal fix. PyAutoFit has no supported way to seed a search, which is why the
merged change must monkeypatch a third-party module from a test, and why users
cannot reproduce a fit.
🤖 Generated with Claude Code
https://claude.ai/code/session_016vdGab4C5rWumTCXkWHPyh
Generated by Claude Code