diff --git a/active.md b/active.md index d4b9e40a..213a55ea 100644 --- a/active.md +++ b/active.md @@ -13,25 +13,6 @@ `research/mge-lane-death` branch was never created. This is the canonical copy of the 2026-08-17 human-approved inference programme. -## positions-lh-penalty-accumulation -- issue: https://github.com/PyAutoLabs/PyAutoLens/issues/699 -- status: pr-open (https://github.com/PyAutoLabs/PyAutoLens/pull/700) -- worktree: ~/Code/PyAutoLabs-wt/positions-lh-penalty-accumulation -- repos: - - PyAutoLens: feature/positions-lh-penalty-accumulation -- prompt: active/positions_lh_penalty_accumulation_bug.md -- CONFLICT OVERRIDE (deliberate, 2026-08-17): `worktree_check_conflict` exits 1 — PyAutoLens is - also claimed by `version-stamp-sync-guards`. FILE-DISJOINT verified: that branch's only commit - (`be4c4c8b6`) touches `autolens/__init__.py` + `release.sh`; this task touches - `autolens/analysis/analysis/lens.py` + `test_autolens/`. Human-directed session ("get prs and - whatnot up", 2026-08-17). If that task starts touching `analysis/`, stop and re-coordinate. -- summary: `log_likelihood_penalty_from` (`lens.py:163-181`) overwrites its accumulator then adds - the variable to itself → analysis subtracts 2x the LAST PositionsLH penalty and discards earlier - entries. Fix accumulation to a true sum, repin the 2 tests that encode the bug - (`test_analysis_imaging.py:101,:126` assert the same value for 1 and 2 penalties), add a - sum-of-penalties regression test, align docstring (keep 0.0-array return, not None). - CP-1 of the inference programme (plan §2.1); blocks all PositionsLH benchmarking. - ## stored-sample-reconstruction-guard - issue: https://github.com/PyAutoLabs/PyAutoFit/issues/1486 - status: library-dev — WORKSPACE HALF SHIPPED; the PyAutoFit hardening (#1486) is what remains diff --git a/active/positions_lh_penalty_accumulation_bug.md b/active/positions_lh_penalty_accumulation_bug.md deleted file mode 100644 index e5fb7151..00000000 --- a/active/positions_lh_penalty_accumulation_bug.md +++ /dev/null @@ -1,60 +0,0 @@ -# PositionsLH penalty accumulation returns 2x the LAST penalty, discarding the rest - -- Work type: bug -- Target: PyAutoLens -- Sized: small -- Origin: inference-programme planning pass 2026-08-17 (plan §2.1, CP-1); human: "thats - worrying if theres a bug in soemthing so important so defo check". - -## Original request (verbatim, from the programme plan critical path) - -> CP-1 · PositionsLH defect verify + fix (hours, laptop). Unblocks the entire positions -> arc; every later positions result depends on it. - -## The bug (VERIFIED against main by direct read, 2026-08-17) - -`AnalysisLens.log_likelihood_penalty_from` (`autolens/analysis/analysis/lens.py:163-181`): - -```python -log_likelihood_penalty = self._xp.array(0.0) -if self.positions_likelihood_list is not None: - for positions_likelihood in self.positions_likelihood_list: - if positions_likelihood is not None: - log_likelihood_penalty = ( # <-- OVERWRITES the accumulator - positions_likelihood.log_likelihood_penalty_from(...) - ) - log_likelihood_penalty += log_likelihood_penalty # <-- doubles itself - return log_likelihood_penalty -``` - -- One penalty in the list (the common case, incl. every SLaM stage): returns **2x** the - documented `1e8 * (max_separation - threshold)` penalty. -- N penalties (double-source-plane / multi-plane usage): returns 2x the **last** entry - only; all earlier penalties silently discarded. -- Docstring also promises `None` when there is no penalty but the code returns a 0.0 - array (the JAX-safe behaviour) — align the docstring, keep the behaviour. - -Existing tests PIN the bug: `test_autolens/imaging/model/test_analysis_imaging.py:101` -and `:126` assert the SAME value (-44097289521.734665) for one and for two penalty -objects — exactly the 2x-last signature. Both expected values need recomputing after -the fix (single: base - p; two-plane: base - (p0 + p1)). - -## Fix - -Accumulate: `log_likelihood_penalty = log_likelihood_penalty + penalty_i` (JAX-traceable, -no in-place mutation semantics needed). Update the two pinned test values, add a -regression test asserting (a) two penalties = sum of the two individual penalties, -(b) one penalty = exactly the `PositionsLH.log_likelihood_penalty_from` value (no 2x). - -## Science impact (record in PR) - -Inside threshold the penalty is exactly 0 either way — converged posteriors and all -positions-free results unchanged. Outside threshold the fence slope halves (2e8 -> 1e8 -per arcsec): early-search likelihood values in penalized regions change, and -multi-plane penalty stacking is corrected. Classify as bug-fix restoring documented -behaviour; note in release notes that penalized-region likelihood values shift. - -## Do-not - -- Do not change the penalty formula, threshold semantics, or `PositionsLH` itself. -- Do not return `None` (JAX path needs the 0.0 array); fix the docstring instead. diff --git a/complete/2026/08/positions-lh-penalty-accumulation.md b/complete/2026/08/positions-lh-penalty-accumulation.md new file mode 100644 index 00000000..bdfd5602 --- /dev/null +++ b/complete/2026/08/positions-lh-penalty-accumulation.md @@ -0,0 +1,120 @@ +- issue: https://github.com/PyAutoLabs/PyAutoLens/issues/699 (CLOSED completed) +- pr: https://github.com/PyAutoLabs/PyAutoLens/pull/700 — MERGED 2026-08-17 as `5d55825`, 3 files, +28/-8 +- classification: library (PyAutoLens) — bug, severity high; CP-1 of the inference programme (autolens_profiling#134, PROGRAMME.md §2.1) +- branch: `feature/positions-lh-penalty-accumulation` +- worktree: `~/Code/PyAutoLabs-wt/positions-lh-penalty-accumulation` — **release pending** (merge happened from a remote session; free the worktree in the next laptop session or let repo_cleanup flag it) + +## What was wrong + +`AnalysisLens.log_likelihood_penalty_from` (`autolens/analysis/analysis/lens.py:163-181`) +overwrote its accumulator with each entry's penalty and then added the variable +to itself, so the analysis subtracted **2x the LAST** `PositionsLH` penalty and +silently discarded every earlier entry in `positions_likelihood_list`. With one +entry (every SLaM stage) that is 2x the documented +`1e8 * (max_separation - threshold)` fence; with N entries +(double-source-plane / multi-plane) all but the last were lost. Blocked the +entire PositionsLH benchmarking arc — every positions experiment would have +measured an undocumented target. + +## Fix + +Accumulation is now a true sum (`x = x + y`, trivially `xp`-safe under `jnp`); +docstring aligned to the actual 0.0-array (not `None`) no-penalty return, kept +for the JAX path. Tests that PINNED the bug repinned: imaging single-penalty +`-44097289521.73` → `-22048644768.18` (exactly half — the 2x), double-plane +`-44097289521.73` → `-44140499627.75` (the true sum, now distinct from the +single-penalty value), interferometer `-44097289569.2` → `-22048644815.85`. +New regression assertions: analysis penalty == sum of each entry's own +`log_likelihood_penalty_from`, the two per-plane penalties genuinely differ, +single-entry == the entry's value exactly (no 2x). Full suite 538/538; PR CI +green (unittest 3.12/3.13 + docs-build). + +## Science impact (release-notes item) + +Inside the threshold the penalty is exactly 0 either way — converged posteriors +and positions-free results unchanged. Outside it the fence slope **halves** +from the undocumented 2e8/arcsec to the documented 1e8/arcsec, so likelihood +values in penalized regions shift. Multi-plane penalty stacking is corrected — +previously only the last plane counted. + +## Traps and findings + +- **THE TESTS ENCODED THE BUG, AND ITS SIGNATURE HID THE DISCARD.** The + double-plane test asserted the SAME value for one and for two penalties — + under 2x-last, adding a second penalty changes nothing the tolerance could + see. The corrected two-plane value shows the per-plane penalties genuinely + differ; the regression test now pins the sum explicitly. +- **CONFLICT OVERRIDE precedent used:** PyAutoLens was co-claimed by + `version-stamp-sync-guards`; `worktree_check_conflict` exits 1. FILE-DISJOINT + verified (that branch touches only `autolens/__init__.py` + `release.sh`) and + a deliberate, human-directed override was recorded in active.md rather than + blocking. +- **Sizing-proxy miss:** the Brain Bug Agent scored this large(7)/split via the + prose-length proxy; correctly overridden to small/single-PR — the fix was one + accumulation line + docstring + test repins. Detailed prompts overcount. +- **Registry-edit trap (same session):** a blanket `sed` status edit briefly + clobbered the stored-sample task's status line in active.md — caught and + restored immediately. Scope registry edits to the task's own `##` section. + +## Original prompt + +# PositionsLH penalty accumulation returns 2x the LAST penalty, discarding the rest + +- Work type: bug +- Target: PyAutoLens +- Sized: small +- Origin: inference-programme planning pass 2026-08-17 (plan §2.1, CP-1); human: "thats + worrying if theres a bug in soemthing so important so defo check". + +## Original request (verbatim, from the programme plan critical path) + +> CP-1 · PositionsLH defect verify + fix (hours, laptop). Unblocks the entire positions +> arc; every later positions result depends on it. + +## The bug (VERIFIED against main by direct read, 2026-08-17) + +`AnalysisLens.log_likelihood_penalty_from` (`autolens/analysis/analysis/lens.py:163-181`): + +```python +log_likelihood_penalty = self._xp.array(0.0) +if self.positions_likelihood_list is not None: + for positions_likelihood in self.positions_likelihood_list: + if positions_likelihood is not None: + log_likelihood_penalty = ( # <-- OVERWRITES the accumulator + positions_likelihood.log_likelihood_penalty_from(...) + ) + log_likelihood_penalty += log_likelihood_penalty # <-- doubles itself + return log_likelihood_penalty +``` + +- One penalty in the list (the common case, incl. every SLaM stage): returns **2x** the + documented `1e8 * (max_separation - threshold)` penalty. +- N penalties (double-source-plane / multi-plane usage): returns 2x the **last** entry + only; all earlier penalties silently discarded. +- Docstring also promises `None` when there is no penalty but the code returns a 0.0 + array (the JAX-safe behaviour) — align the docstring, keep the behaviour. + +Existing tests PIN the bug: `test_autolens/imaging/model/test_analysis_imaging.py:101` +and `:126` assert the SAME value (-44097289521.734665) for one and for two penalty +objects — exactly the 2x-last signature. Both expected values need recomputing after +the fix (single: base - p; two-plane: base - (p0 + p1)). + +## Fix + +Accumulate: `log_likelihood_penalty = log_likelihood_penalty + penalty_i` (JAX-traceable, +no in-place mutation semantics needed). Update the two pinned test values, add a +regression test asserting (a) two penalties = sum of the two individual penalties, +(b) one penalty = exactly the `PositionsLH.log_likelihood_penalty_from` value (no 2x). + +## Science impact (record in PR) + +Inside threshold the penalty is exactly 0 either way — converged posteriors and all +positions-free results unchanged. Outside threshold the fence slope halves (2e8 -> 1e8 +per arcsec): early-search likelihood values in penalized regions change, and +multi-plane penalty stacking is corrected. Classify as bug-fix restoring documented +behaviour; note in release notes that penalized-region likelihood values shift. + +## Do-not + +- Do not change the penalty formula, threshold semantics, or `PositionsLH` itself. +- Do not return `None` (JAX path needs the 0.0 array); fix the docstring instead. diff --git a/complete/index.md b/complete/index.md index b20f0975..3c51183d 100644 --- a/complete/index.md +++ b/complete/index.md @@ -6,7 +6,7 @@ Token-light navigation over the finished-work records (schema: only then grep a dated bucket. Curators: edit the band between the CURATED markers; everything below GENERATED is rebuilt. -1004 records across 7 buckets. +1005 records across 7 buckets. ## Highlights @@ -94,6 +94,7 @@ _(curate hard-won records here — survives regeneration.)_ - [point-source-light](2026/08/point-source-light.md) — Added standard and linear point-source light profiles with total-flux normalization and oversampled PSF convol… - [pointmass-smbh-jax](2026/08/pointmass-smbh-jax.md) — `al.mp.PointMass` and `al.mp.SMBH` failed every JAX-mode fit (user report on 2026.8.4.1). Two independent bugs… - [pointmass-smbh-jax-ci](2026/08/pointmass-smbh-jax-ci.md) — CI JAX coverage for the PointMass/SMBH regression class (follow-up to PyAutoGalaxy#553/#554). `misc/profiles_j… +- [positions-lh-penalty-accumulation](2026/08/positions-lh-penalty-accumulation.md) — CLOSED completed - [positive-solver-divergence-diagnosis](2026/08/positive-solver-divergence-diagnosis.md) — Proved NumPy FNNLS and JAX PDIP agree to 1.715e-9 on identical systems (2.468e-13 tightened). The 8.989e-3 nat… - [potential-correction-env-declaration](2026/08/potential-correction-env-declaration.md) - [potential-correction-validation](2026/08/potential-correction-validation.md) diff --git a/dashboard.md b/dashboard.md index c92e696c..882b4d9f 100644 --- a/dashboard.md +++ b/dashboard.md @@ -8,7 +8,7 @@ Tasks only — the organism's health lives with the Heart (`/health`), not here. | Where | Count | |-------|------:| -| [In flight](#in-flight) (`active/`) | 5 | +| [In flight](#in-flight) (`active/`) | 4 | | [Parked](#parked) (`parked.md`) | 1 | | [Planned](#planned) (`planned.md`) | 7 | | [Backlog](#backlog) (`draft/`) | 139 | @@ -49,7 +49,6 @@ Live on GitHub: [open issues](https://github.com/search?q=org%3APyAutoLabs+is%3A Issued — each has an open GitHub issue and usually a branch. The full record for each is in [`active.md`](active.md). - [Commit the inference-methods programme plan + knowledge ledger into autolens_profiling](active/inference_programme_ledger.md) — [issue #134](https://github.com/PyAutoLabs/autolens_profiling/issues/134) — pr-open (https://github.com/PyAutoLabs/autolens_profiling/pull/135) -- [PositionsLH penalty accumulation returns 2x the LAST penalty, discarding the](active/positions_lh_penalty_accumulation_bug.md) — [issue #699](https://github.com/PyAutoLabs/PyAutoLens/issues/699) — pr-open (https://github.com/PyAutoLabs/PyAutoLens/pull/700) - [PyAutoReduce validation: slacs1430+4105 ACS reduction vs trusted legacy dataset](active/pyautoreduce_slacs1430_acs_comparison.md) - [Reconstructing a stored sample raises through `ignore_assertions=True`](active/to_instance_guard_gap.md) — [issue #1486](https://github.com/PyAutoLabs/PyAutoFit/issues/1486) — library-dev — WORKSPACE HALF SHIPPED; the PyAutoFit hardening (#1486) is what remains - [Version-stamp sync to 2026.8.17.1 + release-sed guards](active/version_stamp_sync_and_release_sed_guards.md) — [issue #235](https://github.com/PyAutoLabs/PyAutoHands/issues/235) — pr-open (https://github.com/PyAutoLabs/PyAutoLens/pull/700)