Skip to content

Commit 25804e8

Browse files
satraclaude
andcommitted
refactor(027)!: drop deprecation shims — hard cutover to abstractatlas/aacli
Per requester: no deprecation shims. Removes: - src/ohbm2026/__init__.py (the import meta-path shim) — `import ohbm2026` now raises ModuleNotFoundError. - the `ohbmcli` [project.scripts] entry + `_ohbmcli_deprecated_main` in cli.py — `ohbmcli` is now `command not found`. Also renames the remaining `ohbmcli` string literals in src (+ tests): argparse `prog=` (aacli --help now shows `usage: aacli`), provenance `command_line` strings, help/error text; and fixes a dynamic `__import__("ohbm2026")` in test_enrich_stage that the module-ref passes missed. Reinstalled the venv (uninstall ohbm2026 dist → install -e .) so a prior installed `ohbm2026` can't mask the cutover. Spec/plan/tasks/contracts (FR-003, SC-007, R3, rename-map, cli-aacli) + CLAUDE pointer updated to describe the hard cutover. Verified: full suite `Ran 1034 — OK (skipped=1)`; `import ohbm2026` → ModuleNotFoundError; `ohbmcli` → command not found; `aacli` works. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f25c0d0 commit 25804e8

34 files changed

Lines changed: 87 additions & 155 deletions

CLAUDE.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,10 @@ things: (1) **renames** the component `ohbm2026`→`abstractatlas` (package
175175
`src/ohbm2026/``src/abstractatlas/` via `git mv` + import rewrite across
176176
~86 files) and the CLI `ohbmcli`**`aacli`** (module form
177177
`python -m abstractatlas.cli`; legacy `ohbm-*` scripts→`aa-*` or dropped),
178-
with `ohbmcli`/`import ohbm2026` kept as **labeled deprecation shims** for
179-
one cycle; and (2) **generalizes ingestion** into a pluggable architecture —
178+
with `ohbmcli`/`import ohbm2026` **removed outright (hard cutover, no
179+
shims)** — they fail loudly (`command not found` / `ModuleNotFoundError`);
180+
the venv is reinstalled so a prior pip-installed `ohbm2026` dist doesn't
181+
mask it; and (2) **generalizes ingestion** into a pluggable architecture —
180182
a NEW `src/abstractatlas/ingest/` subpackage with an `Ingestor` ABC
181183
(`pull``normalize``validate`), a runtime-discoverable `registry`
182184
(never a hardcoded source list — CA-007), and a standardized **LinkML
@@ -199,7 +201,7 @@ fidelity. Companions: `research.md`, `data-model.md`,
199201
`contracts/{rename-map,ingestor-interface,ingest-schema.linkml.yaml,cli-aacli}.md`,
200202
`quickstart.md`. NOTE for future sessions: after this ships, the package is
201203
`abstractatlas` and the CLI is `aacli` — update muscle memory (`ohbmcli`
202-
still works via a deprecation shim slated for removal).
204+
and `import ohbm2026` are GONE; they error, no shim).
203205

