From c89e2c7385f47141f3255de61861163b8a5f233b Mon Sep 17 00:00:00 2001 From: B-Deprez Date: Fri, 18 Sep 2026 15:51:52 +0200 Subject: [PATCH] Phase 5: prepare the 0.1.0 release as garg-aml-smurfing --- CITATION.cff | 2 +- CONTRIBUTING.md | 5 +++-- README.md | 10 ++++++---- docs/decisions/0006-no-torch-dependency.md | 2 +- docs/index.md | 6 ++++-- docs/install.md | 10 +++++----- docs/reproducing.md | 2 +- mkdocs.yml | 2 +- pyproject.toml | 2 +- src/garg_aml/__init__.py | 3 ++- src/garg_aml/api.py | 5 +++-- 11 files changed, 28 insertions(+), 21 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 593735f..d57f3d9 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,5 +1,5 @@ cff-version: 1.2.0 -title: garg-aml +title: garg-aml-smurfing message: >- If you use this software, please cite both the software and the paper it implements. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5aa5a33..2bcabfc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,7 +72,8 @@ registered with: | Field | Value | |---|---| | Owner | `VerbekeLab` | -| Repository | `garg-aml` | +| Repository | `garg-aml` (the GitHub repo) | +| PyPI project | `garg-aml-smurfing` | | Workflow | `release.yml` | | Environment | `release` | @@ -99,7 +100,7 @@ confirm it works with nothing else present. ### If you cannot publish to PyPI -The `garg-aml` name has a single owner. If that account is unreachable, the code +The `garg-aml-smurfing` name has a single owner. If that account is unreachable, the code is still safe — it lives in the `VerbekeLab` organisation — but the name is not reclaimable quickly. Publish under a new name instead: change `name` in `pyproject.toml`, register Trusted Publishing for the new project, and release diff --git a/README.md b/README.md index 3c26844..14363ba 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# garg-aml +# GARG-AML Graph-based detection of **smurfing** patterns in transaction networks. @@ -9,16 +9,18 @@ are empty and whose off-diagonal parts are dense. GARG-AML scores every account by exactly that contrast — one number in [-1, 1], computed from local structure alone, with no training and no labels. -[![PyPI](https://img.shields.io/pypi/v/garg-aml.svg)](https://pypi.org/project/garg-aml/) -[![Python](https://img.shields.io/pypi/pyversions/garg-aml.svg)](https://pypi.org/project/garg-aml/) +[![PyPI](https://img.shields.io/pypi/v/garg-aml-smurfing.svg)](https://pypi.org/project/garg-aml-smurfing/) +[![Python](https://img.shields.io/pypi/pyversions/garg-aml-smurfing.svg)](https://pypi.org/project/garg-aml-smurfing/) [![License: MIT](https://img.shields.io/badge/License-MIT-orange.svg)](LICENSE) ## Install ```bash -pip install garg-aml +pip install garg-aml-smurfing ``` +> Installed as **`garg-aml-smurfing`**, imported as **`garg_aml`**. The shorter name was already taken on PyPI by an unrelated project. + ## Use ```python diff --git a/docs/decisions/0006-no-torch-dependency.md b/docs/decisions/0006-no-torch-dependency.md index 7e339f0..2744891 100644 --- a/docs/decisions/0006-no-torch-dependency.md +++ b/docs/decisions/0006-no-torch-dependency.md @@ -8,7 +8,7 @@ needs `torch` and `torch-geometric`. That baseline lives in the research repository. **Why.** GARG-AML computes a closed-form structural score; nothing in it learns. -A practitioner evaluating it should be able to `pip install garg-aml` and get a +A practitioner evaluating it should be able to `pip install garg-aml-smurfing` and get a handful of megabytes. Pulling a deep-learning stack behind an unrelated score would cost adoption for no functional gain, and would make the package unusable in the locked-down environments where compliance teams work. diff --git a/docs/index.md b/docs/index.md index 3d58dfd..06fae19 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,12 +1,14 @@ -# garg-aml +# GARG-AML Find **smurfing** in a transaction network: one score per account, computed from local structure, with nothing to train and no labels required. ```bash -pip install garg-aml +pip install garg-aml-smurfing ``` +> Installed as **`garg-aml-smurfing`**, imported as **`garg_aml`**. The shorter name was already taken on PyPI by an unrelated project. + ```python import garg_aml as ga diff --git a/docs/install.md b/docs/install.md index 445a211..72a088e 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,7 +1,7 @@ # Installation ```bash -pip install garg-aml +pip install garg-aml-smurfing ``` Python 3.10 or newer. The core depends only on numpy, pandas, networkx and @@ -11,11 +11,11 @@ scipy — no deep-learning stack, nothing that needs compiling. | Extra | Install | What it adds | |---|---|---| -| `progress` | `pip install 'garg-aml[progress]'` | `progress=True` progress bars (tqdm) | -| `parallel` | `pip install 'garg-aml[parallel]'` | `n_jobs` other than 1 (joblib) | -| `sklearn` | `pip install 'garg-aml[sklearn]'` | the `GargAmlScorer` estimator | +| `progress` | `pip install 'garg-aml-smurfing[progress]'` | `progress=True` progress bars (tqdm) | +| `parallel` | `pip install 'garg-aml-smurfing[parallel]'` | `n_jobs` other than 1 (joblib) | +| `sklearn` | `pip install 'garg-aml-smurfing[sklearn]'` | the `GargAmlScorer` estimator | -Ask for several at once with `pip install 'garg-aml[progress,parallel]'`. +Ask for several at once with `pip install 'garg-aml-smurfing[progress,parallel]'`. Each is genuinely optional: the package imports and scores without any of them, and reaching for a feature you have not installed raises an error that names the diff --git a/docs/reproducing.md b/docs/reproducing.md index 16c0aa0..1db5cf2 100644 --- a/docs/reproducing.md +++ b/docs/reproducing.md @@ -33,7 +33,7 @@ only through a function no experiment called. It is not ported. See Pin an exact version when reproducing published numbers: ```bash -pip install garg-aml==0.1.0 +pip install garg-aml-smurfing==0.1.0 ``` Each release is tagged in the repository and archived with a DOI, so a paper can diff --git a/mkdocs.yml b/mkdocs.yml index 3c4c2bf..d8bfefd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,4 +1,4 @@ -site_name: garg-aml +site_name: GARG-AML site_description: Graph-based detection of smurfing patterns in transaction networks repo_url: https://github.com/VerbekeLab/garg-aml edit_uri: edit/main/docs/ diff --git a/pyproject.toml b/pyproject.toml index b1f5b56..cbac61f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ requires = ["hatchling>=1.27"] build-backend = "hatchling.build" [project] -name = "garg-aml" +name = "garg-aml-smurfing" dynamic = ["version"] description = "Graph-based detection of smurfing patterns in transaction networks." readme = "README.md" diff --git a/src/garg_aml/__init__.py b/src/garg_aml/__init__.py index 8ab9e8e..3a35e8d 100644 --- a/src/garg_aml/__init__.py +++ b/src/garg_aml/__init__.py @@ -74,7 +74,8 @@ def __getattr__(name: str) -> Any: from .estimator import GargAmlScorer except ImportError as exc: # pragma: no cover - depends on the environment raise ImportError( - "GargAmlScorer needs scikit-learn: pip install 'garg-aml[sklearn]'" + "GargAmlScorer needs scikit-learn: " + "pip install 'garg-aml-smurfing[sklearn]'" ) from exc return GargAmlScorer raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/garg_aml/api.py b/src/garg_aml/api.py index f87ae07..8d5aecf 100644 --- a/src/garg_aml/api.py +++ b/src/garg_aml/api.py @@ -26,7 +26,7 @@ def _progress(nodes: list, show: bool) -> Iterable: from tqdm import tqdm except ImportError as exc: # pragma: no cover - depends on the environment raise ImportError( - "progress=True needs tqdm: pip install 'garg-aml[progress]'" + "progress=True needs tqdm: pip install 'garg-aml-smurfing[progress]'" ) from exc return tqdm(nodes) @@ -56,7 +56,8 @@ def measure(node: Hashable) -> tuple[float, ...]: from joblib import Parallel, delayed except ImportError as exc: # pragma: no cover - depends on the environment raise ImportError( - "n_jobs other than 1 needs joblib: pip install 'garg-aml[parallel]'" + "n_jobs other than 1 needs joblib: " + "pip install 'garg-aml-smurfing[parallel]'" ) from exc # Each worker receives its own copy of the graph, so the memory cost scales