Skip to content

prompt: confirm root cause of the numba psf_weighted_data garbage, file the kernel-shift split-out - #257

Merged
Jammy2211 merged 4 commits into
mainfrom
claude/autoarray-numba-psf-garbage-hfxnjv
Aug 21, 2026
Merged

prompt: confirm root cause of the numba psf_weighted_data garbage, file the kernel-shift split-out#257
Jammy2211 merged 4 commits into
mainfrom
claude/autoarray-numba-psf-garbage-hfxnjv

Conversation

@Jammy2211

@Jammy2211 Jammy2211 commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Mind-side record for the numba sparse-operator likelihood bug fixed in PyAutoArray#456 (merged).

What changed

draft/bug/autoarray/numba_first_call_garbage_psf_weighted_data.md — records the confirmed root cause, which is not the numba codegen/caching issue the prompt led with.

psf_weighted_data_from gathered the weight map with no bounds check, and numba @jit() does not bounds-check array reads. Any unmasked pixel within kernel_shape // 2 of the array edge read uninitialized heap memory instead of raising IndexError. Proven by compiling the shipped source unchanged under boundscheck=True.

That resolves the puzzle the prompt flagged — the inputs really were identical between call 1 and call 2; the function reads memory outside its inputs.

Symptom 1 reproduced on the euclid dataset

Calling psf_weighted_data_from on the real profiling dataset (autolens_profiling, dataset/imaging/euclid, mask radius 3.5", PSF 21x21):

max abs(psf_weighted_data) sum
pre-fix (1c33850) 4.901e300 1.333e301
post-fix 298.312 559433.417

The bug report's own numbers were "max abs = 4.8e299 on fit #1, 2.98e02 on fit #2". The post-fix value 298.31 = 2.98e02 matches the report's correct value exactly, and the pre-fix value reproduces the uninitialized-memory scale. 1244 of the 3841 unmasked pixels (32%) gather off the array.

The record also notes that the mask padding does not protect this path: apply_mask leaves data.native and data.mask at (71, 71), and only derive_mask.blurring_from(allow_padding=True) pads (to (89, 89)) for the dense convolver. The sparse numba path reads the unpadded array, so the mask sits flush against the array edge.

The named acceptance probe turns out to be a weak detector

parallel_scaling/pixelization_numba.py was run at P=2, 24 evals, 2 map repeats, cold NUMBA_CACHE_DIR, both pre-fix and post-fix. Both runs reported corrupt_evals_first_map = 0 and corrupt_evals_steady_maps = [0, 0]. That is not evidence of no bug — the values an out-of-bounds read returns are whatever the allocator left next to the weight map, and in that process they were benign. The pre-fix warm-up likelihood still drifted from the post-fix one in the 6th decimal (5860.175003698866 vs 5860.175922117387).

The record therefore recommends the deterministic max abs(psf_weighted_data) comparison as the regression probe instead of those counters, which can read zero on a run where the bug is fully present. Correction also posted on PyAutoArray#456.

Other findings recorded

The prompt's second suspect (an inf from finite image / zero noise passing the isnan guard) is recorded as unreachable.native zeroes both data and noise outside the mask, giving 0/0 = NaN every time. The isnan guard was left alone rather than widened to isfinite, which would have silently swallowed a genuine bad-noise-map error.

draft/bug/autoarray/numba_kernel_shift_axes_swapped.md (new) — a separate defect found while fixing the first. Both numba PSF gathers derive their kernel half-widths from the transposed kernel axes (kernel_shift_y from shape[1]). Harmless for square kernels; kernels are validated as odd, not square, so a 3x5 PSF mis-centres the gather.

Filed rather than fixed inline, per the one-prompt-one-task rule: psf_precision_value_from carries the identical swap, and correcting one without the other would make the psf_weighted_data and psf_precision_operator paths disagree about kernel orientation. They need fixing together.

dashboard.md / dashboard.html — regenerated. dashboard_refresh.yml gates pull requests on draft/**, so a stale page fails the branch rather than self-healing on main. The diff is confined to the new prompt: backlog 145 → 146, bug 36 → 37, and its backlog entry.

Checks run locally

  • scripts/lifecycle.py check → OK
  • scripts/lifecycle.py index --check → OK
  • scripts/registry_toc.py --check → fresh
  • intake dashboard --check → current (after regeneration)
  • pytest tests/ → 159 passed

No registry files (active.md, active/, complete/) were touched — those stay with $start-dev and the ship skills.

🤖 Generated with Claude Code

https://claude.ai/code/session_013unzp382r79c4BN8g4ckb2

claude added 4 commits August 21, 2026 01:20
Records the confirmed diagnosis on the bug prompt: an unguarded out-of-bounds
gather in `psf_weighted_data_from`, not the numba codegen/caching issue the
prompt led with. Proven by compiling the shipped source under numba
`boundscheck=True`. Notes why the inf suspect is unreachable, and what was
not verified here (the profiling-harness corruption counters).

Files the kernel-shift axis swap found alongside it as its own prompt, per
the one-prompt-one-task rule.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013unzp382r79c4BN8g4ckb2
`dashboard_refresh.yml` gates pull requests on `draft/**`, so the stale page
would have failed CI on the branch rather than self-healing on main.

Diff is confined to the new prompt: backlog 145 -> 146, bug 36 -> 37, and its
backlog entry.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013unzp382r79c4BN8g4ckb2
Symptom 1 reproduced exactly on the real profiling dataset: pre-fix
max abs(psf_weighted_data) = 4.901e300, post-fix 298.312. The bug report's
own "2.98e02 on fit #2" matches the post-fix value exactly.

Corrects an earlier reading of the mask padding: `apply_mask` does not pad,
and the padded blurring mask belongs to the dense convolver, not the sparse
numba path — which reads the unpadded (71, 71) array, so 1244 of 3841 pixels
gather off the array edge.

Also records that the named acceptance probe is a weak detector: the
corruption counters read zero both pre-fix and post-fix, because the values
an out-of-bounds read returns depend on heap state. The direct
max abs(psf_weighted_data) check is the reliable probe.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013unzp382r79c4BN8g4ckb2
@Jammy2211
Jammy2211 merged commit 440d68b into main Aug 21, 2026
1 check passed
@github-actions
github-actions Bot deleted the claude/autoarray-numba-psf-garbage-hfxnjv branch August 25, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants