Skip to content

Fleet migration ledger — 60 repos, by wave #30

Description

@thorwhalen

The single tracking table for the argh→cw programme. Every column was re-verified against real source and the fleet dataset; corrections to earlier drafts are marked [C].

Legend — argh dep: declared in packaging metadata. i2: declares i2. tests: argv-level tests that exercise the dispatcher (⚠ = a test_cli.py exists but calls the functions as plain Python and would pass with the parser deleted — a false green, worse than no tests).


Rollup

verdict repos commands
cw 34 ~380
argparse-inline 3 12
drop-cli (delete the block, keep the repo, drop the dep) 11 21
dead-or-example 11 22
already-migrated (an → typer) 1 17
Total distinct 60

Test coverage is the cost, not the code. Of the 34 cw-bound repos, 8 have argv-level dispatcher tests (xa, opsward, coact, skill, lacing, illustration, grub, ocracy). 26 do not. Two more (enlace_auth, reelee) have the false green described above.


Two verified ordering traps — do not split either pair

1. cw + theremin. cw/pyproject.toml:17 declares argh and imports it nowhere. theremin/pyproject.toml:35-43 declares dol, i2, cw, meshed, opencv-python, hum, mediapipe — no argh — while theremin/main.py:25 and theremin/script_utils.py:12 both import it at module scope. Deleting cw's line breaks theremin's console script.

Resolution adopted: theremin declares argh explicitly first (one line, and a genuine packaging-bug fix), which decouples them — cw's deletion then lands immediately, unblocked by cw's own build. theremin's argh line dies at its own migration.

2. wads + isee. wads/pyproject.toml:21 declares argh in core deps. isee/pyproject.toml:13 declares ["semver==2.13.0", "wads", "tomli…"] — no argh — and isee/__init__.py:37 imports argh inside main(), which is the console script isee = "isee:main". isee free-rides on wads. Splitting them kills isee's console script in every CI job that calls isee, and 8 GitHub Action YAMLs invoke isee <cmd> by name.


Wave 0 — cw itself

repo pkg cmds entry point argh dep i2 tests effort
i2mint/cw cw 0 none ✅ unused ✅ ✗ trivial
thorwhalen/theremin theremin 1 theremin.main:dispatched_theremin_cli ✗ via cw ✅ ✗ medium

theremin is the fleet's heaviest per-parameter-override user: 10 @argh.arg decorators (script_utils.py:378-425), nargs='?' const='list' on five parameters, explicit short flags -p -s -k -v -r -n -w. It is the stress test for cw's override channel — and the worst possible repo to prove the API on, which is why cw's parity corpus must not consist of it alone.

Wave 0b — deletion track (23 repos, no cw, no design decisions)

See the deletion-track issues. [C] the set is 23 distinct repos, not 22 (the earlier list already de-duplicated the two checkouts of i2mint/taped and still names 23). [C] the edit is ~200 lines, not ~40 (ten files alone account for 143). [C] 11 argh declarations come off, 9 of them from PyPI-published distributions (oui, scoopy, odus, wealth, brand, loopyng, pipoke, mood, cw); projreg and glossa-data-prep are unpublished.

Wave 1 — pilots with pre-existing subprocess test suites

repo pkg cmds entry point argh dep i2 tests effort
thorwhalen/opsward opsward 6 opsward.__main__:main ✅ ✗ ✅ trivial
thorwhalen/grub grub 1 grub.cli:main ✅ ✗ ✅ trivial
thorwhalen/ocracy ocracy 10 ocracy.__main__:main extra [cli] ✗ ✅ trivial
thorwhalen/coact coact 11 coact.__main__:main ✅ ✗ ✅ small
thorwhalen/xa xa 13 xa.cli:main ✅ ✗ ✅ medium

