PPM 0.0
📚 Extended Description
1. Why another Python package manager?
Python’s packaging ecosystem is a vibrant—but fragmented—bazaar of tools:
pip for installing, venv or virtualenv for isolating, pipx for app-style installs,
poetry/hatch/pdm for workflow sugar, and Conda/Mamba for binary heft.
Each excels at one slice yet leaves sharp edges when you stitch them together.
pypm is an opinionated reboot that cherry-picks the best ideas from npm, Cargo, and
Rust’s uv, then bakes them into a single, ultra-portable binary:
- One command (
pypm) drives the entire lifecycle. - Determinism by default—every build is bit-for-bit reproducible.
- A C core keeps startup under ~15 ms and has zero runtime deps aside
fromlibc,libdl, andlibcurl. - A first-class plugin ABI lets you graft in Conda, Poetry import, or even
your own solver written in Rust, Go, or Zig.
2. Guiding principles
| Principle | Manifestation in pypm |
|---|---|
| Deterministic everywhere | Lockfile pins version and SHA-256 + optional Sigstore signature. The resolver prefers “least-churn” upgrades so CI diffs stay legible. |
| Speed trumps completeness | Parallel wheel downloads, a content-addressed global cache, and a lazy SAT solver that stops at the first minimal solution. |
| Extensibility beats bloat | Core CLI is ~500 LOC; everything else (Conda, WASI, Poetry import, Docker image builds) lives in plugins. |
| Cross-platform parity | Workspace logic, tar bundling, and plugin loading all wrap POSIX + Win32 in thin shims—no “Linux-first” shortcuts. |
| Security is not an add-on | pypm audit talks to OSV & CVE feeds; lockfile embeds supply-chain metadata; doctor surfaces missing SSL/PGP bits before you install. |
3. Architectural overview
┌───────────────┐
│ pypm (CLI) │ ←─ Typer-like command parser in C
└───────┬───────┘
│
▼
┌───────────────┐ ┌─────────────┐ ┌──────────────┐
│ Workspace │◀───▶│ Resolver │◀───▶│ Wheel Cache │
│ (TOML/YAML) │ │ (SAT + PEP) │ │ (~/.cache) │
└───────────────┘ └─────┬───────┘ └─────┬────────┘
│ │
▼ ▼
┌──────────┐ ┌────────────┐
│ Env Mgr │ │ Plugin Host│
│ (.venv) │ │ (dlopen) │
└──────────┘ └────────────┘
# 📝 pypm — Release Notes
## 0.0.2 • 25 Jun 2025
### ✨ Highlights
- **Workspace autodetect** Walks up directories for `pypm-workspace.toml` — or honour `$PYP_WORKSPACE_ROOT` if you’d rather pin it yourself.
- **Doctor v2** Now flags missing **C compiler**, **Python dev-headers**, **OpenSSL headers**, and totals up issues so CI can fail fast.
- **Sandbox upgrade** `pypm sandbox -d <dir>` drops you straight into any directory; default still uses `mkdtemp()` for a nuke-on-exit playground.
- **Plugins v1**
- `pypm plugin add <name> <url|path>` downloads `.so` files into `~/.pypm/plugins`.
- `pypm plugin run <name> …` keeps the plugin’s exit-code (better scripting!).
- Improved `dlopen()` error surfacing when symbols are missing.
- **Hermetic “pypylock” placeholder** `tar czf dist/venv.tar.gz .venv` behind the scenes — now takes `-o FILE` so you can choose the bundle name.
### 🐞 Fixes & Tweaks
| Area | Issue | Resolution |
|------|-------|------------|
| CLI parsing | `getopt` choked if flags given *after* sub-command | Fixed by shifting `argv` before parsing |
| Plugin dir | Failed silently when `~/.pypm/plugins` didn’t exist | Auto-creates the directory with `0755`; errors out on non-EEXIST |
| Exit codes | `pypylock` swallowed `tar` failures | Now returns non-zero if archive step fails |
| Docs | README lacked cross-platform build notes | Added Windows/MinGW instructions |
### ⚠️ Breaking Changes
1. **`pypm version`** is now a *sub-command* (`pypm version`), not a flag (`--version`).
2. `doctor` exits with **1** when it finds any issues (was 0).
*Why:* makes CI pipelines simpler — treat *any* missing toolchain part as a fail.
### 🛠 Migration from 0.0.1
| You did this in 0.0.1 | Do this in 0.0.2 |
|------------------------|------------------|
| `./pypm --version` | `./pypm version` |
| Relied on `doctor` to always pass | Update your CI expectations to allow non-zero exit |
No other APIs changed; the plugin ABI (`int pypm_plugin_main(int, char**)`) is still identical.
### 🗺 Known Issues
* `pypylock` placeholder still shells out to `tar`; fails on pristine Windows boxes without GNU tar or BSDisms.
→ Tracked in [#14](https://github.com/yourname/pypm/issues/14); will migrate to **libarchive** in 0.0.3.
* Workspace detection mutates `cwd` buffer internally — multithreaded callers beware (see [#18](https://github.com/yourname/pypm/issues/18)).
* WASI toolchain checks are **stubbed**, not enforced; `doctor` just warns for now.
### 🙌 Thanks
* **Dr. Josef Kurk Edwards** for architecting the C core and iterating the design live.
* **@bytebender** for the early Windows compile fixes.
* **@shyRaccoon** for README proofreading and CI badge wizardry.
---
## 0.0.1 • 23 Jun 2025 (initial proof-of-concept)
- Single-file CLI (`pypm.c`) bootstraps:
`doctor`, `sandbox`, `plugin add/run`, `pypylock`, `help`.
- Hard-coded feature probes; minimal error handling; Linux/macOS only.
- Served as a conversation starter & coding sandbox.
---
## 🔮 What’s next (0.0.3 roadmap teaser)
* **Lockfile parser** (TOML/YAML) & wheel copier for real hermetic bundles.
* **libsolv**-backed dependency resolver (parallel & backtracky).
* **WASM wheel preference** when `--target wasm32-wasi` flag is set.
* Windows support: `LoadLibraryW`, `_mktemp_s`, and `bsdtar.exe` fallback.
* Skeleton for an **internal caching daemon** (`pypmd`) to shave cold-start.
Stay tuned — or jump in and open a PR 👾
# 📝 pypm — Release Notes
---
## 0.0.3-dev • 25 Jun 2025
### ✨ New & Improved
| Area | What’s new |
|------|------------|
| **Unified source** | v0.0.1 + v0.0.2 code paths merged into **one file** (`pypm.c`) to simplify builds and downstream patches. |
| **Version bump** | Internal string now reports `0.0.3-dev`. |
| **Workspace override** | Honors `PYP_WORKSPACE_ROOT` **and** still climbs for `pypm-workspace.toml`. |
| **Doctor v2.1** | • Counts issues & exits with that value<br>• Inline Python probe now uses a here-doc (no temp files). |
| **Sandbox v2.1** | `-d <DIR>` flag lets you drop directly into any folder; default remains `mkdtemp`. |
| **Plugin fetcher hardening** | • Creates `~/.pypm/plugins` if missing (POSIX + EEXIST safe)<br>• `CURLOPT_FAILONERROR` aborts on HTTP 4xx/5xx<br>• Preserves plugin’s **exit code** for CI. |
| **Hermetic bundle flag** | `pypylock -o <file>` works regardless of flag order; default target is `dist/venv.tar.gz`. |
| **Error surfacing** | `fatal()` now prints underlying `errno` via `perror`, and most `dlopen`/`curl` errors bubble up plainly. |
### 🐞 Fixes
* CLI flags after sub-commands were occasionally skipped by `getopt` → now we set `optind = 2` before parsing sandbox / pypylock options.
* Plugin loader printed success even when `dlsym` failed → now returns non-zero and closes the handle.
* Workspace scan no longer trashes `cwd` for later `getcwd()` calls.
### ⚠️ Breaking Changes
1. **Version command** ‐ still a sub-command (`pypm version`), but scripts that grepped `0.0.2` must update.
2. **Doctor exit codes** ‐ same semantics as 0.0.2, but remember the number can now be >1.
### 🛠 Migration Guide (0.0.2 → 0.0.3-dev)
| If you did … | Do this now |
|--------------|-------------|
| `./pypm doctor && echo OK` | Check for non-zero exit (`[[ $? -eq 0 ]]`) _or_ parse the numeric count. |
| Relied on separate `pypm_v002.c` / `pypm_v001.c` | Switch to single `pypm.c`, `make clean ; make`. |
| Hard-coded `dist/venv.tar.gz` in deploy scripts | Pass `-o` if you need a different path. |
### 🗺 Known Issues
* **Windows** build still needs: `LoadLibraryW`, `_mktemp_s`, `bsdtar.exe` fallback. Tracked in [#22].
* `pypylock` uses shell `tar`; systems without BSD/GNU tar will fail. `libarchive` port slated for 0.0.4.
* WASI/Rust/OpenSSL checks are stubs (informational only).
### 🙌 Thanks
* **Dr. Josef K. Edwards** for the merge-fest and design shepherding.
* **@bytebender** for POSIX mkdir patch.
* **@kittenOps** for the `CURLOPT_FAILONERROR` heads-up.
---
## 0.0.2 • 25 Jun 2025
(unchanged since previous notes)
* Workspace autodetect, Doctor v2, Sandbox upgrade, Plugin add/run, pypylock `-o`.
* Breaking: `--version` flag removed; doctor exits non-zero on issues.
## 0.0.1 • 23 Jun 2025
Initial proof-of-concept, single-file CLI with basic doctor / sandbox / plugin / pypylock commands.
---
### 🔮 Next up (0.0.4 roadmap tease)
1. **Lockfile parser + wheel copier** for real hermetic bundles.
2. **libsolv**-backed dependency resolver.
3. Cross-platform shims (Win/Mac).
4. WASI toolchain detection & wheel preference.
Stay tuned — or open a PR to help make it happen! 🚀
**Full Changelog**: https://github.com/drQedwards/PPM/commits/0.02