codeclone 1.4.4__tar.gz → 2.0.0b2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. {codeclone-1.4.4 → codeclone-2.0.0b2}/LICENSE +2 -0
  2. codeclone-2.0.0b2/PKG-INFO +386 -0
  3. codeclone-2.0.0b2/README.md +344 -0
  4. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/__init__.py +2 -7
  5. codeclone-2.0.0b2/codeclone/_cli_args.py +382 -0
  6. codeclone-2.0.0b2/codeclone/_cli_baselines.py +389 -0
  7. codeclone-2.0.0b2/codeclone/_cli_config.py +266 -0
  8. codeclone-2.0.0b2/codeclone/_cli_gating.py +136 -0
  9. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/_cli_meta.py +56 -12
  10. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/_cli_paths.py +9 -13
  11. codeclone-2.0.0b2/codeclone/_cli_reports.py +147 -0
  12. codeclone-2.0.0b2/codeclone/_cli_rich.py +128 -0
  13. codeclone-2.0.0b2/codeclone/_cli_runtime.py +189 -0
  14. codeclone-2.0.0b2/codeclone/_cli_summary.py +151 -0
  15. codeclone-2.0.0b2/codeclone/_coerce.py +50 -0
  16. codeclone-2.0.0b2/codeclone/_html_badges.py +172 -0
  17. codeclone-2.0.0b2/codeclone/_html_css.py +1153 -0
  18. codeclone-2.0.0b2/codeclone/_html_data_attrs.py +27 -0
  19. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/_html_escape.py +2 -7
  20. codeclone-2.0.0b2/codeclone/_html_filters.py +56 -0
  21. codeclone-2.0.0b2/codeclone/_html_js.py +598 -0
  22. codeclone-2.0.0b2/codeclone/_html_report/__init__.py +10 -0
  23. codeclone-2.0.0b2/codeclone/_html_report/_assemble.py +361 -0
  24. codeclone-2.0.0b2/codeclone/_html_report/_components.py +128 -0
  25. codeclone-2.0.0b2/codeclone/_html_report/_context.py +292 -0
  26. codeclone-2.0.0b2/codeclone/_html_report/_glossary.py +56 -0
  27. codeclone-2.0.0b2/codeclone/_html_report/_icons.py +76 -0
  28. codeclone-2.0.0b2/codeclone/_html_report/_sections/__init__.py +2 -0
  29. codeclone-2.0.0b2/codeclone/_html_report/_sections/_clones.py +645 -0
  30. codeclone-2.0.0b2/codeclone/_html_report/_sections/_coupling.py +159 -0
  31. codeclone-2.0.0b2/codeclone/_html_report/_sections/_dead_code.py +112 -0
  32. codeclone-2.0.0b2/codeclone/_html_report/_sections/_dependencies.py +473 -0
  33. codeclone-2.0.0b2/codeclone/_html_report/_sections/_meta.py +388 -0
  34. codeclone-2.0.0b2/codeclone/_html_report/_sections/_overview.py +644 -0
  35. codeclone-2.0.0b2/codeclone/_html_report/_sections/_structural.py +29 -0
  36. codeclone-2.0.0b2/codeclone/_html_report/_sections/_suggestions.py +275 -0
  37. codeclone-2.0.0b2/codeclone/_html_report/_tables.py +121 -0
  38. codeclone-2.0.0b2/codeclone/_html_report/_tabs.py +57 -0
  39. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/_html_snippets.py +6 -43
  40. codeclone-2.0.0b2/codeclone/_schema_validation.py +41 -0
  41. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/baseline.py +127 -34
  42. codeclone-2.0.0b2/codeclone/blockhash.py +29 -0
  43. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/blocks.py +18 -38
  44. codeclone-2.0.0b2/codeclone/cache.py +2377 -0
  45. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/cfg.py +82 -51
  46. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/cfg_model.py +6 -8
  47. codeclone-2.0.0b2/codeclone/cli.py +1265 -0
  48. codeclone-2.0.0b2/codeclone/contracts.py +66 -0
  49. codeclone-2.0.0b2/codeclone/domain/__init__.py +132 -0
  50. codeclone-2.0.0b2/codeclone/domain/findings.py +74 -0
  51. codeclone-2.0.0b2/codeclone/domain/quality.py +77 -0
  52. codeclone-2.0.0b2/codeclone/domain/source_scope.py +44 -0
  53. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/errors.py +2 -7
  54. codeclone-2.0.0b2/codeclone/extractor.py +1152 -0
  55. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/fingerprint.py +2 -7
  56. codeclone-2.0.0b2/codeclone/grouping.py +67 -0
  57. codeclone-2.0.0b2/codeclone/html_report.py +26 -0
  58. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/meta_markers.py +2 -7
  59. codeclone-2.0.0b2/codeclone/metrics/__init__.py +36 -0
  60. codeclone-2.0.0b2/codeclone/metrics/cohesion.py +88 -0
  61. codeclone-2.0.0b2/codeclone/metrics/complexity.py +93 -0
  62. codeclone-2.0.0b2/codeclone/metrics/coupling.py +93 -0
  63. codeclone-2.0.0b2/codeclone/metrics/dead_code.py +120 -0
  64. codeclone-2.0.0b2/codeclone/metrics/dependencies.py +198 -0
  65. codeclone-2.0.0b2/codeclone/metrics/health.py +125 -0
  66. codeclone-2.0.0b2/codeclone/metrics_baseline.py +788 -0
  67. codeclone-2.0.0b2/codeclone/models.py +298 -0
  68. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/normalize.py +18 -26
  69. codeclone-2.0.0b2/codeclone/paths.py +16 -0
  70. codeclone-2.0.0b2/codeclone/pipeline.py +1703 -0
  71. codeclone-2.0.0b2/codeclone/report/__init__.py +74 -0
  72. codeclone-2.0.0b2/codeclone/report/_formatting.py +12 -0
  73. codeclone-2.0.0b2/codeclone/report/_source_kinds.py +45 -0
  74. codeclone-2.0.0b2/codeclone/report/blocks.py +43 -0
  75. codeclone-2.0.0b2/codeclone/report/derived.py +227 -0
  76. codeclone-1.4.4/codeclone/_report_explain.py → codeclone-2.0.0b2/codeclone/report/explain.py +66 -56
  77. codeclone-1.4.4/codeclone/_report_explain_contract.py → codeclone-2.0.0b2/codeclone/report/explain_contract.py +10 -16
  78. codeclone-2.0.0b2/codeclone/report/findings.py +556 -0
  79. codeclone-2.0.0b2/codeclone/report/json_contract.py +2270 -0
  80. codeclone-2.0.0b2/codeclone/report/markdown.py +524 -0
  81. codeclone-2.0.0b2/codeclone/report/merge.py +78 -0
  82. codeclone-2.0.0b2/codeclone/report/overview.py +497 -0
  83. codeclone-2.0.0b2/codeclone/report/sarif.py +944 -0
  84. codeclone-2.0.0b2/codeclone/report/segments.py +209 -0
  85. codeclone-2.0.0b2/codeclone/report/serialize.py +717 -0
  86. codeclone-2.0.0b2/codeclone/report/suggestions.py +731 -0
  87. codeclone-2.0.0b2/codeclone/report/types.py +26 -0
  88. codeclone-2.0.0b2/codeclone/scanner.py +171 -0
  89. codeclone-2.0.0b2/codeclone/structural_findings.py +1047 -0
  90. codeclone-2.0.0b2/codeclone/suppressions.py +263 -0
  91. codeclone-2.0.0b2/codeclone/templates.py +38 -0
  92. codeclone-2.0.0b2/codeclone/ui_messages.py +569 -0
  93. codeclone-2.0.0b2/codeclone.egg-info/PKG-INFO +386 -0
  94. codeclone-2.0.0b2/codeclone.egg-info/SOURCES.txt +138 -0
  95. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone.egg-info/requires.txt +6 -3
  96. {codeclone-1.4.4 → codeclone-2.0.0b2}/pyproject.toml +29 -12
  97. codeclone-2.0.0b2/tests/test_architecture.py +149 -0
  98. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_baseline.py +298 -26
  99. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_blockhash.py +2 -2
  100. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_cache.py +766 -35
  101. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_cfg.py +22 -41
  102. codeclone-2.0.0b2/tests/test_cli_config.py +266 -0
  103. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_cli_inprocess.py +1370 -946
  104. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_cli_smoke.py +3 -3
  105. codeclone-2.0.0b2/tests/test_cli_unit.py +1030 -0
  106. codeclone-2.0.0b2/tests/test_coerce.py +53 -0
  107. codeclone-2.0.0b2/tests/test_core_branch_coverage.py +969 -0
  108. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_detector_golden.py +12 -12
  109. codeclone-2.0.0b2/tests/test_extractor.py +1614 -0
  110. codeclone-2.0.0b2/tests/test_golden_v2.py +337 -0
  111. codeclone-2.0.0b2/tests/test_html_report.py +2116 -0
  112. codeclone-2.0.0b2/tests/test_html_report_helpers.py +95 -0
  113. codeclone-2.0.0b2/tests/test_metrics_baseline.py +543 -0
  114. codeclone-2.0.0b2/tests/test_metrics_modules.py +601 -0
  115. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_normalize.py +130 -126
  116. codeclone-2.0.0b2/tests/test_pipeline_metrics.py +347 -0
  117. codeclone-2.0.0b2/tests/test_pipeline_process.py +456 -0
  118. codeclone-2.0.0b2/tests/test_python_syntax_compat.py +19 -0
  119. codeclone-2.0.0b2/tests/test_report.py +2940 -0
  120. codeclone-2.0.0b2/tests/test_report_branch_invariants.py +365 -0
  121. codeclone-2.0.0b2/tests/test_report_contract_coverage.py +1665 -0
  122. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_report_explain.py +113 -61
  123. codeclone-2.0.0b2/tests/test_report_source_kinds.py +29 -0
  124. codeclone-2.0.0b2/tests/test_report_suggestions.py +368 -0
  125. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_scanner_extra.py +101 -6
  126. codeclone-2.0.0b2/tests/test_structural_findings.py +824 -0
  127. codeclone-2.0.0b2/tests/test_suppressions.py +430 -0
  128. codeclone-1.4.4/PKG-INFO +0 -389
  129. codeclone-1.4.4/README.md +0 -348
  130. codeclone-1.4.4/codeclone/_cli_args.py +0 -180
  131. codeclone-1.4.4/codeclone/_cli_summary.py +0 -129
  132. codeclone-1.4.4/codeclone/_report_blocks.py +0 -94
  133. codeclone-1.4.4/codeclone/_report_grouping.py +0 -64
  134. codeclone-1.4.4/codeclone/_report_segments.py +0 -247
  135. codeclone-1.4.4/codeclone/_report_serialize.py +0 -418
  136. codeclone-1.4.4/codeclone/_report_types.py +0 -18
  137. codeclone-1.4.4/codeclone/blockhash.py +0 -21
  138. codeclone-1.4.4/codeclone/cache.py +0 -895
  139. codeclone-1.4.4/codeclone/cli.py +0 -906
  140. codeclone-1.4.4/codeclone/contracts.py +0 -64
  141. codeclone-1.4.4/codeclone/extractor.py +0 -292
  142. codeclone-1.4.4/codeclone/html_report.py +0 -789
  143. codeclone-1.4.4/codeclone/report.py +0 -61
  144. codeclone-1.4.4/codeclone/scanner.py +0 -115
  145. codeclone-1.4.4/codeclone/templates.py +0 -3103
  146. codeclone-1.4.4/codeclone/ui_messages.py +0 -323
  147. codeclone-1.4.4/codeclone.egg-info/PKG-INFO +0 -389
  148. codeclone-1.4.4/codeclone.egg-info/SOURCES.txt +0 -64
  149. codeclone-1.4.4/tests/test_cli_unit.py +0 -313
  150. codeclone-1.4.4/tests/test_extractor.py +0 -542
  151. codeclone-1.4.4/tests/test_html_report.py +0 -981
  152. codeclone-1.4.4/tests/test_report.py +0 -1302
  153. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone/py.typed +0 -0
  154. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone.egg-info/dependency_links.txt +0 -0
  155. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone.egg-info/entry_points.txt +0 -0
  156. {codeclone-1.4.4 → codeclone-2.0.0b2}/codeclone.egg-info/top_level.txt +0 -0
  157. {codeclone-1.4.4 → codeclone-2.0.0b2}/setup.cfg +0 -0
  158. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_blocks.py +0 -0
  159. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_cfg_model.py +0 -0
  160. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_cli_main_guard.py +0 -0
  161. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_cli_main_guard_runpy.py +0 -0
  162. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_fingerprint.py +0 -0
  163. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_init.py +0 -0
  164. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_security.py +0 -0
  165. {codeclone-1.4.4 → codeclone-2.0.0b2}/tests/test_segments.py +0 -0
