Plan: CLI Noun-Verb Reorganisation
Status: Draft
Overview
Reorganise the CascadeGuard CLI from flat top-level verbs to a consistent noun-verb pattern. The actions group already follows this convention (actions pin, actions audit, actions policy init). This plan extends it to all commands.
Current → Proposed Mapping
| Current command | New command | Noun group |
|---|---|---|
validate | images validate | images |
enrol | images enrol | images |
check | images check | images |
status | images status | images |
build | pipeline build | pipeline |
deploy | pipeline deploy | pipeline |
test | pipeline test | pipeline |
pipeline | pipeline run | pipeline |
scan-report | vuln report | vuln |
scan-issues | vuln issues | vuln |
actions pin | actions pin | actions (unchanged) |
actions audit | actions audit | actions (unchanged) |
actions policy init | actions policy init | actions (unchanged) |
(new) scan | scan | top-level |
Noun Groups
images — Image lifecycle management
cascadeguard images validate Validate images.yaml configuration
cascadeguard images enrol Enrol a new image in images.yaml
cascadeguard images check Check image and base image states
cascadeguard images status Show status of all images
pipeline — CI/CD orchestration
cascadeguard pipeline run Run full pipeline (validate → check → build → deploy → test)
cascadeguard pipeline build Trigger a build via GitHub Actions
cascadeguard pipeline deploy Deploy via ArgoCD
cascadeguard pipeline test Check build test results via GitHub Actions
vuln — Vulnerability management
cascadeguard vuln report Parse scanner output, write diffable vulnerability reports
cascadeguard vuln issues Create/update/reopen per-CVE GitHub issues
actions — GitHub Actions utilities (unchanged)
cascadeguard actions pin Pin action refs to full commit SHAs
cascadeguard actions audit Audit workflow files for pinning status / policy
cascadeguard actions policy init Scaffold a starter actions-policy.yaml
scan — Repository scanner (top-level, new)
cascadeguard scan Discover and analyse container artifacts in a repo
Implementation Approach
Parser restructure in build_parser()
Replace the flat subparser with noun-level subparsers, each containing their own verb subparsers:
sub = parser.add_subparsers(dest="command", metavar="command")
sub.required = True
# images
images = sub.add_parser("images", help="Image lifecycle management")
images_sub = images.add_subparsers(dest="images_command", metavar="subcommand")
images_sub.required = True
images_sub.add_parser("validate", help="Validate images.yaml")
# ... enrol, check, status
# pipeline
pipeline = sub.add_parser("pipeline", help="CI/CD orchestration")
pipeline_sub = pipeline.add_subparsers(dest="pipeline_command", metavar="subcommand")
pipeline_sub.required = True
pipeline_sub.add_parser("run", help="Run full pipeline")
# ... build, deploy, test
# vuln
vuln = sub.add_parser("vuln", help="Vulnerability management")
vuln_sub = vuln.add_subparsers(dest="vuln_command", metavar="subcommand")
vuln_sub.required = True
# ... report, issues
# actions — already structured this way, no change
# scan — top-level
sub.add_parser("scan", help="Discover and analyse container artifacts")Dispatch restructure in main()
Replace the flat dispatch dict with noun-level dispatchers (same pattern as existing cmd_actions):
def cmd_images(args) -> int:
return {
"validate": cmd_validate,
"enrol": cmd_enrol,
"check": cmd_check,
"status": cmd_status,
}[args.images_command](args)
def cmd_pipeline(args) -> int:
return {
"run": cmd_pipeline_run, # renamed from cmd_pipeline
"build": cmd_build,
"deploy": cmd_deploy,
"test": cmd_test,
}[args.pipeline_command](args)
def cmd_vuln(args) -> int:
return {
"report": cmd_scan_report,
"issues": cmd_scan_issues,
}[args.vuln_command](args)
commands = {
"images": cmd_images,
"pipeline": cmd_pipeline,
"vuln": cmd_vuln,
"actions": cmd_actions,
"scan": cmd_scan,
}Handler functions
No changes to the actual handler logic (cmd_validate, cmd_enrol, etc.) — only the dispatch wiring changes. The one rename is cmd_pipeline → cmd_pipeline_run to avoid collision with the new cmd_pipeline dispatcher.
Backward Compatibility
Option A: Clean break (recommended)
Remove old commands. The tool is pre-1.0 and not widely distributed yet. Update all references in:
Taskfile.docker.yaml(Docker entrypoint tasks)Taskfile.shared.yaml(state repo shared tasks)- README and docs
- Generated CI workflow files (
generate-cioutput)
Option B: Deprecation aliases
Keep old commands as hidden aliases that print a deprecation warning and delegate to the new structure. Remove after one release cycle.
Files to Change
| File | Change |
|---|---|
app/app.py | Restructure build_parser() and main() dispatch |
Taskfile.docker.yaml | Update command references |
Taskfile.shared.yaml | Update command references |
README.md | Update command examples |
app/tests/ | Update any tests that invoke CLI commands |
Global Options
The existing --images-yaml and --state-dir flags are currently global. After reorganisation they only make sense for the images noun group. Move them to the images subparser.
# Before (global)
cascadeguard --images-yaml custom.yaml validate
# After (scoped)
cascadeguard images --images-yaml custom.yaml validate
Help Output (target)
$ cascadeguard --help
CascadeGuard — container image lifecycle tool
Commands:
images Image lifecycle management
pipeline CI/CD orchestration
vuln Vulnerability management
actions GitHub Actions utilities
scan Discover and analyse container artifacts
$ cascadeguard images --help
Image lifecycle management
Subcommands:
validate Validate images.yaml configuration
enrol Enrol a new image in images.yaml
check Check image and base image states
status Show status of all images
Phases
Phase 1: Restructure parser and dispatch
- Refactor
build_parser()into noun groups - Add noun-level dispatchers
- Rename
cmd_pipeline→cmd_pipeline_run - Move
--images-yaml/--state-dirtoimagessubparser - Update tests
Phase 2: Update references
Taskfile.docker.yamlTaskfile.shared.yamlREADME.md- Generated CI workflow templates (if
generate-ciemits cascadeguard commands)
Phase 3: Add scan command (separate plan)
- Wire up
scansubparser at top level - Implement discovery modules per the scan command plan