From ddc63a010d5b27b279d015c963ada4ae7448aad8 Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Thu, 9 Jul 2026 17:31:11 +0100 Subject: [PATCH 1/4] ci: run --check-citations as the fifth wiki-currency leg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wires the citation-path check into the wiki-currency workflow (PR / dispatch / workflow_call). CI has no git checkouts, so _project_tree gains a pip-install fallback: resolve against site-packages and check only package-internal paths (autofit/...), skipping repo-level cites (README.md, docs/) rather than false-flagging them — full checkouts (local runs) still check everything. Verified by simulation: package path found, repo-level cite skipped, missing package path exits 1. Follow-up to #40 / PR #41. Co-Authored-By: Claude Fable 5 --- .github/workflows/wiki-currency.yml | 6 +++- autoassistant/audit_skill_apis.py | 49 ++++++++++++++++++++++------- skills/al_audit_skill_apis.md | 16 ++++++---- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/.github/workflows/wiki-currency.yml b/.github/workflows/wiki-currency.yml index 0e72770..ee76ffd 100644 --- a/.github/workflows/wiki-currency.yml +++ b/.github/workflows/wiki-currency.yml @@ -104,11 +104,15 @@ jobs: echo >> "$REPORT" } - # The released stack installed above is the ground truth for all four checks. + # The released stack installed above is the ground truth for all five checks. + # Citations resolve against the pip install (package-internal paths only — + # repo-level cites like README.md are skipped here and checked by local runs + # with full checkouts; see skills/al_audit_skill_apis.md §6). run "Version drift (--check-version)" --check-version run "Symbol audit (--scope all)" --scope all run "Idiom deny-list (--lint-idioms)" --lint-idioms run "Provenance (--check-provenance)" --check-provenance + run "Citation paths (--check-citations)" --check-citations cat "$REPORT" >> "$GITHUB_STEP_SUMMARY" if [ "$fail" -ne 0 ]; then diff --git a/autoassistant/audit_skill_apis.py b/autoassistant/audit_skill_apis.py index ed3e547..7535374 100644 --- a/autoassistant/audit_skill_apis.py +++ b/autoassistant/audit_skill_apis.py @@ -1146,16 +1146,31 @@ def _sources_projects(root: Path) -> list[str]: return list(PROJECT_IMPORT) -def _project_tree(project: str, root: Path) -> Optional[Path]: - """A directory holding `project`'s source tree: the installed checkout - (_project_repo), else `sources//`, else a sibling clone of this repo. +def _project_tree(project: str, root: Path) -> Optional[tuple[Path, str]]: + """A directory holding `project`'s source tree, tagged with how complete it is: + + - `("…", "repo")` — a full checkout: the installed package's enclosing git repo, + a `sources//` clone, or a sibling clone. Every repo-relative path is + checkable. + - `("…", "package")` — a plain pip install (CI): the site-packages directory + containing the imported package. Only paths under the package itself + (`autofit/…`) are checkable; repo-level files (README.md, docs/) are not, and + the caller must skip them rather than flag them. + None when nothing is present — the caller downgrades to a warning.""" repo = _project_repo(project) if repo is not None: - return repo + return repo, "repo" for candidate in (root / "sources" / project, root.parent / project): if candidate.is_dir(): - return candidate + return candidate, "repo" + imp = PROJECT_IMPORT.get(project) + if imp: + try: + mod = importlib.import_module(imp) + return Path(mod.__file__).resolve().parent.parent, "package" + except Exception: # noqa: BLE001 + pass return None @@ -1177,25 +1192,35 @@ def check_citations(root: Path) -> int: warns: list[str] = [] seen_missing_tree: set[str] = set() n_citations = 0 + n_skipped = 0 def _check_one(rel_file: Path, project: str, cited: str) -> None: - nonlocal n_citations + nonlocal n_citations, n_skipped n_citations += 1 if project == "autolens_assistant": - tree: Optional[Path] = root # self-citations resolve against this repo + resolved: Optional[tuple[Path, str]] = (root, "repo") # self-citations else: - tree = _project_tree(project, root) - if tree is None: + resolved = _project_tree(project, root) + if resolved is None: if project not in seen_missing_tree: seen_missing_tree.add(project) warns.append( - f"{project}: no checkout resolvable (installed/sources/sibling) — " + f"{project}: no source tree resolvable (checkout or install) — " f"its citations skipped." ) + n_skipped += 1 return + tree, kind = resolved concrete = cited.split("...")[0].rstrip("/") if not concrete: return + if kind == "package": + # Plain pip install: only package-internal paths exist on disk. Skip + # repo-level citations (README.md, docs/) — a full checkout checks them. + imp = PROJECT_IMPORT.get(project, "") + if concrete.split("/")[0] != imp: + n_skipped += 1 + return if not (tree / concrete).exists(): errors.append(f"{rel_file}: `{project}:{cited}` — {concrete} not in {tree}") @@ -1228,8 +1253,8 @@ def _check_one(rel_file: Path, project: str, cited: str) -> None: for e in errors: print(f"[citations] ERROR {e}", file=sys.stderr) print( - f"[citations] scanned {len(files)} files, {n_citations} citation(s) — " - f"{len(errors)} missing path(s), {len(warns)} warning(s).", + f"[citations] scanned {len(files)} files, {n_citations} citation(s) " + f"({n_skipped} skipped) — {len(errors)} missing path(s), {len(warns)} warning(s).", file=sys.stderr, ) return 1 if errors else 0 diff --git a/skills/al_audit_skill_apis.md b/skills/al_audit_skill_apis.md index 1dc56dc..c594fa4 100644 --- a/skills/al_audit_skill_apis.md +++ b/skills/al_audit_skill_apis.md @@ -169,12 +169,16 @@ python autoassistant/audit_skill_apis.py --check-citations # 0 ok, 1 on missin It scans `skills/`, `wiki/core/`, `AGENTS.md` and `llms.txt` for inline `` `:` `` citations (projects from `sources.yaml`) plus each wiki -page's frontmatter `sources[].paths[]`, and resolves every path against a checkout -of the cited project (installed → `sources//` → sibling clone). A path -containing `...` is a deliberate abbreviation — only its concrete prefix must -exist. Missing paths are ERRORs; a project with no resolvable checkout downgrades -to a warning. Run it alongside the symbol audit in every refresh -(`al_refresh_api_docs`) and before a release. +page's frontmatter `sources[].paths[]`, and resolves every path against a source +tree of the cited project: a full checkout (installed-from-git → +`sources//` → sibling clone) checks everything; a plain pip install +(CI) checks package-internal paths (`autofit/…`) and skips repo-level ones +(README.md, docs/) rather than false-flagging them. A path containing `...` is a +deliberate abbreviation — only its concrete prefix must exist. Missing paths are +ERRORs; a project with no resolvable tree downgrades to a warning. Run it +alongside the symbol audit in every refresh (`al_refresh_api_docs`) and before a +release; it is also the fifth leg of the `wiki-currency` CI workflow, so PRs are +graded on it automatically. ERRORs fail the check; warnings (unpinned `main`, unstamped legacy pages) do not unless `--strict`, so the release/PR check goes red on genuine forgery/staleness without nuking the From e6fddf096efa7b32578b43824f94d93a34a4669a Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Thu, 9 Jul 2026 17:35:06 +0100 Subject: [PATCH 2/4] ci: grade citation paths against main clones, not the release wheel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first PR run proved the leg works but exposed the version axis: docs pin main while CI installs the released stack, so post-release moves (ultranest/, pyswarms/, weak/model/, quantity/) false-failed. CI now shallow-clones the five libraries (+ sparse autolens_workspace: scripts/ + root catalogues) into sources/ — the resolver's documented fallback — so citations grade against the refs the docs pin; the release install remains ground truth for the symbol / version / idiom checks only. Pip-install resolution stays as last resort. Co-Authored-By: Claude Fable 5 --- .github/workflows/wiki-currency.yml | 23 +++++++++++++++++++---- skills/al_audit_skill_apis.md | 22 ++++++++++++++-------- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/.github/workflows/wiki-currency.yml b/.github/workflows/wiki-currency.yml index ee76ffd..712e472 100644 --- a/.github/workflows/wiki-currency.yml +++ b/.github/workflows/wiki-currency.yml @@ -76,6 +76,22 @@ jobs: pip install autolens fi + # Citation paths are graded against the refs the docs pin (`main` checkouts), + # NOT the pip-installed release above — post-release file moves would otherwise + # false-fail the docs. The pip install stays the ground truth for the symbol / + # version / idiom checks (what users actually run); the clones land in sources/, + # the resolver's documented fallback. autolens_workspace is sparse-cloned to its + # cited surface (scripts/ + root catalogues) to skip the heavy dataset blobs. + - name: Clone cited source trees (citation ground truth) + run: | + mkdir -p sources + for repo in PyAutoConf PyAutoArray PyAutoFit PyAutoGalaxy PyAutoLens; do + git clone --quiet --depth 1 "https://github.com/PyAutoLabs/$repo" "sources/$repo" + done + git clone --quiet --depth 1 --filter=blob:none --sparse \ + https://github.com/PyAutoLabs/autolens_workspace sources/autolens_workspace + git -C sources/autolens_workspace sparse-checkout set scripts llms.txt llms-full.txt workspace_index.json + - name: Run wiki-currency checks id: checks run: | @@ -104,10 +120,9 @@ jobs: echo >> "$REPORT" } - # The released stack installed above is the ground truth for all five checks. - # Citations resolve against the pip install (package-internal paths only — - # repo-level cites like README.md are skipped here and checked by local runs - # with full checkouts; see skills/al_audit_skill_apis.md §6). + # The released stack installed above is the ground truth for the first four + # checks; citations resolve against the sources/ clones from the previous + # step (the refs the docs pin — see skills/al_audit_skill_apis.md §6). run "Version drift (--check-version)" --check-version run "Symbol audit (--scope all)" --scope all run "Idiom deny-list (--lint-idioms)" --lint-idioms diff --git a/skills/al_audit_skill_apis.md b/skills/al_audit_skill_apis.md index c594fa4..ef3ccf7 100644 --- a/skills/al_audit_skill_apis.md +++ b/skills/al_audit_skill_apis.md @@ -171,14 +171,20 @@ It scans `skills/`, `wiki/core/`, `AGENTS.md` and `llms.txt` for inline `` `:` `` citations (projects from `sources.yaml`) plus each wiki page's frontmatter `sources[].paths[]`, and resolves every path against a source tree of the cited project: a full checkout (installed-from-git → -`sources//` → sibling clone) checks everything; a plain pip install -(CI) checks package-internal paths (`autofit/…`) and skips repo-level ones -(README.md, docs/) rather than false-flagging them. A path containing `...` is a -deliberate abbreviation — only its concrete prefix must exist. Missing paths are -ERRORs; a project with no resolvable tree downgrades to a warning. Run it -alongside the symbol audit in every refresh (`al_refresh_api_docs`) and before a -release; it is also the fifth leg of the `wiki-currency` CI workflow, so PRs are -graded on it automatically. +`sources//` → sibling clone) checks everything; a plain pip install is +the last-resort fallback, checking package-internal paths (`autofit/…`) and +skipping repo-level ones (README.md, docs/) rather than false-flagging them. A +path containing `...` is a deliberate abbreviation — only its concrete prefix +must exist. Missing paths are ERRORs; a project with no resolvable tree +downgrades to a warning. + +**Ground truth is the ref the docs pin, not the released wheel.** The docs track +`main`, so a post-release file move (e.g. a sampler module becoming a package) +would false-fail against a pip release. The `wiki-currency` CI workflow therefore +shallow-clones the cited repos into `sources/` before running this as its fifth +leg — the release install stays the ground truth only for the symbol / version / +idiom checks. Run it alongside the symbol audit in every refresh +(`al_refresh_api_docs`) and before a release. ERRORs fail the check; warnings (unpinned `main`, unstamped legacy pages) do not unless `--strict`, so the release/PR check goes red on genuine forgery/staleness without nuking the From 04501b5d8deaa975bceb4ca049b6736ba019325a Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Thu, 9 Jul 2026 17:37:01 +0100 Subject: [PATCH 3/4] ci: sparse-checkout cone mode takes directories only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'sparse-checkout set scripts' — root-level catalogue files are included automatically in cone mode; passing llms.txt as a pattern was fatal. Co-Authored-By: Claude Fable 5 --- .github/workflows/wiki-currency.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/wiki-currency.yml b/.github/workflows/wiki-currency.yml index 712e472..96551fb 100644 --- a/.github/workflows/wiki-currency.yml +++ b/.github/workflows/wiki-currency.yml @@ -90,7 +90,9 @@ jobs: done git clone --quiet --depth 1 --filter=blob:none --sparse \ https://github.com/PyAutoLabs/autolens_workspace sources/autolens_workspace - git -C sources/autolens_workspace sparse-checkout set scripts llms.txt llms-full.txt workspace_index.json + # Cone mode: directories only; root-level files (llms.txt, llms-full.txt, + # workspace_index.json) are always included automatically. + git -C sources/autolens_workspace sparse-checkout set scripts - name: Run wiki-currency checks id: checks From 19d949b3892766f4d9e1bd2203462c308473d0cd Mon Sep 17 00:00:00 2001 From: Jammy2211 Date: Thu, 9 Jul 2026 17:40:35 +0100 Subject: [PATCH 4/4] docs: drop cites to modules removed on main (ultranest, pyswarms, quantity) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CI citations leg (grading against origin/main clones) caught what local sibling checkouts — behind main — could not: nest/ultranest/ and mle/pyswarms/ are deleted upstream, and autolens/quantity/ is archived to autolens_workspace_developer/legacy. searches.md prose already said the two samplers weren't public; now the dead Source cites and frontmatter paths are gone too. stack/autolens.md's Quantity API section becomes a Derived-quantities note pointing at Tracer methods + the workspace guides. Co-Authored-By: Claude Fable 5 --- wiki/core/api/searches.md | 16 +++++++--------- wiki/core/stack/autolens.md | 12 +++++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/wiki/core/api/searches.md b/wiki/core/api/searches.md index ee8c71f..0e269a7 100644 --- a/wiki/core/api/searches.md +++ b/wiki/core/api/searches.md @@ -5,11 +5,9 @@ sources: paths: - autofit/non_linear/search/nest/nautilus/ - autofit/non_linear/search/nest/dynesty/ - - autofit/non_linear/search/nest/ultranest/ - autofit/non_linear/search/mcmc/emcee/ - autofit/non_linear/search/mcmc/zeus/ - autofit/non_linear/search/mle/bfgs/ - - autofit/non_linear/search/mle/pyswarms/ - autofit/non_linear/search/mle/drawer/ pinned_commit: main last_updated: 2026-07-09 @@ -60,16 +58,15 @@ Reference: Speagle (2020), arXiv:1904.02180 — see ### UltraNest -UltraNest is not currently exposed as a public `autofit` search class in the -2026.5.29.4 stack. Prefer `af.Nautilus`, `af.DynestyStatic`, or -`af.DynestyDynamic` for nested-sampling runs. +UltraNest is not exposed as a public `autofit` search class, and its former +`nest/ultranest/` module has been removed from `main` entirely. Prefer +`af.Nautilus`, `af.DynestyStatic`, or `af.DynestyDynamic` for nested-sampling +runs. ```python af.Nautilus(path_prefix=..., name=..., n_live=200) ``` -Source: `PyAutoFit:autofit/non_linear/search/nest/ultranest/`. Optional dep. - Reference: Buchner — algorithmic foundation in [`wiki/literature/concepts/nested-sampling.md`](../../literature/concepts/nested-sampling.md) (Skilling 2006); UltraNest itself is documented at @@ -120,8 +117,9 @@ Source: `PyAutoFit:autofit/non_linear/search/mle/bfgs/`. ### Particle Swarm / MLE Searches -PySwarms is not currently exposed as a public `autofit` search class in the -2026.5.29.4 stack. Use the public MLE/debug searches instead. +PySwarms is not exposed as a public `autofit` search class, and its former +`mle/pyswarms/` module has been removed from `main` entirely. Use the public +MLE/debug searches instead. ```python af.LBFGS(path_prefix=..., name=...) diff --git a/wiki/core/stack/autolens.md b/wiki/core/stack/autolens.md index 87ea856..c13db72 100644 --- a/wiki/core/stack/autolens.md +++ b/wiki/core/stack/autolens.md @@ -7,7 +7,6 @@ sources: - autolens/imaging/model/ - autolens/interferometer/model/ - autolens/point/ - - autolens/quantity/ - README.md pinned_commit: main last_updated: 2026-07-09 @@ -95,11 +94,14 @@ See [`concepts/inversions_and_pixelizations`](../concepts/inversions_and_pixeliz Used for quasar lensing and time-delay cosmography. -## Quantity API +## Derived quantities -`autolens/quantity/` exposes objects for measuring derived lensing quantities — total -Einstein mass within a radius, projected enclosed mass, mass-to-light ratios — with -proper uncertainty propagation from the posterior. See +The former `autolens/quantity/` package has been archived (it lives on in +`autolens_workspace_developer/legacy`). Derived lensing quantities — Einstein +radius/mass, enclosed masses, magnifications — are computed from `Tracer` +methods and posterior samples directly; the workspace guides +(`autolens_workspace:scripts/guides/lens_calc.py`, `scripts/guides/units/`) are +the recipes. See [`concepts/samples_and_posteriors`](../concepts/samples_and_posteriors.md) and [`concepts/cosmology_and_units`](../concepts/cosmology_and_units.md).