@@ -2,6 +2,8 @@ MIT License
2
2
 
3
3
  Copyright (c) 2024 Denis Rozhnovskiy
4
4
 
5
+ The name “CodeClone” refers to the official project distribution.
6
+
5
7
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
8
  of this software and associated documentation files (the "Software"), to deal
7
9
  in the Software without restriction, including without limitation the rights
@@ -0,0 +1,386 @@
1
+ Metadata-Version: 2.4
2
+ Name: codeclone
3
+ Version: 2.0.0b2
4
+ Summary: Structural code quality analysis for Python
5
+ Author-email: Den Rozhnovskiy <pytelemonbot@mail.ru>
6
+ Maintainer-email: Den Rozhnovskiy <pytelemonbot@mail.ru>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/orenlab/codeclone
9
+ Project-URL: Repository, https://github.com/orenlab/codeclone
10
+ Project-URL: Issues, https://github.com/orenlab/codeclone/issues
11
+ Project-URL: Changelog, https://github.com/orenlab/codeclone/releases
12
+ Project-URL: Documentation, https://orenlab.github.io/codeclone/
13
+ Keywords: python,ast,cfg,code-clone,duplication,static-analysis,architecture,control-flow,ci
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Topic :: Software Development :: Quality Assurance
17
+ Classifier: Topic :: Software Development :: Testing
18
+ Classifier: Typing :: Typed
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3.14
25
+ Classifier: Operating System :: OS Independent
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Requires-Python: >=3.10
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ Requires-Dist: pygments>=2.19.2
31
+ Requires-Dist: rich>=14.3.2
32
+ Requires-Dist: tomli>=2.0.1; python_version < "3.11"
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=9.0.0; extra == "dev"
35
+ Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
36
+ Requires-Dist: build>=1.4.1; extra == "dev"
37
+ Requires-Dist: twine>=5.0.0; extra == "dev"
38
+ Requires-Dist: mypy>=1.19.1; extra == "dev"
39
+ Requires-Dist: ruff>=0.15.8; extra == "dev"
40
+ Requires-Dist: pre-commit>=4.5.1; extra == "dev"
41
+ Dynamic: license-file
42
+
43
+ <p align="center">
44
+ <img src="https://orenlab.github.io/codeclone/assets/codeclone-wordmark.svg" alt="CodeClone" height="60">
45
+ </p>
46
+
47
+ <p align="center">
48
+ <strong>Structural code quality analysis for Python</strong>
49
+ </p>
50
+
51
+ <p align="center">
52
+ <a href="https://pypi.org/project/codeclone/"><img src="https://img.shields.io/pypi/v/codeclone.svg?style=flat-square" alt="PyPI"></a>
53
+ <a href="https://pypi.org/project/codeclone/"><img src="https://img.shields.io/pypi/dm/codeclone.svg?style=flat-square" alt="Downloads"></a>
54
+ <a href="https://github.com/orenlab/codeclone/actions/workflows/tests.yml"><img src="https://github.com/orenlab/codeclone/actions/workflows/tests.yml/badge.svg?branch=main&style=flat-square" alt="Tests"></a>
55
+ <a href="https://github.com/orenlab/codeclone/actions/workflows/benchmark.yml"><img src="https://github.com/orenlab/codeclone/actions/workflows/benchmark.yml/badge.svg?style=flat-square" alt="Benchmark"></a>
56
+ <a href="https://pypi.org/project/codeclone/"><img src="https://img.shields.io/pypi/pyversions/codeclone.svg?style=flat-square" alt="Python"></a>
57
+ <a href="https://github.com/orenlab/codeclone"><img src="https://img.shields.io/badge/codeclone-81%20(B)-green" alt="codeclone 81 (B)"></a>
58
+ <a href="https://github.com/orenlab/codeclone/blob/main/LICENSE"><img src="https://img.shields.io/pypi/l/codeclone.svg?style=flat-square" alt="License"></a>
59
+ </p>
60
+
61
+ ---
62
+
63
+ CodeClone provides comprehensive structural code quality analysis for Python. It detects architectural
64
+ duplication via normalized AST and Control Flow Graphs, computes quality metrics, and enforces CI gates —
65
+ all with baseline-aware governance that separates **known** technical debt from **new** regressions.
66
+
67
+ Docs: [orenlab.github.io/codeclone](https://orenlab.github.io/codeclone/) ·
68
+ Live sample report:
69
+ [orenlab.github.io/codeclone/examples/report/](https://orenlab.github.io/codeclone/examples/report/)
70
+
71
+ ## Features
72
+
73
+ - **Clone detection** — function (CFG fingerprint), block (statement windows), and segment (report-only) clones
74
+ - **Structural findings** — duplicated branch families, clone guard/exit divergence and clone-cohort drift (report-only)
75
+ - **Quality metrics** — cyclomatic complexity, coupling (CBO), cohesion (LCOM4), dependency cycles, dead code, health
76
+ score
77
+ - **Baseline governance** — known debt stays accepted; CI blocks only new clones and metric regressions
78
+ - **Reports** — interactive HTML, deterministic JSON/TXT plus Markdown and SARIF projections from one canonical report
79
+ - **CI-first** — deterministic output, stable ordering, exit code contract, pre-commit support
80
+ - **Fast*** — incremental caching, parallel processing, warm-run optimization, and reproducible benchmark coverage
81
+
82
+ ## Quick Start
83
+
84
+ ```bash
85
+ pip install codeclone # or: uv tool install codeclone
86
+
87
+ codeclone . # analyze current directory
88
+ codeclone . --html # generate HTML report
89
+ codeclone . --html --open-html-report # generate and open HTML report
90
+ codeclone . --json --md --sarif --text # generate machine-readable reports
91
+ codeclone . --html --json --timestamped-report-paths # keep timestamped report snapshots
92
+ codeclone . --ci # CI mode (--fail-on-new --no-color --quiet)
93
+ ```
94
+
95
+ <details>
96
+ <summary>Run without install</summary>
97
+
98
+ ```bash
99
+ uvx codeclone@latest .
100
+ ```
101
+
102
+ </details>
103
+
104
+ ## CI Integration
105
+
106
+ ```bash
107
+ # 1. Generate baseline (commit to repo)
108
+ codeclone . --update-baseline
109
+
110
+ # 2. Add to CI pipeline
111
+ codeclone . --ci
112
+ ```
113
+
114
+ The `--ci` preset equals `--fail-on-new --no-color --quiet`.
115
+ When a trusted metrics baseline is loaded, CI mode also enables
116
+ `--fail-on-new-metrics`.
117
+
118
+ ### Quality Gates
119
+
120
+ ```bash
121
+ # Metrics thresholds
122
+ codeclone . --fail-complexity 20 --fail-coupling 10 --fail-cohesion 4 --fail-health 60
123
+
124
+ # Structural policies
125
+ codeclone . --fail-cycles --fail-dead-code
126
+
127
+ # Regression detection vs baseline
128
+ codeclone . --fail-on-new-metrics
129
+ ```
130
+
131
+ ### Pre-commit
132
+
133
+ ```yaml
134
+ repos:
135
+ - repo: local
136
+ hooks:
137
+ - id: codeclone
138
+ name: CodeClone
139
+ entry: codeclone
140
+ language: system
141
+ pass_filenames: false
142
+ args: [ ".", "--ci" ]
143
+ types: [ python ]
144
+ ```
145
+
146
+ ## Configuration
147
+
148
+ CodeClone can load project-level configuration from `pyproject.toml`:
149
+
150
+ ```toml
151
+ [tool.codeclone]
152
+ min_loc = 10
153
+ min_stmt = 6
154
+ baseline = "codeclone.baseline.json"
155
+ skip_metrics = false
156
+ quiet = false
157
+ html_out = ".cache/codeclone/report.html"
158
+ json_out = ".cache/codeclone/report.json"
159
+ md_out = ".cache/codeclone/report.md"
160
+ sarif_out = ".cache/codeclone/report.sarif"
161
+ text_out = ".cache/codeclone/report.txt"
162
+ block_min_loc = 20
163
+ block_min_stmt = 8
164
+ segment_min_loc = 20
165
+ segment_min_stmt = 10
166
+ ```
167
+
168
+ Precedence: CLI flags > `pyproject.toml` > built-in defaults.
169
+
170
+ ## Baseline Workflow
171
+
172
+ Baselines capture the current duplication state. Once committed, they become the CI reference point.
173
+
174
+ - Clones are classified as **NEW** (not in baseline) or **KNOWN** (accepted debt)
175
+ - `--update-baseline` writes both clone and metrics snapshots
176
+ - Trust is verified via `generator`, `fingerprint_version`, and `payload_sha256`
177
+ - In `--ci` mode, an untrusted baseline is a contract error (exit 2)
178
+
179
+ Full contract: [Baseline contract](https://orenlab.github.io/codeclone/book/06-baseline/)
180
+
181
+ ## Exit Codes
182
+
183
+ | Code | Meaning |
184
+ |------|-------------------------------------------------------------------------------|
185
+ | `0` | Success |
186
+ | `2` | Contract error — untrusted baseline, invalid config, unreadable sources in CI |
187
+ | `3` | Gating failure — new clones or metric threshold exceeded |
188
+ | `5` | Internal error |
189
+
190
+ Contract errors (`2`) take precedence over gating failures (`3`).
191
+
192
+ ## Reports
193
+
194
+ | Format | Flag | Default path |
195
+ |----------|-----------|---------------------------------|
196
+ | HTML | `--html` | `.cache/codeclone/report.html` |
197
+ | JSON | `--json` | `.cache/codeclone/report.json` |
198
+ | Markdown | `--md` | `.cache/codeclone/report.md` |
199
+ | SARIF | `--sarif` | `.cache/codeclone/report.sarif` |
200
+ | Text | `--text` | `.cache/codeclone/report.txt` |
201
+
202
+ All report formats are rendered from one canonical JSON report document.
203
+
204
+ - `--open-html-report` opens the generated HTML report in the default browser and requires `--html`.
205
+ - `--timestamped-report-paths` appends a UTC timestamp to default report filenames for bare report flags such as
206
+ `--html` or `--json`. Explicit report paths are not rewritten.
207
+
208
+ The published docs site also includes a live example HTML/JSON/SARIF report
209
+ generated from the current `codeclone` repository during the docs build.
210
+
211
+ Structural findings include:
212
+
213
+ - `duplicated_branches`
214
+ - `clone_guard_exit_divergence`
215
+ - `clone_cohort_drift`
216
+
217
+ ### Inline Suppressions
218
+
219
+ CodeClone keeps dead-code detection deterministic and static by default. When a symbol is intentionally
220
+ invoked through runtime dynamics (for example framework callbacks, plugin loading, or reflection), suppress
221
+ the known false positive explicitly at the declaration site:
222
+
223
+ ```python
224
+ # codeclone: ignore[dead-code]
225
+ def handle_exception(exc: Exception) -> None:
226
+ ...
227
+
228
+
229
+ class Middleware: # codeclone: ignore[dead-code]
230
+ ...
231
+ ```
232
+
233
+ Dynamic/runtime false positives are resolved via explicit inline suppressions, not via broad heuristics.
234
+
235
+ <details>
236
+ <summary>JSON report shape (v2.1)</summary>
237
+
238
+ ```json
239
+ {
240
+ "report_schema_version": "2.1",
241
+ "meta": {
242
+ "codeclone_version": "2.0.0b2",
243
+ "project_name": "...",
244
+ "scan_root": ".",
245
+ "report_mode": "full",
246
+ "baseline": {
247
+ "...": "..."
248
+ },
249
+ "cache": {
250
+ "...": "..."
251
+ },
252
+ "metrics_baseline": {
253
+ "...": "..."
254
+ },
255
+ "runtime": {
256
+ "report_generated_at_utc": "..."
257
+ }
258
+ },
259
+ "inventory": {
260
+ "files": {
261
+ "...": "..."
262
+ },
263
+ "code": {
264
+ "...": "..."
265
+ },
266
+ "file_registry": {
267
+ "encoding": "relative_path",
268
+ "items": []
269
+ }
270
+ },
271
+ "findings": {
272
+ "summary": {
273
+ "...": "..."
274
+ },
275
+ "groups": {
276
+ "clones": {
277
+ "functions": [],
278
+ "blocks": [],
279
+ "segments": []
280
+ },
281
+ "structural": {
282
+ "groups": []
283
+ },
284
+ "dead_code": {
285
+ "groups": []
286
+ },
287
+ "design": {
288
+ "groups": []
289
+ }
290
+ }
291
+ },
292
+ "metrics": {
293
+ "summary": {},
294
+ "families": {}
295
+ },
296
+ "derived": {
297
+ "suggestions": [],
298
+ "overview": {
299
+ "families": {},
300
+ "top_risks": [],
301
+ "source_scope_breakdown": {},
302
+ "health_snapshot": {}
303
+ },
304
+ "hotlists": {
305
+ "most_actionable_ids": [],
306
+ "highest_spread_ids": [],
307
+ "production_hotspot_ids": [],
308
+ "test_fixture_hotspot_ids": []
309
+ }
310
+ },
311
+ "integrity": {
312
+ "canonicalization": {
313
+ "version": "1",
314
+ "scope": "canonical_only"
315
+ },
316
+ "digest": {
317
+ "algorithm": "sha256",
318
+ "verified": true,
319
+ "value": "..."
320
+ }
321
+ }
322
+ }
323
+ ```
324
+
325
+ Canonical contract: [Report contract](https://orenlab.github.io/codeclone/book/08-report/) and
326
+ [Dead-code contract](https://orenlab.github.io/codeclone/book/16-dead-code-contract/)
327
+
328
+ </details>
329
+
330
+ ## How It Works
331
+
332
+ 1. **Parse** — Python source to AST
333
+ 2. **Normalize** — canonical structure (robust to renaming, formatting)
334
+ 3. **CFG** — per-function control flow graph
335
+ 4. **Fingerprint** — stable hash computation
336
+ 5. **Group** — function, block, and segment clone groups
337
+ 6. **Metrics** — complexity, coupling, cohesion, dependencies, dead code, health
338
+ 7. **Gate** — baseline comparison, threshold checks
339
+
340
+ Architecture: [Architecture narrative](https://orenlab.github.io/codeclone/architecture/) ·
341
+ CFG semantics: [CFG semantics](https://orenlab.github.io/codeclone/cfg/)
342
+
343
+ ## Documentation
344
+
345
+ | Topic | Link |
346
+ |----------------------------|----------------------------------------------------------------------------------------------------|
347
+ | Contract book (start here) | [Contracts and guarantees](https://orenlab.github.io/codeclone/book/00-intro/) |
348
+ | Exit codes | [Exit codes and failure policy](https://orenlab.github.io/codeclone/book/03-contracts-exit-codes/) |
349
+ | Configuration | [Config and defaults](https://orenlab.github.io/codeclone/book/04-config-and-defaults/) |
350
+ | Baseline contract | [Baseline contract](https://orenlab.github.io/codeclone/book/06-baseline/) |
351
+ | Cache contract | [Cache contract](https://orenlab.github.io/codeclone/book/07-cache/) |
352
+ | Report contract | [Report contract](https://orenlab.github.io/codeclone/book/08-report/) |
353
+ | Metrics & quality gates | [Metrics and quality gates](https://orenlab.github.io/codeclone/book/15-metrics-and-quality-gates/) |
354
+ | Dead code | [Dead-code contract](https://orenlab.github.io/codeclone/book/16-dead-code-contract/) |
355
+ | Docker benchmark contract | [Benchmarking contract](https://orenlab.github.io/codeclone/book/18-benchmarking/) |
356
+ | Determinism | [Determinism policy](https://orenlab.github.io/codeclone/book/12-determinism/) |
357
+
358
+ ## * Benchmarking
359
+
360
+ <details>
361
+ <summary>Reproducible Docker Benchmark</summary>
362
+
363
+ ```bash
364
+ ./benchmarks/run_docker_benchmark.sh
365
+ ```
366
+
367
+ The wrapper builds `benchmarks/Dockerfile`, runs isolated container benchmarks, and writes results to
368
+ `.cache/benchmarks/codeclone-benchmark.json`.
369
+
370
+ Use environment overrides to pin the benchmark envelope:
371
+
372
+ ```bash
373
+ CPUSET=0 CPUS=1.0 MEMORY=2g RUNS=16 WARMUPS=4 \
374
+ ./benchmarks/run_docker_benchmark.sh
375
+ ```
376
+
377
+ Performance claims are backed by the reproducible benchmark workflow documented
378
+ in [Benchmarking contract](https://orenlab.github.io/codeclone/book/18-benchmarking/)
379
+
380
+ </details>
381
+
382
+ ## Links
383
+
384
+ - **Issues:** <https://github.com/orenlab/codeclone/issues>
385
+ - **PyPI:** <https://pypi.org/project/codeclone/>
386
+ - **License:** MIT