Simplify the Commander adapter now that behavior can change: dispatch a leading
`web` token to its own parser instead of a subcommand of the root program, and
read opts()/processedArgs after parse() instead of action closures with a
mutable holder.
This removes enablePositionalOptions(), the parent-option leak guard, both
action closures, and the --resume/--prompt argParser threading. Behavior
changes: `dsh -p x web` is a headless prompt (extra positional dropped),
`dsh web -p x` fails loud (web has no -p), and a repeated --resume is natural
last-wins. The two real fail-loud invariants stay as post-parse checks: an empty
--resume= id (agent-loop treats '' as no-resume) and an empty -p task.
Trims args.spec.ts to the routing/fail-loud/help behavior that matters; the
tui-agent keyless PTY smoke still covers bin.ts dispatch end to end. Net ~114
fewer lines across adapter and tests.
Replace the dsh CLI's three hand-rolled parsing idioms (raw argv[0]/includes
dispatch in bin.ts, per-mode node:util parseArgs in headless.ts/web.ts, and the
bespoke parseResumeArg scanner in dsh-app-boot) with a single Commander adapter
in apps/cli/src/args.ts. parseDshArgs resolves argv into a discriminated
DshInvocation union; bin.ts switches on the mode and dynamic-imports the chosen
module, which now consumes already-parsed values.
- web is a real subcommand; --host uses choices and --port an argParser range
check, moving validation into the parser.
- --resume rejects empty and repeated forms; --prompt rejects empty; a config
positional after --prompt and a root flag placed before web fail loud.
- adds --help/--version; removes parseResumeArg from dsh-app-boot.
- new apps/cli/tests/args.spec.ts (apps/*/tests added to vitest include,
apps/cli/tests to tsconfig.host.json); the tui-agent keyless PTY smoke covers
bin.ts dispatch end to end unchanged.