This is a high-quality audit. A 2.1 average complexity score is healthy for a security tool, but your "Score 5" items are classic "Technical Debt" in CLI design.
Here is a 3-stage plan to refactor these commands to reveal their intent and simplify the API.
Goal: Decompose the "Score 5" commands into focused sub-commands.
This command is currently a "dumping ground" for snapshot metrics.
- Action: Split into
statusandrisk. - New Commands:
stave snapshot status: Focus on inventory counts, retention estimates, and "physical" health (file sizes, corrupted JSON).stave snapshot risk: Focus on SLA posture, overdue trends, and "logical" health.
- Result: Reduces 13 flags to ~6 per command.
This command is trying to be a "Compliance Officer in a Box."
- Action: Separate Generation (Data) from Gating (Logic).
- New Commands:
stave audit generate: Handles formats (SBOM, PDF, JSON), compliance frameworks, and privacy masking.stave audit gate: Handles the "Pass/Fail" logic based on thresholds (e.g.,fail-on-critical).
- Result: Users can now pipe them:
stave audit generate --format json | stave audit gate --strict.
Goal: Turn "Mode Flags" into explicit sub-commands to clarify the user's journey.
Using flags like --control-id to trigger a completely different UI/output is confusing.
- Action: Create a
findingsub-command. - New Command:
stave diagnose finding --id <ID>. - Intent: The top-level
stave diagnoseremains a "General Health Check," whilefindingis the "Deep Dive."
The --profile vs --controls/--observations mutual exclusivity is a "leaky abstraction."
- Action: Standardize on "Profiles" as the primary intent, and treat "Direct Dirs" as the "Ad-hoc" mode.
- Fix: Use Cobra's
MarkFlagsMutuallyExclusiveto provide a clear error message: "Cannot use --profile with --controls; choose either a Managed Profile or Ad-hoc Directories."
Goal: Remove "Noise" from the help text of individual commands.
Flags like --verbose, --log-level, and --sanitize should not be redefined in every command file.
- Action: Move these to the
RootCmdas Persistent Flags. - Intent: When a user types
stave <command> --help, they only see the flags unique to that command's business logic. The "Technical" flags are tucked away in the global help.
The "Switching Policy" logic is currently hidden in code.
- Action: Use a "Strategy" pattern in the CLI layer.
- Suggestion: Instead of one command with a
--policyflag, considerstave ci gate violationandstave ci gate drift. This reveals the intent of the "Gate" immediately.
- Iterative Deprecation: Don't delete the old flags immediately. Add the new sub-commands, and mark the old flags as
HiddenorDeprecated. - Update
docs/: Use thestave capabilitiescommand to reflect these changes so the documentation stays in sync with the CLI structure. - Command Aliases: If users are used to
stave apply --dry-run, makestave validatea suggested alias in the help text.
Final Verdict:
By moving your "Score 5" and "Score 4" commands toward the "Score 1" (Unix-style) model of your inspect tools, you move from a "Feature-Driven CLI" to an "Intent-Driven CLI."