|
| 1 | +--- |
| 2 | +description: Evaluate and enforce specific CLI argument parsing discipline across the codebase |
| 3 | +--- |
| 4 | + |
| 5 | +**Input argument:** `Language` (for example `Python` or `TypeScript`). |
| 6 | + |
| 7 | +## Goal 🎯 |
| 8 | + |
| 9 | +Audit every CLI entrypoint and argument parser in this repository against the CLI Contract Baseline and the argument parsing standards defined below. For each entrypoint, report compliance or non-compliance per category, citing concrete evidence (function names, line numbers, code snippets). Where gaps exist, implement fixes immediately using the sensible defaults described in this prompt and the baseline. |
| 10 | + |
| 11 | +## Steps 👣 |
| 12 | + |
| 13 | +### Step 1: Discover CLI entrypoints |
| 14 | + |
| 15 | +1. Detect the `Language` (Python or TypeScript) before running any file discovery. |
| 16 | +2. Run `git ls-files '*.<ext>'` to enumerate tracked files for the detected language (for example `.py`, `.ts`, `.tsx`). |
| 17 | +3. Locate CLI entrypoints in each language and runtime, including: |
| 18 | + - Conventional entry files (for example `__main__`, `main`, `cli`, `bin/`, `scripts/`). |
| 19 | + - Package metadata that registers commands (for example `pyproject.toml`, `setup.cfg`, `setup.py`, `package.json`, `Cargo.toml`). |
| 20 | +4. Record the entrypoint function or module for each CLI. |
| 21 | + |
| 22 | +### Step 2: Identify argument parsing logic |
| 23 | + |
| 24 | +1. For each CLI, find the argument parsing library (for example argparse, click, typer, clap, cobra, commander, yargs). |
| 25 | +2. Flag manual parsing (`sys.argv`, `os.Args`, `process.argv`) or ad-hoc split logic that bypasses a parser. |
| 26 | +3. Record where validation and default handling occur. |
| 27 | + |
| 28 | +### Step 3: Assess compliance |
| 29 | + |
| 30 | +Evaluate each CLI against the CLI Contract Baseline at: |
| 31 | + |
| 32 | +- `.github/instructions/includes/cli-contract-baseline.include.md` |
| 33 | + |
| 34 | +Report compliance for: |
| 35 | + |
| 36 | +- Exit codes |
| 37 | +- Stdout vs stderr |
| 38 | +- Documentation and testing expectations |
| 39 | +- Developer ergonomics |
| 40 | +- Wrappers and shared libraries |
| 41 | +- Cloud and serverless workloads (where relevant) |
| 42 | +- Argument parsing and flags |
| 43 | + |
| 44 | +### Step 4: Remediate |
| 45 | + |
| 46 | +1. Apply fixes immediately using the defaults in this prompt and the baseline. |
| 47 | +2. Keep changes small and consistent with existing patterns. |
| 48 | +3. Where behaviour changes are introduced, add tests using a strict Red → Green → Refactor flow. |
| 49 | + |
| 50 | +## Implementation requirements 🛠️ |
| 51 | + |
| 52 | +### Anti-patterns (flag and fix immediately) 🚫 |
| 53 | + |
| 54 | +- Manual `argv` parsing that bypasses a dedicated parser. |
| 55 | +- Abbreviated long flags or prefix matching that can become ambiguous. |
| 56 | +- More than two positional arguments without clear documentation and validation. |
| 57 | +- Boolean values represented as positional arguments. |
| 58 | +- Unknown flags or surplus positional arguments ignored or silently dropped. |
| 59 | +- Flag names that are inconsistent across commands for the same concept. |
| 60 | +- Help output that omits defaults, environment variable sources, or usage examples. |
| 61 | +- Hidden side effects on flag parsing or validation that make flags non-idempotent. |
| 62 | +- Interactive prompts triggered by default without a non-interactive equivalent. |
| 63 | +- Diagnostics printed to `stdout` or mixed into machine-readable outputs. |
| 64 | +- Wrapper CLIs that re-implement business logic instead of delegating to shared libraries. |
| 65 | + |
| 66 | +### Principles 🧭 |
| 67 | + |
| 68 | +- Keep parsing predictable, explicit, and stable for both humans and automation. |
| 69 | +- Prefer clarity over brevity; avoid clever parsing tricks. |
| 70 | +- Keep behaviour deterministic for the same inputs and environment. |
| 71 | +- Use clear, consistent naming: kebab-case for flags and nouns for commands. |
| 72 | +- Prefer long flags and add short aliases only when they are common and unambiguous. |
| 73 | +- Keep interfaces stable; avoid breaking changes or add deprecation periods. |
| 74 | +- Ensure flags are idempotent and avoid hidden side effects. |
| 75 | +- Accept arguments in predictable order and prefer explicit named flags over positional ambiguity. |
| 76 | +- Make configuration precedence explicit: CLI > env vars > config file > defaults. |
| 77 | +- Keep CLI entrypoints thin: parse/validate, call shared logic, and forward exit codes. |
| 78 | + |
| 79 | +### Argument parsing and flag rules 🧩 |
| 80 | + |
| 81 | +- Use a dedicated argument parser with validation, defaults, and help output. |
| 82 | +- Use kebab-case for long flags and single-letter short flags only for common actions. |
| 83 | +- Require exact long-flag matches; do not allow abbreviations. |
| 84 | +- Support `--` to stop option parsing and treat the remainder as positional input. |
| 85 | +- Use explicit boolean switches (`--feature` and `--no-feature`) or a single clear switch. |
| 86 | +- Validate required inputs, mutual exclusions, and ranges at parse time and exit with code `2` plus a `--help` hint. |
| 87 | +- Support repeatable flags for multiple values and document ordering, de-duplication, and limits. |
| 88 | +- Reject unknown flags and surplus positional arguments with exit code `2`. |
| 89 | +- Follow standard conventions for `-h/--help`, `-v/--version`, `--verbose`, and `--quiet`. These are must-have arguments for every CLI. |
| 90 | +- Provide `--yes` or `--no-input` for non-interactive operation and make prompts opt-in. |
| 91 | + |
| 92 | +### Modern parser defaults 🧱 |
| 93 | + |
| 94 | +- Use type hints or explicit parameter types for all options and arguments. |
| 95 | +- Prefer specialised parameter types (choice/enum, path/file, range, UUID, datetime) instead of raw strings. |
| 96 | +- Validate file and path parameters for existence and permissions at parse time. |
| 97 | +- Use explicit prompts only when configured; never prompt for required values by default. |
| 98 | +- For sensitive inputs, require confirmation prompts and avoid echoing input back to the terminal. |
| 99 | +- Use subcommands for distinct actions instead of large flag sets on a single command. |
| 100 | +- Use a shared context object to pass parsed configuration to subcommands; avoid global mutable state. |
| 101 | +- Use parser callbacks for validation and normalisation rather than manual checks after parsing. |
| 102 | +- Keep `--help` and `--version` eager so they work even when other inputs are invalid. |
| 103 | +- Provide shell completion support when the parser supports it and document how to enable it. |
| 104 | +- Use the parser's output helpers for consistent encoding and `stdout`/`stderr` handling. |
| 105 | + |
| 106 | +### Help and documentation 📋 |
| 107 | + |
| 108 | +- Keep `--help` short, structured, grouped, and example-driven. |
| 109 | +- Make defaults sensible and document them clearly in `--help`. |
| 110 | +- Include a piping or `--json` example when machine-readable output exists. |
| 111 | +- Document exit codes and diagnostic behaviour in README and help output. |
| 112 | +- Describe mutually exclusive options, default value sources, and configuration precedence. |
| 113 | + |
| 114 | +### Validation and errors 🚦 |
| 115 | + |
| 116 | +- Validate inputs early and return clear, actionable errors. |
| 117 | +- Use exit code `2` for parsing and validation errors. |
| 118 | +- Ensure errors are actionable and include a `--help` hint. |
| 119 | +- Do not emit diagnostics on `stdout`. |
| 120 | +- Use exit code `0` for success and `1` for operational failures when no specific code applies. |
| 121 | +- Exit with the first failure cause; do not mask distinct failures behind the same code unless documented. |
| 122 | + |
| 123 | +### Stdout and stderr semantics 📤 |
| 124 | + |
| 125 | +- Keep `stdout` for primary result payloads and `stderr` for diagnostics. |
| 126 | +- Ensure `stdout` stays clean for piping or redirection. |
| 127 | +- Emit progress to `stderr` for long-running commands. |
| 128 | +- Provide an explicit `--json` mode when machine-readable output is supported. |
| 129 | +- Flush and close streams explicitly before exiting short-lived handlers. |
| 130 | + |
| 131 | +### Developer ergonomics 🧑💻 |
| 132 | + |
| 133 | +- Provide `--help`, `--version`, and `--verbose` or `--quiet` consistently. |
| 134 | +- Offer `--dry-run` when the command mutates resources. |
| 135 | +- Keep interactive prompts opt-in and always provide a non-interactive equivalent. |
| 136 | + |
| 137 | +### Logging verbosity controls 🔊 |
| 138 | + |
| 139 | +- `--verbose` raises verbosity one step; allow `-v`, `-vv`, `-vvv` to increment levels (for example INFO → DEBUG → TRACE). |
| 140 | +- `--quiet` lowers verbosity one step; allow `-q`, `-qq` similarly. |
| 141 | +- Document the exact mapping from flags to log levels in `--help`. |
| 142 | +- Provide `--log-level <level>` for explicit control; flags are convenience. |
| 143 | +- Support an environment variable for verbosity (for example `LOG_LEVEL` or `VERBOSITY`), with precedence: CLI flags > env vars > config file > defaults. |
| 144 | +- Keep diagnostics on `stderr` and keep outputs deterministic. |
| 145 | + |
| 146 | +### Wrappers and shared libraries 📦 |
| 147 | + |
| 148 | +- Keep CLI entrypoints thin and delegate domain logic to shared libraries. |
| 149 | +- Align wrapper validation rules and defaults with the underlying library API. |
| 150 | +- Centralise shared parsing or logging helpers across related CLIs. |
| 151 | +- Expose a `main(args: list[str]) -> int` or equivalent entrypoint where possible. |
| 152 | + |
| 153 | +### Cloud and serverless workloads ☁️ |
| 154 | + |
| 155 | +- Avoid reliance on background daemons or writable current directories unless explicitly provisioned. |
| 156 | +- Provide `--timeout` flags where platform limits apply and emit periodic progress to `stderr`. |
| 157 | +- Emit structured logs compatible with shared observability standards. |
| 158 | +- Avoid interactive authentication flows; support token injection or credentials for automation. |
| 159 | + |
| 160 | +### Testing expectations 🧪 |
| 161 | + |
| 162 | +- Add integration tests for each CLI covering a success case and each reserved non-zero exit code. |
| 163 | +- Add unit tests for parsing edge cases (unknown flag, missing required input, mutual exclusions). |
| 164 | +- Keep tests deterministic and assert exact exit codes. |
| 165 | +- Test the CLI contract explicitly (help text, parsing, errors, exit codes). |
| 166 | +- Include smoke tests for wrapper CLIs to ensure deterministic exit codes and diagnostics. |
| 167 | +- Use the parser's built-in test runner where available instead of spawning subprocesses. |
| 168 | + |
| 169 | +## Output requirements 📋 |
| 170 | + |
| 171 | +1. **Findings per file**: for each category above and each of its bullet point, state one of the following statuses with a brief explanation and the emoji shown: ✅ Fully compliant, ⚠️ Partially compliant, ❌ Not compliant. |
| 172 | +2. **Evidence links**: reference specific lines using workspace-relative Markdown links (e.g., `[src/app.py](src/app.py#L10-L40)`). |
| 173 | +3. **Immediate fixes**: apply sensible defaults inline where possible; do not defer trivial remediations. |
| 174 | +4. **Unknowns**: when information is missing, record **Unknown from code – {suggested action}** rather than guessing. |
| 175 | +5. **Summary checklist**: after processing all CLIs, confirm overall compliance with: |
| 176 | + - [ ] Principles |
| 177 | + - [ ] Argument parsing and flag rules |
| 178 | + - [ ] Modern parser defaults |
| 179 | + - [ ] Help and documentation |
| 180 | + - [ ] Validation and errors |
| 181 | + - [ ] Stdout and stderr semantics |
| 182 | + - [ ] Developer ergonomics |
| 183 | + - [ ] Logging verbosity controls |
| 184 | + - [ ] Wrappers and shared libraries |
| 185 | + - [ ] Cloud and serverless workloads |
| 186 | + - [ ] Testing expectations |
| 187 | + |
| 188 | +--- |
| 189 | + |
| 190 | +> **Version**: 1.0.1 |
| 191 | +> **Last Amended**: 2026-01-29 |
0 commit comments