Skip to content
Merged
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
61 changes: 61 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# cw

A codec layer wiring a string-only environment (the command line) to a Python
function call: `argv -> Namespace -> (args, kwargs) -> f -> result -> stdout`.
The MIT-licensed, in-house replacement for `argh` (LGPL-3.0-or-later).

## Module map (`cw/`)

- `base.py` β€” bottom of the import graph: sentinels, errors, help rendering.
Everything else imports from here.
- `grammar.py` β€” **the riskiest, most opinionated module**: how a Python
signature becomes command-line arguments (reproduces argh 0.31.3's behavior
deliberately β€” see `docs/adr/0004-grammar-errata.md`).
- `ingress.py` β€” `Namespace -> (args, kwargs)`, honouring `/`, `*args`, `*`, `**kwargs`.
- `egress.py` β€” `result -> stdout lines + exit code` β€” a seam argh has **no
hook for at all**.
- `cli.py` β€” the argparse surface: build a parser, run one; produces a **plain**
`argparse.ArgumentParser`, never a subclass (so `argcomplete.autocomplete`
and other argparse-typed tools keep working).
- `commands.py` β€” turns an object (function, list, mapping, module, instance,
or `'pkg.mod:name'` string) into the `{name: callable}` tree a parser is
built from.
- `convention.py` β€” `cw`'s defaults, one frozen value per context.
- `resolution.py` β€” resolves function specs from various formats; `resource_inputs`
needs the `resource` extra (real `i2`, not the LGPL package cw replaces).
- `compat.py` β€” **deprecated from day one**: a transitional argh shim so a repo
can retire an `argh` dependency with a one-line import change.
- `testing.py` β€” record a CLI's behaviour before a migration, assert it after;
deliberately standalone (only stdlib imports β€” see D4 in the ADRs).

## Tests & lint (verified)

```bash
uv venv .venv && uv pip install -e ".[dev]"
.venv/bin/pytest -v --tb=short # 972 passed, 2 skipped, 1 environment-dependent failure (see gotcha)
.venv/bin/ruff check .
```
Or `wads ci-local` (`[tool.wads.ci.install].extras = "test"` β€” **required**: a
bare `uv pip install -e .` leaves `cw.resolution`'s i2-dependent tests/doctests
failing).

**Gotcha found verifying:** `tests/argh_parity/test_compat_parity.py::TestArgDeclarations::test_completer_reaches_the_action`
failed locally β€” it asserts on real `argh`'s own parser action gaining a
`.completer` attribute, which didn't happen in this environment (argh version/
`argcomplete` availability), not a `cw` bug. `tests/argh_parity/` is a
differential suite (cw vs. real argh) that self-skips when `argh` is absent;
`cw` itself never imports `argh` at runtime β€” `test_import_is_cheap.py` enforces
that import costs stdlib only.

## Docs

- `docs/adr/0001`-`0008`: the v1 seam table, ingress stash, merge ladder, grammar
errata, release/rollback policy, v1 cut list, what adversarial review changed,
no-fourth-channel-for-group-kwargs.

## Dependents

41 packages import `cw` (fleet dependency graph), including `appshelf`,
`astern`, `crowsnest`, `liaise`, `openloops`, `priv`, `wads` β€” see
`fleet_dependents.json` for the full list. Check dependents' CLI tests before
changing `grammar.py`, `ingress.py`, or `egress.py`'s public behaviour.
Loading