Every task the Mind is holding. Tap a task's 📋 and its /start_dev command is on your clipboard — paste it into a Claude Code chat to route Claude straight to that task.
-
In flight 2 · Parked 3 · Planned 6 · Backlog 143 · markdown version
+
In flight 2 · Parked 3 · Planned 6 · Backlog 146 · markdown version
Start here
-
Highest priority (filed as high) — showing 12 of 18
+
Highest priority (filed as high) — showing 12 of 19
143 filed prompts, not started — sorted most-pickable first (priority, then size). 23 of them belong to an epic and are listed only under Epics below.
+
146 filed prompts, not started — sorted most-pickable first (priority, then size). 23 of them belong to an epic and are listed only under Epics below.
diff --git a/dashboard.md b/dashboard.md
index 4abde06b..df646139 100644
--- a/dashboard.md
+++ b/dashboard.md
@@ -11,11 +11,11 @@ Every task the Mind is holding, on one page: what is in flight, what is parked,
| [In flight](#in-flight) (`active/`) | 2 |
| [Parked](#parked) (`parked.md`) | 3 |
| [Planned](#planned) (`planned.md`) | 6 |
-| [Backlog](#backlog) (`draft/`) | 143 |
+| [Backlog](#backlog) (`draft/`) | 146 |
## Start here
-**Highest priority** (filed as `high`) — showing 12 of 18
+**Highest priority** (filed as `high`) — showing 12 of 19
📋 TRIAGE: needs manual review before routing — medium · safe · high
@@ -73,6 +73,14 @@ Every task the Mind is holding, on one page: what is in flight, what is parked,
+📋 Stamp the small-datasets regime at the FITS writer funnel — pyautonerves · large · supervised · high
+
+```
+/start_dev draft/bug/pyautonerves/small_datasets_regime_stamp_at_writer_funnel.md
+```
+
+
+
📋 Deep research: Can we speed up Delaunay in PyAutoArray? — autoarray · too-large · supervised · high
```
@@ -105,14 +113,6 @@ Every task the Mind is holding, on one page: what is in flight, what is parked,
-📋 Re-baseline the MGE imaging JIT profiling regression value — autolens_workspace_developer · too-large · supervised · high
-
-```
-/start_dev draft/test/autolens_workspace_developer/mge_jit_regression_rebaseline.md
-```
-
-
-
**Quick wins** (small enough, and safe enough to run unattended)
- _(none right now)_
@@ -229,7 +229,7 @@ Scoped but not started; some are not yet prompt files. Full detail in [`planned.
## Backlog
-**143** filed prompts, not started. Each section is sorted most-pickable first (priority, then size). **23** of them belong to an epic and are listed only under [Epics](#epics) below.
+**146** filed prompts, not started. Each section is sorted most-pickable first (priority, then size). **23** of them belong to an epic and are listed only under [Epics](#epics) below.
feature — 28
@@ -461,7 +461,15 @@ Scoped but not started; some are not yet prompt files. Full detail in [`planned.
-bug — 31
+bug — 33
+
+📋 Stamp the small-datasets regime at the FITS writer funnel — pyautonerves · large · supervised · high
+
+```
+/start_dev draft/bug/pyautonerves/small_datasets_regime_stamp_at_writer_funnel.md
+```
+
+📋 Fix release JAX runtime compatibility and likelihood parity — health_fixes · too-large · supervised · high
@@ -519,6 +527,14 @@ Scoped but not started; some are not yet prompt files. Full detail in [`planned.
+📋 should_simulate rmtree's committed, gitignore-allowlisted datasets — autoarray · medium · supervised · medium
+
+```
+/start_dev draft/bug/autoarray/small_datasets_rmtree_of_committed_data.md
+```
+
+
+
📋 Numba PSF gathers derive the y/x kernel shifts from the — autoarray · low · supervised · medium
```
@@ -847,7 +863,15 @@ Scoped but not started; some are not yet prompt files. Full detail in [`planned.
-maintenance — 17
+maintenance — 18
+
+📋 smoke_install.sh's stale jax<0.7 pin — CI is on the right — ci · low · supervised · medium
+
+```
+/start_dev draft/maintenance/ci/smoke_install_stale_jax_pin.md
+```
+
+📋 autolens_workspace_developer rectangular experiments — Gut stash + rename — autolens_workspace_developer · small · supervised · normal
diff --git a/draft/bug/autoarray/small_datasets_rmtree_of_committed_data.md b/draft/bug/autoarray/small_datasets_rmtree_of_committed_data.md
new file mode 100644
index 00000000..8680fd7e
--- /dev/null
+++ b/draft/bug/autoarray/small_datasets_rmtree_of_committed_data.md
@@ -0,0 +1,84 @@
+# should_simulate rmtree's committed, gitignore-allowlisted datasets
+
+Type: bug
+Target: autoarray
+Repos:
+- @PyAutoArray
+- @autolens_workspace_test
+Difficulty: medium
+Autonomy: supervised
+Priority: medium
+Status: formalised
+
+Tracked as PyAutoArray#470. Found during
+`complete/2026/08/jax-grad-local-vs-ci-assertions.md`; **independent of that bug**
+and untouched by its fix (PyAutoArray#471).
+
+`should_simulate` deletes tracked, version-controlled data and replaces it with
+capped-simulator output.
+
+## The defect
+
+`autoarray/util/dataset_util.py`, small-datasets branch:
+
+```python
+if os.environ.get("PYAUTO_SMALL_DATASETS") == "1":
+ if Path(dataset_path).exists():
+ shutil.rmtree(dataset_path)
+```
+
+The `rmtree` is unconditional. It never asks whether the directory holds
+generated data or committed data.
+
+## The live case
+
+In `autolens_workspace_test`:
+
+- `.gitignore:13` reads `!dataset/point_source/simple/**` — an explicit allowlist
+ exception, i.e. the directory is **deliberately committed**. `git ls-files`
+ confirms three tracked JSON files under it. The allowlist comments describe this
+ class as real/external data that must never be purged.
+- `scripts/point_source/visualization/visualization.py:39` calls
+ `should_simulate("dataset/point_source/simple")`, and that script declares only
+ `ENV: real_plots` (line 22), so it **keeps** `PYAUTO_SMALL_DATASETS=1` under the
+ smoke profile defaults.
+
+So an ordinary smoke run deletes committed data. It is then re-simulated through
+`PointSolver.solve`, which under the cap short-circuits to a fixed position pair
+(`PyAutoLens autolens/point/solver/point_solver.py:119`) — the replacement is not
+merely lower-resolution, it is degenerate. Seven full-regime scripts read that
+same directory, one of them in `smoke_tests.txt`.
+
+## Severity — recoverable, but wrong
+
+`git checkout -- dataset/point_source/simple` restores it and the deletion shows
+as a dirty tree, so this is not unrecoverable data loss. But it silently violates
+the invariant the allowlist exists to express, leaves developers with an
+unexplained dirty tree after a routine smoke run, and — combined with the seven
+full-regime readers — is the same mixed-regime collision class as #260 in a
+dataset family the shape-based fix is structurally blind to (JSON, no FITS).
+
+## Options (a design call is needed — do not just pick one)
+
+1. **Skip `rmtree` for git-tracked paths.** Cheap, but puts a git dependency in a
+ library utility: wrong layer.
+2. **Have the workspace declare the exception** — give
+ `point_source/visualization/visualization.py` a `full_datasets`-style profile
+ entry so it never enters the small regime against committed data. Narrowest
+ fix; leaves the general footgun armed for the next allowlisted dataset.
+3. **Regime path separation** — capped runs write to a separate path so the two
+ regimes never share a directory. Removes the collision rather than detecting
+ it, and would also close #260's remaining gaps, but needs a path-rewrite layer
+ in the IO with real sharp edges (committed read-only inputs like
+ `uv_wavelengths/sma.fits` need read-fallback; plot outputs; absolute paths).
+
+(2) unblocks the immediate case; (3) is the architecturally correct shape if this
+class keeps recurring. Related: PyAutoNerves#153.
+
+
+
+
diff --git a/draft/bug/pyautonerves/small_datasets_regime_stamp_at_writer_funnel.md b/draft/bug/pyautonerves/small_datasets_regime_stamp_at_writer_funnel.md
new file mode 100644
index 00000000..298c539d
--- /dev/null
+++ b/draft/bug/pyautonerves/small_datasets_regime_stamp_at_writer_funnel.md
@@ -0,0 +1,99 @@
+# Stamp the small-datasets regime at the FITS writer funnel
+
+Type: bug
+Target: pyautonerves
+Repos:
+- @PyAutoNerves
+- @PyAutoArray
+Difficulty: large
+Autonomy: supervised
+Priority: high
+Status: formalised
+
+Tracked as PyAutoNerves#153. Follow-up to
+`complete/2026/08/jax-grad-local-vs-ci-assertions.md` (PyAutoArray#471), which
+closed the **imaging** manifestation of this bug class and deliberately left the
+rest open.
+
+`PYAUTO_SMALL_DATASETS=1` caps simulated datasets to a reduced resolution, but
+**nothing on disk records which regime a dataset was written under**. That gap
+lets a capped dataset survive into a later full-resolution run and be loaded
+silently.
+
+## Why the shipped fix is not enough
+
+PyAutoArray#471 made `should_simulate` regenerate on the small->full transition by
+*inferring* the regime from `data.fits`'s shape (the cap emits exactly
+`SMALL_DATASETS_SHAPE_NATIVE = (16, 16)`). That inference is structurally blind to
+two dataset families:
+
+- **Point-source and weak-lensing datasets are JSON** — `dataset/point_source/simple/`
+ holds only `.json`, and weak lensing writes `dataset.json`
+ (`autolens_workspace/scripts/weak/simulator.py:136`). There is no FITS to infer
+ from, so `should_simulate` degenerates to existence-only there.
+- **Interferometer corruption is shape-invariant.** The visibility count is fixed
+ by the committed uv file (`sma.fits`, 360 baselines) while the real-space grid
+ the visibilities are computed from is capped 256x256 -> 16x16
+ (`Grid2D.uniform`, `uniform_2d.py:499`). So a capped run writes a `data.fits`
+ with **identical NAXIS** and garbage values.
+
+The interferometer case is the reason this is `Priority: high`: unlike the imaging
+failure that started all this, it produces **no shape mismatch and trips no
+assertion**. It fails silently. A silent wrong answer in a likelihood is worse
+than a loud one.
+
+## The proposal
+
+Record the regime at **write** time instead of inferring it at read time.
+
+Every FITS write in the entire stack funnels through **one function** —
+`autonerves/fitsable.py:89` `output_to_fits` (verified: it is the only
+`output_to_fits` definition across PyAutoNerves, PyAutoArray, PyAutoGalaxy and
+PyAutoLens, and is re-exported as `aa.output_to_fits`). A header card written
+there when `PYAUTO_SMALL_DATASETS=1` is active is:
+
+- **truthful by construction** — written by the same call that writes the data, so
+ it cannot disagree with it, and there is no stamped-but-empty-directory failure
+ mode (the reason a marker file written by `should_simulate` was rejected: that
+ function runs *before* simulation and cannot write a truthful marker);
+- **zero-call-site** — no changes across the ~420 `should_simulate` sites in the
+ workspaces;
+- **the only discriminant that can catch the interferometer case**, since it does
+ not depend on shape.
+
+`PyAutoArray.should_simulate` then prefers the stamp, keeping the existing shape
+heuristic as the legacy fallback for datasets already on disk that carry no stamp.
+
+## Risks to weigh before implementing
+
+- This changes a header card on **every FITS the stack writes**. Round-trip tests,
+ file-hash regression pins and golden-file comparisons could be disturbed. This is
+ exactly why it was kept out of PyAutoArray#471 rather than riding along with it —
+ it deserves its own deliberate change and its own CI run.
+- **JSON datasets need a separate decision.** `autonerves/dictable.py:370` is the
+ equivalent funnel, but stamping there risks round-trip pollution of the dictable
+ schema. Point-source and weak lensing stay exposed until that is settled —
+ decide it explicitly rather than by omission.
+- The stamp only helps datasets written *after* it lands, so the shape fallback in
+ PyAutoArray is not throwaway work and must not be removed.
+
+## Suggested scope
+
+1. Add the regime stamp to `output_to_fits`, gated on the env var. Decide the card
+ name and whether absence means "full" or "unknown".
+2. Teach `should_simulate` to prefer the stamp, shape check as fallback.
+3. Run the round-trip / golden-file surface deliberately — that is the real risk,
+ not the logic.
+4. Take the JSON decision explicitly (stamp `dictable`, or record why not and
+ leave point-source/weak-lensing tracked as still-exposed).
+5. Validate against the interferometer case specifically: capped run then
+ full-regime run must now regenerate, where today it silently does not.
+
+
+
+
diff --git a/draft/maintenance/ci/smoke_install_stale_jax_pin.md b/draft/maintenance/ci/smoke_install_stale_jax_pin.md
new file mode 100644
index 00000000..fd1892fc
--- /dev/null
+++ b/draft/maintenance/ci/smoke_install_stale_jax_pin.md
@@ -0,0 +1,68 @@
+# smoke_install.sh's stale `jax<0.7` pin — CI is on the right jax by accident
+
+Type: maintenance
+Target: ci
+Repos:
+- @autolens_workspace_test
+Difficulty: low
+Autonomy: supervised
+Priority: medium
+Status: formalised
+
+Found 2026-08-22 while building a CI-equivalent environment to reproduce
+autolens_workspace_test#260. Latent — CI is green today — but it is green for the
+wrong reason.
+
+## The defect
+
+`autolens_workspace_test/.github/scripts/smoke_install.sh:9`:
+
+```bash
+pip install "jax<0.7" "jaxlib<0.7"
+```
+
+Replaying the install script verbatim, that line **downgrades jax to 0.6.2** and
+raises a resolver conflict against autonerves' own requirement:
+
+```
+autonerves 9999.0.0.dev0 requires jax<0.11.0,>=0.7.0; ... but you have jax 0.6.2
+which is incompatible.
+Successfully installed jax-0.6.2 jaxlib-0.6.2
+```
+
+The install only ends up on the intended **0.10.2** because the *next* line's
+`[optional]` extras happen to pull it back up:
+
+```bash
+pip install "./PyAutoArray[optional]" "./PyAutoGalaxy[optional]" "./PyAutoLens[optional]"
+```
+
+## Why it matters
+
+The pin no longer expresses the intent it was written for, and the correct
+outcome now depends on line ordering rather than on the constraint. Any
+reordering of those two lines, or a change to what the `[optional]` extras
+resolve, would silently drop the entire smoke suite onto jax 0.6.2 — and because
+`autonerves` declares `jax>=0.7`, that is a configuration the stack does not
+claim to support. The failure would surface as unexplained smoke breakage, not as
+an install error.
+
+The comment block immediately below that line (about `tfp-nightly` vs
+`tensorflow-probability`) is still accurate and should be preserved.
+
+## Suggested scope
+
+1. Establish what the `jax<0.7` pin was originally protecting against, and whether
+ that reason still holds — do not simply delete it because it looks stale.
+2. Either remove it (letting `autonerves`' `jax<0.11.0,>=0.7.0` govern) or replace
+ it with a pin that states the real intended range.
+3. Verify by replaying the install from scratch and asserting the resolved jax
+ version, rather than inferring it from a green run.
+4. Check whether sibling workspaces' install epilogues carry the same stale pin.
+
+
+
+