204206
The immediately-prior Stage 26 plan is at
205207
`specs/026-neuroscape-year-density/plan.md`. Stage 26 (Track A,

pyproject.toml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,13 @@ abstracts_book = [
3939
]
4040

4141
[project.scripts]
42-
# Canonical CLI (spec 027: ohbmcli → aacli).
42+
# Canonical CLI (spec 027: ohbmcli → aacli). Hard cutover — no `ohbmcli`
43+
# alias and no `ohbm2026` import shim: the old names are removed and fail
44+
# loudly (command-not-found / ModuleNotFoundError). The legacy per-stage
45+
# `ohbm-*` console scripts were also dropped (most pointed at modules moved
46+
# in the Stage-5 reorg); their functions remain importable via
47+
# `abstractatlas.*` and runnable as `aacli` subcommands.
4348
aacli = "abstractatlas.cli:main"
44-
# Deprecated alias — warns then delegates to aacli. Kept one transition
45-
# cycle; remove next release. (Spec 027 FR-003 / research R3.)
46-
ohbmcli = "abstractatlas.cli:_ohbmcli_deprecated_main"
47-
# The legacy per-stage `ohbm-*` console scripts were dropped in spec 027:
48-
# most already pointed at modules moved in the Stage-5 reorg
49-
# (ohbm2026.enrichment, ohbm2026.openalex). Their functions remain
50-
# importable via `abstractatlas.*` and runnable as `aacli` subcommands.
5149

5250
[build-system]
5351
requires = ["setuptools>=69"]

specs/027-abstractatlas-rename-ingestors/contracts/cli-aacli.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ subcommand (SC-001).
3030
> surface that makes future sources first-class without new bespoke
3131
> subcommands.
3232
33-
## Deprecation
33+
## Hard cutover (no deprecation)
3434

35-
- `ohbmcli <args>`stderr: `ohbmcli is deprecated; use 'aacli'. Delegating…`
36-
then runs `aacli <args>`. Removed next cycle.
37-
- `python -m ohbm2026.cli` → shim module warns + delegates.
35+
- `ohbmcli`removed; `command not found`.
36+
- `import ohbm2026` / `python -m ohbm2026.cli``ModuleNotFoundError: No module named 'ohbm2026'`.
37+
- The sole interface is `aacli` / `python -m abstractatlas.cli`.
3838

3939
## Verification
4040

specs/027-abstractatlas-rename-ingestors/contracts/rename-map.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,17 @@ green) + SC-003 (byte-identical published data).
1717
| Docs | README, CLAUDE.md, constitution naming refs | updated to `abstractatlas`/`aacli` (FR-012) |
1818
| Site test strings | `ohbm2026` refs in `site/src/**` tests | updated where they name the package (NOT the `ohbm2026` data/site-mode/route which is the source identity) |
1919

20-
## Deprecated shims (one transition period)
20+
## Hard cutover — no shims (per requester)
2121

22-
| Legacy | Behavior |
23-
|--------|----------|
24-
| `ohbmcli` entry point | prints "renamed to `aacli`" deprecation notice, then delegates to `aacli` |
25-
| `import ohbm2026` | thin shim re-exporting `abstractatlas` with a `DeprecationWarning`; labeled + follow-up to remove |
22+
| Legacy | Behavior after cutover |
23+
|--------|------------------------|
24+
| `ohbmcli` | removed from `[project.scripts]``command not found: ohbmcli` |
25+
| `import ohbm2026` | package dir gone + venv reinstalled → `ModuleNotFoundError: No module named 'ohbm2026'` |
2626

27-
Shims MUST be labeled in code with root cause + removal follow-up
28-
(Constitution VI). Neither may partially work in a confusing way (FR-003).
27+
No deprecation shim is provided. Both fail loudly and immediately (FR-003 /
28+
SC-007) — never a silent or partial success. The venv is reinstalled
29+
(`uv pip uninstall ohbm2026 && uv pip install -e .`) so a previously
30+
pip-installed `ohbm2026` dist can't mask the cutover.
2931

3032
## NOT renamed (data identity — FR-004)
3133

specs/027-abstractatlas-rename-ingestors/research.md

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,22 @@ option) — rejected by the requester for continuity.
4343

4444
## R3 — Legacy name policy (`ohbmcli`, `import ohbm2026`)
4545

