09. CLI¶
Purpose¶
Define observable CLI behavior: argument handling, summaries, output writing, and exit routing.
Observable surface only
This chapter covers scripting-visible behavior and user-facing CLI output categories. Rich styling details may evolve as long as markers, exit semantics, and deterministic output contracts stay stable.
Public surface¶
- Public entrypoint:
codeclone/main.py:main - CLI orchestration:
codeclone/surfaces/cli/workflow.py:_main_impl - Parser:
codeclone/config/argparse_builder.py:build_parser - Summary renderer:
codeclone/surfaces/cli/summary.py:_print_summary - Output path validation and writes:
codeclone/surfaces/cli/reports_output.py - Message catalog:
codeclone/ui_messages/__init__.py
Data model¶
CLI modes:
- normal mode
- gating mode (
--ci,--fail-on-new, explicit metric gates) - baseline update mode (
--update-baseline,--update-metrics-baseline)
Summary metrics include:
- files found/analyzed/cache hits/skipped
- structural counters for lines/functions/methods/classes
- function/block/segment clone groups
- suppressed clone groups from
golden_fixture_paths - dead-code active/suppressed status
- dependency depth profile (
avg_depth,p95_depth,max_depth) when metrics are computed - adoption/API/coverage-join facts when computed
- new vs baseline
Refs:
codeclone/surfaces/cli/summary.py:_print_summarycodeclone/surfaces/cli/runtime.py:_metrics_flags_requestedcodeclone/surfaces/cli/runtime.py:_metrics_computedcodeclone/surfaces/cli/report_meta.py:_build_report_meta
Contracts¶
- Help output includes canonical exit-code section and project links.
- Bare report flags write to deterministic default paths under
.cache/codeclone/. --open-html-reportis layered on top of--html; it does not imply HTML output.--timestamped-report-pathsrewrites only default report paths requested via bare flags.- In interactive VS Code terminals, the CLI may print a one-time extension hint
after summary output. The hint is suppressed in
--quiet, CI, and non-TTY contexts, and is tracked per CodeClone version next to the resolved project cache path. - Changed-scope review uses:
--changed-only--diff-against--paths-from-git-diff
- Contract errors use
CONTRACT ERROR:. - Gating failures use
GATING FAILURE:. - Internal errors use
fmt_internal_errorand include traceback only in debug mode.
Refs:
codeclone/contracts/__init__.py:cli_help_epilogcodeclone/ui_messages/__init__.py:fmt_contract_errorcodeclone/ui_messages/__init__.py:fmt_internal_errorcodeclone/surfaces/cli/changed_scope.py:_validate_changed_scope_args
Invariants (MUST)¶
- Report writes are path-validated and write failures are contract errors.
--open-html-reportrequires--html.--timestamped-report-pathsrequires at least one requested report output.--changed-onlyrequires a diff source.- Browser-open failure after successful HTML write is warning-only.
- In gating mode, unreadable source files are contract errors with higher priority than clone/metric gate failures.
Refs:
codeclone/surfaces/cli/reports_output.py:_validate_output_pathcodeclone/surfaces/cli/reports_output.py:_validate_report_ui_flagscodeclone/surfaces/cli/workflow.py:_main_impl
Failure modes¶
Failure precedence
Contract failures take precedence over gating failures. In CI and scripted
flows, invalid config or unreadable sources must surface as exit 2 before
any clone or metrics gate can fail with exit 3.
| Condition | User-facing category | Exit |
|---|---|---|
| Invalid CLI flag | contract | 2 |
| Invalid output extension/path | contract | 2 |
| Invalid changed-scope flag combination | contract | 2 |
| Baseline untrusted in CI/gating | contract | 2 |
| Coverage/API regression gate without required baseline capability | contract | 2 |
| Unreadable source in CI/gating | contract | 2 |
New clones with --fail-on-new |
gating | 3 |
| Threshold or metrics gate exceeded | gating | 3 |
| Unexpected exception | internal | 5 |
Determinism / canonicalization¶
- Summary metric ordering is fixed.
- Compact summary mode is fixed-format text.
- Help epilog is generated from static constants.
- Git diff path inputs are normalized to sorted repo-relative paths.
Refs:
codeclone/surfaces/cli/summary.py:_print_summarycodeclone/contracts/__init__.py:cli_help_epilogcodeclone/surfaces/cli/changed_scope.py:_normalize_changed_paths
Locked by tests¶
tests/test_cli_unit.py::test_cli_help_text_consistencytests/test_cli_unit.py::test_argument_parser_contract_error_marker_for_invalid_argstests/test_cli_inprocess.py::test_cli_summary_format_stabletests/test_cli_inprocess.py::test_cli_unreadable_source_fails_in_ci_with_contract_errortests/test_cli_inprocess.py::test_cli_contract_error_priority_over_gating_failure_for_unreadable_source
Non-guarantees¶
- Rich styling details are not machine-facing contract.
- Warning phrasing may evolve if category markers and exit semantics stay stable.