Metadata-Version: 2.4
Name: can-they-merge
Version: 0.1.0
Summary: Can these Python dependency sets merge into one environment? If not, into how few? Ships the `ctm` CLI, bringing its own uv + micromamba resolvers.
Project-URL: Homepage, https://github.com/DanielHou315/can-they-merge
Project-URL: Repository, https://github.com/DanielHou315/can-they-merge
Project-URL: Issues, https://github.com/DanielHou315/can-they-merge/issues
Author-email: Daniel Hou <danielhou315@gmail.com>
License: MIT
License-File: LICENSE
Keywords: conda,dependencies,environments,packaging,resolver,uv
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.9
Requires-Dist: tomli>=1.1.0; python_version < '3.11'
Provides-Extra: introspect
Requires-Dist: importlib-metadata>=4.6; (python_version < '3.10') and extra == 'introspect'
Requires-Dist: pyyaml>=6.0; extra == 'introspect'
Description-Content-Type: text/markdown

# can-they-merge (`ctm`)

**Can these Python dependency sets merge into one environment? And if not, into
how few?**

Researchers constantly stitch together frameworks, benchmarks, and baselines —
each with its own `requirements.txt`, `pyproject.toml`, or conda
`environment.yaml`. `ctm` answers two questions using *real* resolvers for
ground truth:

1. **`ctm merge`** — do all these inputs co-resolve into a single environment?
2. **`ctm partition`** — when they don't, what is the **minimum number of
   environments** needed to cover a set of components/entrypoints?

`ctm` is a small, pure-Python tool (3.9+) that **brings its own resolvers**: it
fetches pinned [`uv`](https://github.com/astral-sh/uv) (PyPI) and
[`micromamba`](https://mamba.readthedocs.io/) (conda) binaries on first use, so
you don't have to install or manage them.

## Install

```bash
pip install can-they-merge        # or: uv tool install can-they-merge
ctm setup                         # fetch the bundled uv + micromamba resolvers
```

`ctm setup` is optional — the resolvers are also fetched automatically on first
use. For **air-gapped clusters**, run `ctm setup` on a connected machine and
copy the cache dir, or pre-stage the binaries and install from them:

```bash
ctm setup --from-dir /path/to/prestaged/bin
# or point at an existing location:
export CTM_BIN_DIR=/shared/tools/ctm-bin
```

## Usage

### Can they merge?

```bash
ctm merge requirements.txt pyproject.toml environment.yaml
```

```
NOT MERGEABLE ✗  (target: pypi)
  - numpy: <1.20 & >=1.24
  resolver said:
    × No solution found... Because you require numpy<1.20 and numpy>=1.24...
```

- Mix formats freely (auto-detected by extension).
- `--target pypi` (default, uses `uv`) or `--target conda` (uses `micromamba`).
- `--json` for a machine-readable report. Exit codes: `0` mergeable, `1` not
  mergeable, `3` resolver unavailable.

### Minimum number of environments

Pass one dependency file per component:

```bash
ctm partition reqs-train.txt reqs-deploy.txt reqs-util.txt --exact
```

```
2 environment(s) needed [minimum]:
  env 1: reqs-deploy, reqs-util
  env 2: reqs-train
```

- `--exact` proves the count is the true minimum (branch-and-bound; ≤8
  components). Without it, a sound greedy partition is returned and labeled as
  not-proven-minimal.

## How it works

- **Ground truth from real resolvers.** `ctm merge` resolves the union with
  `uv`/`micromamba`; a pure-Python specifier pre-check supplies readable
  conflict explanations and catches obvious cases without a resolver call.
- **Partitioning** builds a conflict graph (no resolver calls), then a
  greedy-with-validation pass (every emitted environment is resolver-checked, so
  it's *sound*), with an optional exact branch-and-bound that memoizes every
  resolution to prove minimality.
- **Over-approximate reachability** (library: `can_they_merge.reachability`)
  statically maps entrypoints to the distributions they need, erring toward
  *including* a package rather than dropping it.

## Configuration

| Env var | Purpose |
|---|---|
| `CTM_BIN_DIR` | Where bundled binaries live (default: per-user cache) |
| `CTM_NO_FETCH=1` | Never auto-download; require `ctm setup` / PATH |
| `CTM_UV_VERSION`, `CTM_MICROMAMBA_VERSION` | Pin resolver versions |
| `CTM_UV_BASE_URL`, `CTM_MICROMAMBA_BASE_URL` | Mirror / offline sources |

## Development

```bash
uv sync
uv run pytest -q                 # unit tests, no network
uv run pytest -q -m integration  # drives real uv against verified fixtures
uv run ruff check src tests
```

Design spec: [`docs/superpowers/specs/2026-06-11-can-it-merge-design.md`](docs/superpowers/specs/2026-06-11-can-it-merge-design.md).

## License

MIT © Daniel Hou