46-
**Decision**: `aacli` / `abstractatlas` are canonical. Provide a
47-
**deprecated shim** for one transition period: `ohbmcli` remains as an entry
48-
point that prints a clear "renamed to `aacli`" deprecation notice then
49-
delegates; `import ohbm2026` resolves via a thin shim module that re-exports
50-
`abstractatlas` with a `DeprecationWarning`. Both are labeled and slated for
51-
removal.
52-
53-
**Rationale**: Avoids silently breaking existing scripts/cron while making
54-
the new name canonical (FR-003, SC-007, edge case). A hard break is also
55-
acceptable per the spec, but a labeled shim is lower-friction and still
56-
loud. The shim carries a root-cause comment + follow-up per Constitution VI.
57-
58-
**Alternatives considered**: hard removal with an error — acceptable but
59-
more disruptive; chose the shim as the default, removable next cycle.
46+
**Decision (updated per requester): HARD CUTOVER — no deprecation shims.**
47+
`aacli` / `abstractatlas` are the sole names. The `ohbmcli` entry point and
48+
any `ohbm2026` import path are removed; using them fails loudly with the
49+
standard not-found error (`command not found: ohbmcli` /
50+
`ModuleNotFoundError: No module named 'ohbm2026'`). The venv is reinstalled
51+
(`uv pip uninstall ohbm2026 && uv pip install -e .`) so a previously
52+
pip-installed `ohbm2026` dist doesn't mask the cutover.
53+
54+
**Rationale**: The requester opted for a clean break — no shim to maintain
55+
or later remove. A bare not-found error is loud and unambiguous (satisfies
56+
FR-003/SC-007's "never silent/partial"), and there is no external
57+
consumer that needs a grace period.
58+
59+
**Alternatives considered**: a labeled deprecation shim (`ohbmcli` warns +
60+
delegates; `ohbm2026` meta-path redirect) — implemented first, then
61+
**removed** at the requester's direction in favour of the hard cutover.
6062

6163
## R4 — Ingestor contract: wrap, don't rewrite
6264

specs/027-abstractatlas-rename-ingestors/spec.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ error rather than silently passed downstream.
102102
### Edge Cases
103103

104104
- **Naming divergence for preserved data**: the package is `abstractatlas` but the published parquet keeps the name `ohbm2026.parquet` (that source's data name). The system must tolerate — and clearly document — this intentional divergence rather than "fix" the data name (which would force a re-publish).
105-
- **Legacy imports / command**: existing scripts, cron jobs, or muscle-memory using `ohbmcli` / `import ohbm2026` must fail with a clear pointer to the new name (or work via a clearly-labeled deprecated alias for one transition period), never a confusing partial success.
105+
- **Legacy imports / command**: existing scripts, cron jobs, or muscle-memory using `ohbmcli` / `import ohbm2026` fail loudly with the standard not-found error (hard cutover — the old names are removed), never a confusing partial success.
106106
- **State-keyed caches/checkpoints**: caches and checkpoints keyed by names that embed `ohbm2026` must remain readable so the rename does not silently invalidate expensive prior work.
107107
- **Source-type asymmetry**: a conference record has no DOI/journal; a literature record has no poster/session. The schema must make each set optional-by-source without letting a conference record masquerade as literature or vice versa.
108108
- **Two sources, one atlas**: an ingestor's records carry which source they came from, so downstream can attribute, filter, and de-duplicate across sources.
@@ -114,7 +114,7 @@ error rather than silently passed downstream.
114114

115115
- **FR-001**: The Python package MUST be renamed `ohbm2026``abstractatlas`, and all internal imports, references, and docs updated to the new name.
116116
- **FR-002**: The canonical CLI MUST be renamed `ohbmcli``aacli`; every existing subcommand MUST remain available with identical behavior and options.
117-
- **FR-003**: Legacy entry points (`ohbmcli`, `import ohbm2026`) MUST either be removed with a precise "renamed to …" error or provided as an explicitly-deprecated alias for one transition period; they MUST NOT partially work in a confusing way.
117+
- **FR-003**: Legacy entry points (`ohbmcli`, `import ohbm2026`) MUST be removed outright (hard cutover — no deprecation shims); using them MUST fail loudly with the standard not-found error (`command not found` / `ModuleNotFoundError: No module named 'ohbm2026'`), never partially work in a confusing way.
118118
- **FR-004**: Existing on-disk data artifact paths, artifact/state-key naming, cache/checkpoint keys, and published data-package names (including `ohbm2026.parquet`) MUST be preserved so no data is regenerated and the live site requires no re-publish (byte-identical data).
119119
- **FR-005**: Ingestion MUST be organized as a pluggable architecture: a common **ingestor contract** (pull records from a source → normalize) with a runtime-discoverable registry of named ingestors.
120120
- **FR-006**: The two existing sources — the OHBM conference (Oxford Abstracts) and the PubMed/NeuroScape corpus — MUST be ported to become the first two ingestor instances behind the common contract, each reproducing its former normalized output exactly.
@@ -153,13 +153,13 @@ error rather than silently passed downstream.
153153
- **SC-004**: Both existing sources are expressed as named ingestors behind the common contract; porting them changed **zero** lines of downstream stage logic (measured by the diff touching only ingestor + rename code).
154154
- **SC-005**: 100% of records emitted by each ingestor validate against the LinkML ingest schema; a deliberately malformed record is rejected with a precise, source-attributed error (0 malformed records reach downstream).
155155
- **SC-006**: A maintainer can onboard a new source by implementing only the ingestor contract + registering it, with no edits to downstream stages — demonstrated by a documented "add an ingestor" guide and the two ports as worked examples.
156-
- **SC-007**: Using a legacy name (`ohbmcli` / `import ohbm2026`) yields a clear rename pointer or a labeled-deprecated alias — never a silent or partial success.
156+
- **SC-007**: Using a legacy name (`ohbmcli` / `import ohbm2026`) fails loudly and immediately with the standard not-found error — never a silent or partial success. (Hard cutover: the old names are gone.)
157157

158158
## Assumptions
159159

160160
- "Foundation only": this change renames + establishes the ingestor architecture + LinkML ingest schema + ports the two existing sources. It does **not** add arXiv/bioRxiv/medRxiv or new-conference ingestors — those are follow-on specs enabled by this foundation.
161161
- Data continuity is paramount: on-disk artifact layout and published data-package names are preserved verbatim (including the historical `ohbm2026.parquet` name), so the rename is a code/CLI/package/docs change with no data regeneration or site re-publish.
162162
- The standardized LinkML ingest schema is designed to **capture the existing normalized shape** (so the ported OHBM output validates and downstream stays byte-identical), while being general enough to admit literature-index sources — it does not reshape already-published data.
163-
- A deprecated `ohbmcli` alias (and/or an `ohbm2026` import shim) may be provided for one transition period; the canonical, documented interface is `aacli` / `abstractatlas`.
163+
- Hard cutover: NO deprecation shims. `ohbmcli` and `import ohbm2026` are removed and fail loudly; the sole interface is `aacli` / `abstractatlas`. (The local venv must be reinstalled so a previously pip-installed `ohbm2026` dist is replaced by `abstractatlas`.)
164164
- Governance docs (constitution) contain naming references (`ohbmcli`, `src/ohbm2026/`, `data/abstracts.json`); updating those references is in scope for doc-sync, coordinated with the project's constitution-amendment process where required.
165165
- Downstream stages already treat the corpus generically enough that a standardized ingest contract can be introduced without changing their outputs for the existing sources.

specs/027-abstractatlas-rename-ingestors/tasks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ renamed package and must follow it. Sequence: Setup → baseline → US1 → US2
5757

5858
- [x] T003 [US1] `git mv src/ohbm2026 src/abstractatlas`, then rewrite `ohbm2026``abstractatlas` across all imports/refs in `src/` (per `contracts/rename-map.md`). Do NOT touch data-identity strings in the rename-map "NOT renamed" table (data paths, state-keys, `ohbm2026.parquet`, `/ohbm2026/` route, `SITE_MODE='ohbm'`, `OHBM2026_*`).
5959
- [x] T004 [US1] Update `pyproject.toml`: `name` `ohbm2026``abstractatlas`; `[project.scripts]` `ohbmcli``aacli = "abstractatlas.cli:main"`; rename `ohbm-*` entry points to `aa-*` where still used or drop them (record disposition per rename-map). Keep `package-dir`/`packages.find` under `src`.
60-
- [x] T005 [US1] Add labeled deprecation shims (FR-003, research R3): `ohbmcli` entry point that warns "renamed to aacli" then delegates; an `ohbm2026` import shim module re-exporting `abstractatlas` with a `DeprecationWarning`. Label both in code with root cause + removal follow-up (Constitution VI).
60+
- [x] T005 [US1] HARD CUTOVER — no deprecation shims (per requester). Remove the `ohbmcli` entry point (pyproject keeps only `aacli`), the legacy `ohbm-*` scripts, and rename all `ohbmcli` string literals in `src/` (argparse `prog=`, provenance `command_line`, help/error text) → `aacli`. Reinstall the venv package so a previously pip-installed `ohbm2026` dist is replaced by `abstractatlas` (`uv pip uninstall ohbm2026 && uv pip install -e .`), so `import ohbm2026` fails with `ModuleNotFoundError` and `ohbmcli` is `command not found` (FR-003/SC-007).
6161
- [x] T006 [P] [US1] Rewrite `ohbm2026``abstractatlas` imports/refs across `tests/` and `scripts/`; update `PYTHONPATH=src -m ohbm2026.cli``-m abstractatlas.cli` in scripts + `.github/workflows/**` + `.githooks/`.
6262
- [x] T007 [P] [US1] Update the few `ohbm2026` string refs in `site/src/**` tests that name the PACKAGE (not the `ohbm2026` data/route/site-mode identity). — VERIFIED NO-OP: audited `site/src` — every `ohbm2026` ref is data/route/storage-key identity (`/ohbm2026/` routes, `ohbm2026.parquet`, `ohbm2026.ui.*`/`ohbm2026.analytics.*` localStorage keys, conference `kind`); the TypeScript site never imports the Python package, so nothing to rename (2 stale comment path-mentions left as historical, like the src ones).
6363
- [x] T008 [US1] Verify the rename: `PYTHONPATH=src .venv/bin/python -m unittest discover -s tests` fully green (SC-002); re-run the T002 fixture under `aacli` and diff artifacts — identical (SC-001); `ohbmcli`/`import ohbm2026` emit the labeled deprecation and still succeed (SC-007); confirm an existing `data/cache/**` (or checkpoint) entry created before the rename is still discovered/reused — no forced recompute from the name change (Constitution III / spec edge case); `git grep -n 'ohbm2026\|ohbmcli'` returns only intentional data-identity names, shims, and historical spec docs.

src/abstractatlas/analyze/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
- `analyze.umap` — Stage 4 UMAP fit + `project_into_umap` (US2).
2424
- `analyze.rollup` — Canonical UI rollup writer (annotations.parquet
2525
+ sqlite).
26-
- `analyze.stage` — Stage 4 orchestrator (`ohbmcli analyze-matrix`).
26+
- `analyze.stage` — Stage 4 orchestrator (`aacli analyze-matrix`).
2727
2828
**No package-level re-exports.** Per spec clarification Session
2929
2026-05-15 Q2, every caller imports from the explicit submodule that

src/abstractatlas/analyze/stage.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Stage 4 orchestrator — `ohbmcli analyze-matrix`.
1+
"""Stage 4 orchestrator — `aacli analyze-matrix`.
22
33
Iterates the `(model, input_source, analysis_kind)` matrix, dispatches
44
to per-kind runners, writes per-bundle artifacts atomically, and emits
@@ -7,7 +7,7 @@
77
88
Per spec FR-001 / FR-002 / FR-003 / FR-014 / FR-017:
99
10-
- Single canonical CLI entrypoint (`ohbmcli analyze-matrix`).
10+
- Single canonical CLI entrypoint (`aacli analyze-matrix`).
1111
- Default matrix is **34 bundles** (5 models × 2 inputs × 4 kinds, with
1212
`neuroscape_clusters` auto-skipped for minilm/openai/pubmedbert
1313
because the published Stage-2 lens is Voyage-dim-specific).
@@ -365,7 +365,7 @@ def _run_entries_parallel(
365365
# internal thread pool should be 1. Setting these env vars BEFORE
366366
# the `Parallel` call ensures the loky-spawned subprocesses inherit
367367
# them. Existing user-set values win (the explicit env-var prefix
368-
# `OMP_NUM_THREADS=N PYTHONPATH=src ohbmcli …` still applies).
368+
# `OMP_NUM_THREADS=N PYTHONPATH=src aacli …` still applies).
369369
if config.n_jobs != 1:
370370
for var in (
371371
"OMP_NUM_THREADS",
@@ -594,7 +594,7 @@ def _git_rev_parse_head() -> str:
594594

595595
def build_parser() -> argparse.ArgumentParser:
596596
p = argparse.ArgumentParser(
597-
prog="ohbmcli analyze-matrix",
597+
prog="aacli analyze-matrix",
598598
description="Stage 4 canonical analysis & annotation matrix.",
599599
)
600600
p.add_argument("--env-file", type=Path, default=Path(".env"))
@@ -692,7 +692,7 @@ def main(argv: list[str] | None = None) -> int:
692692
sqlite_path=args.rollup_path.with_suffix(".sqlite") if args.rollup_path else None,
693693
neuroscape_centroids_dir=args.neuroscape_centroids,
694694
code_revision=args.code_revision or _git_rev_parse_head(),
695-
command_line=" ".join(sys.argv if argv is None else ["ohbmcli", "analyze-matrix"] + list(argv)),
695+
command_line=" ".join(sys.argv if argv is None else ["aacli", "analyze-matrix"] + list(argv)),
696696
env_file=args.env_file,
697697
dry_run=args.dry_run,
698698
n_jobs=args.n_jobs,

src/abstractatlas/atlas_hosting/cli.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
``contracts/cli-upload-atlas-package.md`` +
55
``contracts/cli-compare-data-hosting.md``.
66
7-
Each subcommand exposes a ``build_*_parser`` (the top-level ``ohbmcli``
7+
Each subcommand exposes a ``build_*_parser`` (the top-level ``aacli``
88
copies its actions in) and a ``*_main`` argv entry point returning the
99
documented exit code. Typed Stage-20 failures map to distinct non-zero
1010
codes; secrets are never echoed.
@@ -40,7 +40,7 @@
4040

4141
def build_upload_parser() -> argparse.ArgumentParser:
4242
parser = argparse.ArgumentParser(
43-
prog="ohbmcli upload-atlas-package",
43+
prog="aacli upload-atlas-package",
4444
description=(
4545
"Upload a built atlas-package's parquets to Cloudflare R2 under "
4646
"content-addressed, immutable keys; emit a registry channel entry "
@@ -89,7 +89,7 @@ def upload_main(argv: list[str] | None = None) -> int:
8989
parser = build_upload_parser()
9090
args = parser.parse_args(argv)
9191

92-
command_line = " ".join(["ohbmcli", "upload-atlas-package", *(argv or sys.argv[1:])])
92+
command_line = " ".join(["aacli", "upload-atlas-package", *(argv or sys.argv[1:])])
9393

9494
try:
9595
settings = r2_client.load_settings(args.env_file)
@@ -117,7 +117,7 @@ def upload_main(argv: list[str] | None = None) -> int:
117117

118118
def build_compare_parser() -> argparse.ArgumentParser:
119119
parser = argparse.ArgumentParser(
120-
prog="ohbmcli compare-data-hosting",
120+
prog="aacli compare-data-hosting",
121121
description=(
122122
"Probe the Dropbox- and R2-served copies of each artifact for "
123123
"byte-parity, HTTP Range support, and CORS; write a pass/fail report."

0 commit comments

Comments
 (0)