Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion .github/workflows/wiki-currency.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,24 @@ 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
# 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
run: |
Expand Down Expand Up @@ -104,11 +122,14 @@ 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 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
run "Provenance (--check-provenance)" --check-provenance
run "Citation paths (--check-citations)" --check-citations

cat "$REPORT" >> "$GITHUB_STEP_SUMMARY"
if [ "$fail" -ne 0 ]; then
Expand Down
49 changes: 37 additions & 12 deletions autoassistant/audit_skill_apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/<project>/`, 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/<project>/` 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


Expand All @@ -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}")

Expand Down Expand Up @@ -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
Expand Down
20 changes: 15 additions & 5 deletions skills/al_audit_skill_apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,21 @@ 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
`` `<project>:<path>` `` 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/<project>/` → 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
page's frontmatter `sources[].paths[]`, and resolves every path against a source
tree of the cited project: a full checkout (installed-from-git →
`sources/<project>/` → 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
Expand Down
16 changes: 7 additions & 9 deletions wiki/core/api/searches.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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=...)
Expand Down
12 changes: 7 additions & 5 deletions wiki/core/stack/autolens.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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).

Expand Down
Loading