These five are the only repos whose CLI contract is already pinned by tests somebody else wrote. Four different shapes: single-command (grub), optional-[cli]-extra over a dep-free core (ocracy), three distinct nargs shapes + a test that monkeypatches argh's module object (coact tests/test_cli.py:162), and namespaces with a leaf-name collision (xa: list at top level and inside the archive group).

[C] xa has 13 func.__name__ mutations, not 9 — xa/cli.py:783-792 (ten, including the non-identifier "gen-secret" at :792) plus :794-796 (three archive handlers). All 13 are deletable via a {name: func} mapping form.

Wave 2 — load-bearing tooling

repo pkg cmds entry point argh dep i2 tests effort
thorwhalen/skill skill 10 skill.__main__:main ✅ ✗ ✅ small
i2mint/epythet epythet 6 epythet.cli:epythet_cli ✅ ✗ ✗ small
i2mint/wads wads 17 pack, populate ✅ ✗ ⚠ medium
i2mint/isee isee 9 isee:main ✗ undeclared ✗ ⚠ small

epythet has the highest blast radius in the fleet: actions/publish-github-pages/action.yml:54 runs epythet quickstart . --ignore ${{inputs.ignore}} in every fleet docs job, with no default — so --ignore arrives with zero values and only parses because of nargs='*'. Zero test files in the repo. The action installs from PyPI, so a migration reaches CI only after a release.

wads step 0 is a deletion: wads/__init__.py:98 main() is dead and broken — it calls parser.add_commands(**pack_kw) where pack_kw carries namespace= (renamed to group_name in argh 0.30, so it raises TypeError), it is not among the package's 8 console scripts, and there is no wads/__main__.py. Delete it; do not port it. wads also holds the fleet's only non-dispatch argh API: argh.interaction.confirm at wads/pack.py:219.

Wave 3 — the house twins and the convention docs

repo pkg cmds entry point argh dep i2 tests effort
i2mint/reci reci 4 reci.__main__:main ✅ ✗ ✗ trivial
thorwhalen/illustration illustration 5 illustration.__main__:main ✅ ✗ ✅ trivial
thorwhalen/article article 2 article.__main__:main ✅ ✗ ✗ trivial
thorwhalen/ke ke 6 ke.__main__:main ✅ ✗ ✗ trivial
thorwhalen/ek ek 9 ek.__main__:main ✅ ✗ ✗ small
thorwhalen/toolery toolery 8 toolery.__main__:main ✅ ✗ ✗ small
thorwhalen/hedger hedger 11 hedger.__main__:main ✅ ✗ ✗ small
thorwhalen/scribed scribed 10 scribed.__main__:main extra [cli] ✗ ✗ small
thorwhalen/hearing hearing 6 hearing.cli:main ✅ ✗ ✗ small
thorwhalen/lacing lacing 5 lacing.cli:main ✅ ✗ ✅ small

ek must land its argh removal in the same PR as the _GPL_ALLOW inversion (.github/scripts/check_licenses.py:34 — [C] not :29) or master goes red. hearing migrates with scribed (it depends on it). lacing is the ingress-codec exemplar: lacing/cli.py:249-253 hand-writes int() with the comment "argh delivers option values as strings; coerce here" — and the same bug is still live and unpatched at cli.py:118-120 for --start/--end. reci's own misc/docs/*.md prescribe argh by name; rewrite them or the pattern re-seeds.

Wave 4 — the long tail

repo pkg cmds entry point argh dep i2 tests effort
thorwhalen/lookbook lookbook 5 lookbook.__main__:main ✅ via meshed ✗ small
thorwhalen/ov ov 10 ov.__main__:main ✅ ✗ ✗ small
thorwhalen/citeget citeget 6 citeget.cli:main ✅ ✗ ✗ small
thorwhalen/reelee reelee 26 reelee.__main__:main ✅ ✗ ⚠ small
thorwhalen/tw_platform tw_platform 8 none (python deploy.py) ✗ ✗ ✗ small
thorwhalen/scraped scraped 3 scraped.tools:main ✅ ✗ ✗ small
i2mint/ir ir 14 ir.__main__:main ✅ ✗ ✗ small
i2mint/enlace enlace 8 enlace.__main__:main ✅ ✗ ✗ small
i2mint/enlace_auth enlace_auth 11 enlace_auth.__main__:main ✅ ✗ ⚠ small
i2mint/http2py http2py — api-pkg-maker (dead) ✅ ✅ ✗ small
thorwhalen/ge ge 27 ge.__main__:main ✅ ✗ ✗ medium
thorwhalen/muvid muvid 17 muvid.__main__:main ✅ ✗ ✗ medium
thorwhalen/imbed_data_prep imbed_data_prep 10 none (python -m) ✗ ✅ ✗ trivial
i2mint/gurgle gurgle 2 gurgle-terminal (broken) ✗ ✗ ✗ trivial

ov is the fleet's only generator-returning command (runs() yields) — an egress that only does print(result) prints <generator object …>. tw_platform is the hardest constraint on cw's dependency budget (4222-line deliberately stdlib-only deploy.py; both workflows pip install argh with a comment saying why; live-server deploy, surface must not change). enlace carries the proven --app-name naming trap. http2py is a design source, not really a target: cli_maker.py is a working prototype of signature-ingress + argparse; read it before writing cw. gurgle's gurgle-terminal ImportErrors on a clean install today (undeclared argh at gurgle/terminal.py:221) — decide retire-or-migrate.

Wave 5 — priv, with the most care

repo pkg cmds entry point argh dep i2 tests effort
thorwhalen/priv priv 88 priv.__main__:main ✗ undeclared ✗ ✗ large

Highest value, highest risk, last. 88 commands across 4 namespaces (47 in __all__ + 22 git_ops + 8 pkg + 11 group); zero CLI tests; invoked constantly by the user and by agents via documented commands; priv --help is 489 lines. A functools.partial in __all__ produces the wrong command name, the partial's class docstring as help, and re-exposes the pre-bound keyword. The group name priv git_ops appears verbatim in agent-facing docs and is emitted as a suggested command by the code itself — hyphenating it is a user-visible break, not a cosmetic one.

Optional Wave 5b: re-migrate thorwhalen/an from typer to cw. Drops 7 distributions, restores argcomplete (which an had to abandon when typer replaced argparse), deletes ~120 lines of compensation. Its 443-line suite is written against typer's CliRunner and would need rewriting. Open question, not a recommendation.


Other verdicts

argparse-inline (3): thorwhalen/myproj (the argparse dispatcher is already written and exercised at projreg/__main__.py:244-273), thorwhalen/glossa data-prep, thorwhalen/mood. All Wave 0b, all net code removal, no new dependency.

drop-cli (11): oui, scoopy, odus, wealth, brand, loopyng, pipoke, tec, umpyre, mixing, hubcap. All Wave 0b.

dead-or-example (11): examples, py2dash, py2misc, viral, tapyoca, ut, taped, know, slang, raglab_bak, mv. Wave 0b, except know (a single TODO comment — leave it; it states cw's ingress spec years early) and raglab_bak (owner outside the landing perimeter).

already-migrated (1): thorwhalen/an → typer. Its 400-line tests/test_licence_perimeter.py is the source material for wads-licence-check.


Cross-track dependencies

  • ek's argh removal must ship with its _GPL_ALLOW inversion (licence track).
  • wads + isee land in one window.
  • cw + theremin — decoupled by having theremin declare argh first.
  • The doctrine rewrites split in two: remove the advocacy now (unblocked); install cw as the replacement after v1 ships. Pointing agents at a package that does not exist is worse than pointing them at argh.
  • Every wave's exit gate is a golden captured before the migration and replayed after — recorded exit code, stdout, stderr, and normalised usage: line, byte-identical.

Research & rationale: the canonical spec and the full fleet audit live in the private research ledger (https://github.com/thorwhalen/priv/discussions/65). Effort: large.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions