desloppify 0.7.0__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 (471) hide show
  1. desloppify-0.7.0/LICENSE +21 -0
  2. desloppify-0.7.0/PKG-INFO +216 -0
  3. desloppify-0.7.0/README.md +187 -0
  4. desloppify-0.7.0/desloppify/__init__.py +3 -0
  5. desloppify-0.7.0/desloppify/__main__.py +5 -0
  6. desloppify-0.7.0/desloppify/app/__init__.py +1 -0
  7. desloppify-0.7.0/desloppify/app/cli_support/__init__.py +2 -0
  8. desloppify-0.7.0/desloppify/app/cli_support/parser.py +122 -0
  9. desloppify-0.7.0/desloppify/app/cli_support/parser_groups.py +243 -0
  10. desloppify-0.7.0/desloppify/app/cli_support/parser_groups_admin.py +320 -0
  11. desloppify-0.7.0/desloppify/app/commands/__init__.py +1 -0
  12. desloppify-0.7.0/desloppify/app/commands/_show_terminal.py +46 -0
  13. desloppify-0.7.0/desloppify/app/commands/config_cmd.py +95 -0
  14. desloppify-0.7.0/desloppify/app/commands/detect.py +89 -0
  15. desloppify-0.7.0/desloppify/app/commands/dev_cmd.py +174 -0
  16. desloppify-0.7.0/desloppify/app/commands/dev_scaffold_templates.py +264 -0
  17. desloppify-0.7.0/desloppify/app/commands/fix/__init__.py +5 -0
  18. desloppify-0.7.0/desloppify/app/commands/fix/apply_flow.py +323 -0
  19. desloppify-0.7.0/desloppify/app/commands/fix/cmd.py +70 -0
  20. desloppify-0.7.0/desloppify/app/commands/fix/io.py +15 -0
  21. desloppify-0.7.0/desloppify/app/commands/fix/options.py +33 -0
  22. desloppify-0.7.0/desloppify/app/commands/fix/review_flow.py +144 -0
  23. desloppify-0.7.0/desloppify/app/commands/helpers/__init__.py +1 -0
  24. desloppify-0.7.0/desloppify/app/commands/helpers/lang.py +133 -0
  25. desloppify-0.7.0/desloppify/app/commands/helpers/query.py +16 -0
  26. desloppify-0.7.0/desloppify/app/commands/helpers/rendering.py +69 -0
  27. desloppify-0.7.0/desloppify/app/commands/helpers/runtime.py +39 -0
  28. desloppify-0.7.0/desloppify/app/commands/helpers/runtime_options.py +49 -0
  29. desloppify-0.7.0/desloppify/app/commands/helpers/score.py +40 -0
  30. desloppify-0.7.0/desloppify/app/commands/helpers/state.py +31 -0
  31. desloppify-0.7.0/desloppify/app/commands/helpers/subjective.py +52 -0
  32. desloppify-0.7.0/desloppify/app/commands/issues_cmd.py +231 -0
  33. desloppify-0.7.0/desloppify/app/commands/langs.py +77 -0
  34. desloppify-0.7.0/desloppify/app/commands/move/__init__.py +0 -0
  35. desloppify-0.7.0/desloppify/app/commands/move/move.py +91 -0
  36. desloppify-0.7.0/desloppify/app/commands/move/move_apply.py +113 -0
  37. desloppify-0.7.0/desloppify/app/commands/move/move_directory.py +107 -0
  38. desloppify-0.7.0/desloppify/app/commands/move/move_language.py +101 -0
  39. desloppify-0.7.0/desloppify/app/commands/move/move_planning.py +179 -0
  40. desloppify-0.7.0/desloppify/app/commands/move/move_reporting.py +116 -0
  41. desloppify-0.7.0/desloppify/app/commands/next.py +166 -0
  42. desloppify-0.7.0/desloppify/app/commands/next_output.py +116 -0
  43. desloppify-0.7.0/desloppify/app/commands/next_render.py +395 -0
  44. desloppify-0.7.0/desloppify/app/commands/plan_cmd.py +36 -0
  45. desloppify-0.7.0/desloppify/app/commands/registry.py +64 -0
  46. desloppify-0.7.0/desloppify/app/commands/resolve/__init__.py +8 -0
  47. desloppify-0.7.0/desloppify/app/commands/resolve/apply.py +53 -0
  48. desloppify-0.7.0/desloppify/app/commands/resolve/cmd.py +183 -0
  49. desloppify-0.7.0/desloppify/app/commands/resolve/render.py +178 -0
  50. desloppify-0.7.0/desloppify/app/commands/resolve/selection.py +158 -0
  51. desloppify-0.7.0/desloppify/app/commands/review/__init__.py +2 -0
  52. desloppify-0.7.0/desloppify/app/commands/review/batch.py +195 -0
  53. desloppify-0.7.0/desloppify/app/commands/review/batch_core.py +669 -0
  54. desloppify-0.7.0/desloppify/app/commands/review/batches.py +183 -0
  55. desloppify-0.7.0/desloppify/app/commands/review/entrypoint.py +52 -0
  56. desloppify-0.7.0/desloppify/app/commands/review/import_cmd.py +137 -0
  57. desloppify-0.7.0/desloppify/app/commands/review/import_helpers.py +235 -0
  58. desloppify-0.7.0/desloppify/app/commands/review/output.py +72 -0
  59. desloppify-0.7.0/desloppify/app/commands/review/prepare.py +126 -0
  60. desloppify-0.7.0/desloppify/app/commands/review/runner_helpers.py +388 -0
  61. desloppify-0.7.0/desloppify/app/commands/review/runtime.py +69 -0
  62. desloppify-0.7.0/desloppify/app/commands/scan/__init__.py +0 -0
  63. desloppify-0.7.0/desloppify/app/commands/scan/scan.py +166 -0
  64. desloppify-0.7.0/desloppify/app/commands/scan/scan_artifacts.py +131 -0
  65. desloppify-0.7.0/desloppify/app/commands/scan/scan_helpers.py +170 -0
  66. desloppify-0.7.0/desloppify/app/commands/scan/scan_reporting_analysis.py +383 -0
  67. desloppify-0.7.0/desloppify/app/commands/scan/scan_reporting_dimensions.py +249 -0
  68. desloppify-0.7.0/desloppify/app/commands/scan/scan_reporting_llm.py +331 -0
  69. desloppify-0.7.0/desloppify/app/commands/scan/scan_reporting_presentation.py +291 -0
  70. desloppify-0.7.0/desloppify/app/commands/scan/scan_reporting_subjective.py +477 -0
  71. desloppify-0.7.0/desloppify/app/commands/scan/scan_reporting_summary.py +192 -0
  72. desloppify-0.7.0/desloppify/app/commands/scan/scan_workflow.py +530 -0
  73. desloppify-0.7.0/desloppify/app/commands/show/__init__.py +1 -0
  74. desloppify-0.7.0/desloppify/app/commands/show/cmd.py +155 -0
  75. desloppify-0.7.0/desloppify/app/commands/show/formatting.py +69 -0
  76. desloppify-0.7.0/desloppify/app/commands/show/payload.py +71 -0
  77. desloppify-0.7.0/desloppify/app/commands/show/render.py +266 -0
  78. desloppify-0.7.0/desloppify/app/commands/show/scope.py +75 -0
  79. desloppify-0.7.0/desloppify/app/commands/status.py +182 -0
  80. desloppify-0.7.0/desloppify/app/commands/status_parts/__init__.py +2 -0
  81. desloppify-0.7.0/desloppify/app/commands/status_parts/render.py +527 -0
  82. desloppify-0.7.0/desloppify/app/commands/status_parts/strict_target.py +52 -0
  83. desloppify-0.7.0/desloppify/app/commands/status_parts/summary.py +78 -0
  84. desloppify-0.7.0/desloppify/app/commands/update_skill.py +147 -0
  85. desloppify-0.7.0/desloppify/app/commands/viz_cmd.py +21 -0
  86. desloppify-0.7.0/desloppify/app/commands/zone_cmd.py +130 -0
  87. desloppify-0.7.0/desloppify/app/output/__init__.py +5 -0
  88. desloppify-0.7.0/desloppify/app/output/_viz_cmd_context.py +27 -0
  89. desloppify-0.7.0/desloppify/app/output/scorecard.py +199 -0
  90. desloppify-0.7.0/desloppify/app/output/scorecard_parts/__init__.py +17 -0
  91. desloppify-0.7.0/desloppify/app/output/scorecard_parts/dimension_policy.py +104 -0
  92. desloppify-0.7.0/desloppify/app/output/scorecard_parts/dimensions.py +242 -0
  93. desloppify-0.7.0/desloppify/app/output/scorecard_parts/draw.py +127 -0
  94. desloppify-0.7.0/desloppify/app/output/scorecard_parts/left_panel.py +340 -0
  95. desloppify-0.7.0/desloppify/app/output/scorecard_parts/meta.py +76 -0
  96. desloppify-0.7.0/desloppify/app/output/scorecard_parts/ornaments.py +57 -0
  97. desloppify-0.7.0/desloppify/app/output/scorecard_parts/projection.py +148 -0
  98. desloppify-0.7.0/desloppify/app/output/scorecard_parts/theme.py +127 -0
  99. desloppify-0.7.0/desloppify/app/output/tree_text.py +92 -0
  100. desloppify-0.7.0/desloppify/app/output/visualize.py +287 -0
  101. desloppify-0.7.0/desloppify/cli.py +148 -0
  102. desloppify-0.7.0/desloppify/conftest.py +20 -0
  103. desloppify-0.7.0/desloppify/core/__init__.py +7 -0
  104. desloppify-0.7.0/desloppify/core/_internal/__init__.py +2 -0
  105. desloppify-0.7.0/desloppify/core/_internal/text_utils.py +140 -0
  106. desloppify-0.7.0/desloppify/core/config.py +308 -0
  107. desloppify-0.7.0/desloppify/core/enums.py +31 -0
  108. desloppify-0.7.0/desloppify/core/fallbacks.py +48 -0
  109. desloppify-0.7.0/desloppify/core/issues_render.py +195 -0
  110. desloppify-0.7.0/desloppify/core/query.py +35 -0
  111. desloppify-0.7.0/desloppify/core/registry.py +395 -0
  112. desloppify-0.7.0/desloppify/core/runtime_state.py +111 -0
  113. desloppify-0.7.0/desloppify/core/signal_patterns.py +35 -0
  114. desloppify-0.7.0/desloppify/engine/__init__.py +1 -0
  115. desloppify-0.7.0/desloppify/engine/_scoring/__init__.py +1 -0
  116. desloppify-0.7.0/desloppify/engine/_scoring/detection.py +200 -0
  117. desloppify-0.7.0/desloppify/engine/_scoring/policy/__init__.py +2 -0
  118. desloppify-0.7.0/desloppify/engine/_scoring/policy/core.py +266 -0
  119. desloppify-0.7.0/desloppify/engine/_scoring/results/__init__.py +2 -0
  120. desloppify-0.7.0/desloppify/engine/_scoring/results/core.py +412 -0
  121. desloppify-0.7.0/desloppify/engine/_scoring/subjective/__init__.py +2 -0
  122. desloppify-0.7.0/desloppify/engine/_scoring/subjective/core.py +242 -0
  123. desloppify-0.7.0/desloppify/engine/_state/__init__.py +1 -0
  124. desloppify-0.7.0/desloppify/engine/_state/filtering.py +151 -0
  125. desloppify-0.7.0/desloppify/engine/_state/merge.py +153 -0
  126. desloppify-0.7.0/desloppify/engine/_state/merge_findings.py +203 -0
  127. desloppify-0.7.0/desloppify/engine/_state/merge_history.py +151 -0
  128. desloppify-0.7.0/desloppify/engine/_state/noise.py +198 -0
  129. desloppify-0.7.0/desloppify/engine/_state/persistence.py +156 -0
  130. desloppify-0.7.0/desloppify/engine/_state/resolution.py +149 -0
  131. desloppify-0.7.0/desloppify/engine/_state/schema.py +336 -0
  132. desloppify-0.7.0/desloppify/engine/_state/scoring.py +296 -0
  133. desloppify-0.7.0/desloppify/engine/_work_queue/__init__.py +1 -0
  134. desloppify-0.7.0/desloppify/engine/_work_queue/core.py +154 -0
  135. desloppify-0.7.0/desloppify/engine/_work_queue/helpers.py +297 -0
  136. desloppify-0.7.0/desloppify/engine/_work_queue/issues.py +102 -0
  137. desloppify-0.7.0/desloppify/engine/_work_queue/ranking.py +210 -0
  138. desloppify-0.7.0/desloppify/engine/concerns.py +449 -0
  139. desloppify-0.7.0/desloppify/engine/detectors/__init__.py +7 -0
  140. desloppify-0.7.0/desloppify/engine/detectors/base.py +69 -0
  141. desloppify-0.7.0/desloppify/engine/detectors/complexity.py +82 -0
  142. desloppify-0.7.0/desloppify/engine/detectors/coupling.py +146 -0
  143. desloppify-0.7.0/desloppify/engine/detectors/coverage/__init__.py +2 -0
  144. desloppify-0.7.0/desloppify/engine/detectors/coverage/mapping.py +365 -0
  145. desloppify-0.7.0/desloppify/engine/detectors/dupes.py +260 -0
  146. desloppify-0.7.0/desloppify/engine/detectors/flat_dirs.py +21 -0
  147. desloppify-0.7.0/desloppify/engine/detectors/gods.py +25 -0
  148. desloppify-0.7.0/desloppify/engine/detectors/graph.py +153 -0
  149. desloppify-0.7.0/desloppify/engine/detectors/jscpd_adapter.py +150 -0
  150. desloppify-0.7.0/desloppify/engine/detectors/large.py +34 -0
  151. desloppify-0.7.0/desloppify/engine/detectors/naming.py +86 -0
  152. desloppify-0.7.0/desloppify/engine/detectors/orphaned.py +100 -0
  153. desloppify-0.7.0/desloppify/engine/detectors/passthrough.py +68 -0
  154. desloppify-0.7.0/desloppify/engine/detectors/patterns/__init__.py +2 -0
  155. desloppify-0.7.0/desloppify/engine/detectors/patterns/security.py +177 -0
  156. desloppify-0.7.0/desloppify/engine/detectors/review_coverage.py +267 -0
  157. desloppify-0.7.0/desloppify/engine/detectors/security/__init__.py +5 -0
  158. desloppify-0.7.0/desloppify/engine/detectors/security/detector.py +54 -0
  159. desloppify-0.7.0/desloppify/engine/detectors/security/filters.py +28 -0
  160. desloppify-0.7.0/desloppify/engine/detectors/security/rules.py +201 -0
  161. desloppify-0.7.0/desloppify/engine/detectors/security/scanner.py +30 -0
  162. desloppify-0.7.0/desloppify/engine/detectors/signature.py +147 -0
  163. desloppify-0.7.0/desloppify/engine/detectors/single_use.py +85 -0
  164. desloppify-0.7.0/desloppify/engine/detectors/test_coverage/__init__.py +7 -0
  165. desloppify-0.7.0/desloppify/engine/detectors/test_coverage/detector.py +299 -0
  166. desloppify-0.7.0/desloppify/engine/detectors/test_coverage/discovery.py +126 -0
  167. desloppify-0.7.0/desloppify/engine/detectors/test_coverage/heuristics.py +60 -0
  168. desloppify-0.7.0/desloppify/engine/detectors/test_coverage/metrics.py +40 -0
  169. desloppify-0.7.0/desloppify/engine/planning/__init__.py +7 -0
  170. desloppify-0.7.0/desloppify/engine/planning/common.py +23 -0
  171. desloppify-0.7.0/desloppify/engine/planning/core.py +15 -0
  172. desloppify-0.7.0/desloppify/engine/planning/dimension_rows.py +65 -0
  173. desloppify-0.7.0/desloppify/engine/planning/render.py +302 -0
  174. desloppify-0.7.0/desloppify/engine/planning/scan.py +151 -0
  175. desloppify-0.7.0/desloppify/engine/planning/select.py +44 -0
  176. desloppify-0.7.0/desloppify/engine/planning/types.py +34 -0
  177. desloppify-0.7.0/desloppify/engine/policy/__init__.py +2 -0
  178. desloppify-0.7.0/desloppify/engine/policy/zones.py +275 -0
  179. desloppify-0.7.0/desloppify/engine/policy/zones_data.py +55 -0
  180. desloppify-0.7.0/desloppify/engine/work_queue.py +83 -0
  181. desloppify-0.7.0/desloppify/file_discovery.py +248 -0
  182. desloppify-0.7.0/desloppify/hook_registry.py +67 -0
  183. desloppify-0.7.0/desloppify/intelligence/__init__.py +29 -0
  184. desloppify-0.7.0/desloppify/intelligence/integrity.py +110 -0
  185. desloppify-0.7.0/desloppify/intelligence/narrative/__init__.py +25 -0
  186. desloppify-0.7.0/desloppify/intelligence/narrative/_constants.py +43 -0
  187. desloppify-0.7.0/desloppify/intelligence/narrative/action_engine.py +265 -0
  188. desloppify-0.7.0/desloppify/intelligence/narrative/action_models.py +73 -0
  189. desloppify-0.7.0/desloppify/intelligence/narrative/action_tools.py +79 -0
  190. desloppify-0.7.0/desloppify/intelligence/narrative/core.py +393 -0
  191. desloppify-0.7.0/desloppify/intelligence/narrative/dimensions.py +217 -0
  192. desloppify-0.7.0/desloppify/intelligence/narrative/headline.py +157 -0
  193. desloppify-0.7.0/desloppify/intelligence/narrative/phase.py +90 -0
  194. desloppify-0.7.0/desloppify/intelligence/narrative/reminders.py +482 -0
  195. desloppify-0.7.0/desloppify/intelligence/narrative/strategy_engine.py +337 -0
  196. desloppify-0.7.0/desloppify/intelligence/narrative/types.py +157 -0
  197. desloppify-0.7.0/desloppify/intelligence/review/__init__.py +103 -0
  198. desloppify-0.7.0/desloppify/intelligence/review/_context/__init__.py +1 -0
  199. desloppify-0.7.0/desloppify/intelligence/review/_context/models.py +90 -0
  200. desloppify-0.7.0/desloppify/intelligence/review/_context/patterns.py +70 -0
  201. desloppify-0.7.0/desloppify/intelligence/review/_context/structure.py +126 -0
  202. desloppify-0.7.0/desloppify/intelligence/review/_prepare/__init__.py +1 -0
  203. desloppify-0.7.0/desloppify/intelligence/review/_prepare/helpers.py +47 -0
  204. desloppify-0.7.0/desloppify/intelligence/review/_prepare/remediation_engine.py +210 -0
  205. desloppify-0.7.0/desloppify/intelligence/review/context.py +269 -0
  206. desloppify-0.7.0/desloppify/intelligence/review/context_holistic/__init__.py +10 -0
  207. desloppify-0.7.0/desloppify/intelligence/review/context_holistic/budget.py +220 -0
  208. desloppify-0.7.0/desloppify/intelligence/review/context_holistic/orchestrator.py +103 -0
  209. desloppify-0.7.0/desloppify/intelligence/review/context_holistic/readers.py +19 -0
  210. desloppify-0.7.0/desloppify/intelligence/review/context_holistic/selection.py +237 -0
  211. desloppify-0.7.0/desloppify/intelligence/review/context_holistic/types.py +5 -0
  212. desloppify-0.7.0/desloppify/intelligence/review/context_signals/__init__.py +1 -0
  213. desloppify-0.7.0/desloppify/intelligence/review/context_signals/ai.py +72 -0
  214. desloppify-0.7.0/desloppify/intelligence/review/context_signals/auth.py +166 -0
  215. desloppify-0.7.0/desloppify/intelligence/review/context_signals/migration.py +170 -0
  216. desloppify-0.7.0/desloppify/intelligence/review/dimensions/__init__.py +50 -0
  217. desloppify-0.7.0/desloppify/intelligence/review/dimensions/data.py +202 -0
  218. desloppify-0.7.0/desloppify/intelligence/review/dimensions/holistic.py +7 -0
  219. desloppify-0.7.0/desloppify/intelligence/review/dimensions/lang.py +62 -0
  220. desloppify-0.7.0/desloppify/intelligence/review/dimensions/metadata.py +282 -0
  221. desloppify-0.7.0/desloppify/intelligence/review/dimensions/selection.py +46 -0
  222. desloppify-0.7.0/desloppify/intelligence/review/dimensions/validation.py +219 -0
  223. desloppify-0.7.0/desloppify/intelligence/review/importing/__init__.py +25 -0
  224. desloppify-0.7.0/desloppify/intelligence/review/importing/holistic.py +383 -0
  225. desloppify-0.7.0/desloppify/intelligence/review/importing/per_file.py +189 -0
  226. desloppify-0.7.0/desloppify/intelligence/review/importing/shared.py +98 -0
  227. desloppify-0.7.0/desloppify/intelligence/review/policy.py +160 -0
  228. desloppify-0.7.0/desloppify/intelligence/review/prepare.py +303 -0
  229. desloppify-0.7.0/desloppify/intelligence/review/prepare_batches.py +492 -0
  230. desloppify-0.7.0/desloppify/intelligence/review/remediation.py +10 -0
  231. desloppify-0.7.0/desloppify/intelligence/review/selection.py +253 -0
  232. desloppify-0.7.0/desloppify/languages/__init__.py +72 -0
  233. desloppify-0.7.0/desloppify/languages/_framework/__init__.py +33 -0
  234. desloppify-0.7.0/desloppify/languages/_framework/base/__init__.py +1 -0
  235. desloppify-0.7.0/desloppify/languages/_framework/base/phase_builders.py +65 -0
  236. desloppify-0.7.0/desloppify/languages/_framework/base/shared_phases.py +470 -0
  237. desloppify-0.7.0/desloppify/languages/_framework/base/structural.py +82 -0
  238. desloppify-0.7.0/desloppify/languages/_framework/base/types.py +299 -0
  239. desloppify-0.7.0/desloppify/languages/_framework/commands_base.py +499 -0
  240. desloppify-0.7.0/desloppify/languages/_framework/contract_validation.py +132 -0
  241. desloppify-0.7.0/desloppify/languages/_framework/discovery.py +91 -0
  242. desloppify-0.7.0/desloppify/languages/_framework/facade_common.py +41 -0
  243. desloppify-0.7.0/desloppify/languages/_framework/finding_factories.py +290 -0
  244. desloppify-0.7.0/desloppify/languages/_framework/generic.py +612 -0
  245. desloppify-0.7.0/desloppify/languages/_framework/policy.py +32 -0
  246. desloppify-0.7.0/desloppify/languages/_framework/registry_state.py +93 -0
  247. desloppify-0.7.0/desloppify/languages/_framework/resolution.py +84 -0
  248. desloppify-0.7.0/desloppify/languages/_framework/review_data/__init__.py +1 -0
  249. desloppify-0.7.0/desloppify/languages/_framework/review_data/dimensions.json +375 -0
  250. desloppify-0.7.0/desloppify/languages/_framework/runtime.py +182 -0
  251. desloppify-0.7.0/desloppify/languages/_framework/structure_validation.py +32 -0
  252. desloppify-0.7.0/desloppify/languages/_framework/treesitter/__init__.py +116 -0
  253. desloppify-0.7.0/desloppify/languages/_framework/treesitter/_cache.py +69 -0
  254. desloppify-0.7.0/desloppify/languages/_framework/treesitter/_cohesion.py +132 -0
  255. desloppify-0.7.0/desloppify/languages/_framework/treesitter/_complexity.py +361 -0
  256. desloppify-0.7.0/desloppify/languages/_framework/treesitter/_extractors.py +239 -0
  257. desloppify-0.7.0/desloppify/languages/_framework/treesitter/_imports.py +748 -0
  258. desloppify-0.7.0/desloppify/languages/_framework/treesitter/_normalize.py +90 -0
  259. desloppify-0.7.0/desloppify/languages/_framework/treesitter/_smells.py +210 -0
  260. desloppify-0.7.0/desloppify/languages/_framework/treesitter/_specs.py +801 -0
  261. desloppify-0.7.0/desloppify/languages/_framework/treesitter/_unused_imports.py +122 -0
  262. desloppify-0.7.0/desloppify/languages/_framework/treesitter/phases.py +160 -0
  263. desloppify-0.7.0/desloppify/languages/bash/__init__.py +21 -0
  264. desloppify-0.7.0/desloppify/languages/clojure/__init__.py +22 -0
  265. desloppify-0.7.0/desloppify/languages/csharp/__init__.py +168 -0
  266. desloppify-0.7.0/desloppify/languages/csharp/_parse_helpers.py +150 -0
  267. desloppify-0.7.0/desloppify/languages/csharp/commands.py +134 -0
  268. desloppify-0.7.0/desloppify/languages/csharp/deps/__init__.py +2 -0
  269. desloppify-0.7.0/desloppify/languages/csharp/deps/cli.py +85 -0
  270. desloppify-0.7.0/desloppify/languages/csharp/detectors/__init__.py +4 -0
  271. desloppify-0.7.0/desloppify/languages/csharp/detectors/deps.py +606 -0
  272. desloppify-0.7.0/desloppify/languages/csharp/detectors/security.py +131 -0
  273. desloppify-0.7.0/desloppify/languages/csharp/extractors.py +166 -0
  274. desloppify-0.7.0/desloppify/languages/csharp/extractors_classes.py +166 -0
  275. desloppify-0.7.0/desloppify/languages/csharp/fixers/__init__.py +4 -0
  276. desloppify-0.7.0/desloppify/languages/csharp/move.py +45 -0
  277. desloppify-0.7.0/desloppify/languages/csharp/phases.py +200 -0
  278. desloppify-0.7.0/desloppify/languages/csharp/review.py +101 -0
  279. desloppify-0.7.0/desloppify/languages/csharp/review_data/__init__.py +1 -0
  280. desloppify-0.7.0/desloppify/languages/csharp/review_data/dimensions.override.json +22 -0
  281. desloppify-0.7.0/desloppify/languages/csharp/review_data/holistic_dimensions.override.json +19 -0
  282. desloppify-0.7.0/desloppify/languages/csharp/test_coverage.py +169 -0
  283. desloppify-0.7.0/desloppify/languages/csharp/tests/__init__.py +1 -0
  284. desloppify-0.7.0/desloppify/languages/csharp/tests/test_csharp_deps_cli.py +356 -0
  285. desloppify-0.7.0/desloppify/languages/csharp/tests/test_csharp_parse_helpers.py +260 -0
  286. desloppify-0.7.0/desloppify/languages/csharp/tests/test_smoke.py +2 -0
  287. desloppify-0.7.0/desloppify/languages/cxx/__init__.py +23 -0
  288. desloppify-0.7.0/desloppify/languages/dart/__init__.py +107 -0
  289. desloppify-0.7.0/desloppify/languages/dart/commands.py +82 -0
  290. desloppify-0.7.0/desloppify/languages/dart/detectors/__init__.py +0 -0
  291. desloppify-0.7.0/desloppify/languages/dart/detectors/deps.py +110 -0
  292. desloppify-0.7.0/desloppify/languages/dart/extractors.py +164 -0
  293. desloppify-0.7.0/desloppify/languages/dart/fixers/__init__.py +0 -0
  294. desloppify-0.7.0/desloppify/languages/dart/move.py +25 -0
  295. desloppify-0.7.0/desloppify/languages/dart/phases.py +61 -0
  296. desloppify-0.7.0/desloppify/languages/dart/pubspec.py +24 -0
  297. desloppify-0.7.0/desloppify/languages/dart/review.py +76 -0
  298. desloppify-0.7.0/desloppify/languages/dart/review_data/__init__.py +1 -0
  299. desloppify-0.7.0/desloppify/languages/dart/review_data/dimensions.override.json +1 -0
  300. desloppify-0.7.0/desloppify/languages/dart/review_data/holistic_dimensions.override.json +1 -0
  301. desloppify-0.7.0/desloppify/languages/dart/test_coverage.py +149 -0
  302. desloppify-0.7.0/desloppify/languages/dart/tests/__init__.py +1 -0
  303. desloppify-0.7.0/desloppify/languages/dart/tests/test_init.py +49 -0
  304. desloppify-0.7.0/desloppify/languages/elixir/__init__.py +23 -0
  305. desloppify-0.7.0/desloppify/languages/erlang/__init__.py +22 -0
  306. desloppify-0.7.0/desloppify/languages/fsharp/__init__.py +22 -0
  307. desloppify-0.7.0/desloppify/languages/gdscript/__init__.py +100 -0
  308. desloppify-0.7.0/desloppify/languages/gdscript/commands.py +78 -0
  309. desloppify-0.7.0/desloppify/languages/gdscript/detectors/__init__.py +0 -0
  310. desloppify-0.7.0/desloppify/languages/gdscript/detectors/deps.py +83 -0
  311. desloppify-0.7.0/desloppify/languages/gdscript/extractors.py +102 -0
  312. desloppify-0.7.0/desloppify/languages/gdscript/fixers/__init__.py +0 -0
  313. desloppify-0.7.0/desloppify/languages/gdscript/move.py +25 -0
  314. desloppify-0.7.0/desloppify/languages/gdscript/patterns.py +12 -0
  315. desloppify-0.7.0/desloppify/languages/gdscript/phases.py +56 -0
  316. desloppify-0.7.0/desloppify/languages/gdscript/review.py +68 -0
  317. desloppify-0.7.0/desloppify/languages/gdscript/review_data/__init__.py +1 -0
  318. desloppify-0.7.0/desloppify/languages/gdscript/review_data/dimensions.override.json +1 -0
  319. desloppify-0.7.0/desloppify/languages/gdscript/review_data/holistic_dimensions.override.json +1 -0
  320. desloppify-0.7.0/desloppify/languages/gdscript/test_coverage.py +95 -0
  321. desloppify-0.7.0/desloppify/languages/gdscript/tests/__init__.py +1 -0
  322. desloppify-0.7.0/desloppify/languages/gdscript/tests/test_init.py +49 -0
  323. desloppify-0.7.0/desloppify/languages/go/__init__.py +42 -0
  324. desloppify-0.7.0/desloppify/languages/go/test_coverage.py +120 -0
  325. desloppify-0.7.0/desloppify/languages/go/tests/__init__.py +0 -0
  326. desloppify-0.7.0/desloppify/languages/go/tests/test_init.py +78 -0
  327. desloppify-0.7.0/desloppify/languages/haskell/__init__.py +23 -0
  328. desloppify-0.7.0/desloppify/languages/java/__init__.py +23 -0
  329. desloppify-0.7.0/desloppify/languages/javascript/__init__.py +24 -0
  330. desloppify-0.7.0/desloppify/languages/kotlin/__init__.py +23 -0
  331. desloppify-0.7.0/desloppify/languages/lua/__init__.py +21 -0
  332. desloppify-0.7.0/desloppify/languages/nim/__init__.py +22 -0
  333. desloppify-0.7.0/desloppify/languages/ocaml/__init__.py +22 -0
  334. desloppify-0.7.0/desloppify/languages/perl/__init__.py +21 -0
  335. desloppify-0.7.0/desloppify/languages/php/__init__.py +23 -0
  336. desloppify-0.7.0/desloppify/languages/powershell/__init__.py +24 -0
  337. desloppify-0.7.0/desloppify/languages/python/__init__.py +172 -0
  338. desloppify-0.7.0/desloppify/languages/python/commands.py +217 -0
  339. desloppify-0.7.0/desloppify/languages/python/detectors/__init__.py +0 -0
  340. desloppify-0.7.0/desloppify/languages/python/detectors/bandit_adapter.py +167 -0
  341. desloppify-0.7.0/desloppify/languages/python/detectors/complexity.py +108 -0
  342. desloppify-0.7.0/desloppify/languages/python/detectors/coupling_contracts.py +122 -0
  343. desloppify-0.7.0/desloppify/languages/python/detectors/deps.py +306 -0
  344. desloppify-0.7.0/desloppify/languages/python/detectors/dict_keys.py +336 -0
  345. desloppify-0.7.0/desloppify/languages/python/detectors/dict_keys_visitor.py +470 -0
  346. desloppify-0.7.0/desloppify/languages/python/detectors/facade.py +111 -0
  347. desloppify-0.7.0/desloppify/languages/python/detectors/import_linter_adapter.py +114 -0
  348. desloppify-0.7.0/desloppify/languages/python/detectors/mutable_state.py +341 -0
  349. desloppify-0.7.0/desloppify/languages/python/detectors/private_imports.py +164 -0
  350. desloppify-0.7.0/desloppify/languages/python/detectors/responsibility_cohesion.py +169 -0
  351. desloppify-0.7.0/desloppify/languages/python/detectors/ruff_smells.py +148 -0
  352. desloppify-0.7.0/desloppify/languages/python/detectors/smells.py +431 -0
  353. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/__init__.py +30 -0
  354. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_dispatch.py +202 -0
  355. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_node_detectors.py +177 -0
  356. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_shared.py +107 -0
  357. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_source_detectors.py +244 -0
  358. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_tree_context_detectors.py +148 -0
  359. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_tree_quality_detectors.py +263 -0
  360. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_tree_quality_detectors_types.py +145 -0
  361. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_tree_safety_detectors.py +246 -0
  362. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_tree_safety_detectors_runtime.py +210 -0
  363. desloppify-0.7.0/desloppify/languages/python/detectors/smells_ast/_types.py +57 -0
  364. desloppify-0.7.0/desloppify/languages/python/detectors/uncalled.py +120 -0
  365. desloppify-0.7.0/desloppify/languages/python/detectors/unused.py +200 -0
  366. desloppify-0.7.0/desloppify/languages/python/extractors.py +208 -0
  367. desloppify-0.7.0/desloppify/languages/python/extractors_classes.py +131 -0
  368. desloppify-0.7.0/desloppify/languages/python/extractors_shared.py +51 -0
  369. desloppify-0.7.0/desloppify/languages/python/fixers/__init__.py +4 -0
  370. desloppify-0.7.0/desloppify/languages/python/move.py +236 -0
  371. desloppify-0.7.0/desloppify/languages/python/phases.py +370 -0
  372. desloppify-0.7.0/desloppify/languages/python/phases_quality.py +179 -0
  373. desloppify-0.7.0/desloppify/languages/python/review.py +70 -0
  374. desloppify-0.7.0/desloppify/languages/python/review_data/__init__.py +1 -0
  375. desloppify-0.7.0/desloppify/languages/python/review_data/dimensions.override.json +21 -0
  376. desloppify-0.7.0/desloppify/languages/python/review_data/holistic_dimensions.override.json +19 -0
  377. desloppify-0.7.0/desloppify/languages/python/test_coverage.py +162 -0
  378. desloppify-0.7.0/desloppify/languages/python/tests/__init__.py +1 -0
  379. desloppify-0.7.0/desloppify/languages/python/tests/test_py_commands.py +49 -0
  380. desloppify-0.7.0/desloppify/languages/python/tests/test_py_complexity.py +187 -0
  381. desloppify-0.7.0/desloppify/languages/python/tests/test_py_coupling_contracts.py +66 -0
  382. desloppify-0.7.0/desloppify/languages/python/tests/test_py_deps.py +339 -0
  383. desloppify-0.7.0/desloppify/languages/python/tests/test_py_dict_keys.py +347 -0
  384. desloppify-0.7.0/desloppify/languages/python/tests/test_py_extractors.py +347 -0
  385. desloppify-0.7.0/desloppify/languages/python/tests/test_py_facade.py +160 -0
  386. desloppify-0.7.0/desloppify/languages/python/tests/test_py_init.py +156 -0
  387. desloppify-0.7.0/desloppify/languages/python/tests/test_py_move.py +72 -0
  388. desloppify-0.7.0/desloppify/languages/python/tests/test_py_mutable_state.py +238 -0
  389. desloppify-0.7.0/desloppify/languages/python/tests/test_py_private_imports.py +54 -0
  390. desloppify-0.7.0/desloppify/languages/python/tests/test_py_responsibility_cohesion.py +81 -0
  391. desloppify-0.7.0/desloppify/languages/python/tests/test_py_smells.py +818 -0
  392. desloppify-0.7.0/desloppify/languages/python/tests/test_py_smells_ast_perf.py +30 -0
  393. desloppify-0.7.0/desloppify/languages/python/tests/test_py_uncalled.py +338 -0
  394. desloppify-0.7.0/desloppify/languages/python/tests/test_py_unused.py +238 -0
  395. desloppify-0.7.0/desloppify/languages/r/__init__.py +28 -0
  396. desloppify-0.7.0/desloppify/languages/ruby/__init__.py +23 -0
  397. desloppify-0.7.0/desloppify/languages/rust/__init__.py +31 -0
  398. desloppify-0.7.0/desloppify/languages/scala/__init__.py +23 -0
  399. desloppify-0.7.0/desloppify/languages/swift/__init__.py +22 -0
  400. desloppify-0.7.0/desloppify/languages/typescript/__init__.py +297 -0
  401. desloppify-0.7.0/desloppify/languages/typescript/commands.py +336 -0
  402. desloppify-0.7.0/desloppify/languages/typescript/detectors/__init__.py +0 -0
  403. desloppify-0.7.0/desloppify/languages/typescript/detectors/_smell_detectors.py +336 -0
  404. desloppify-0.7.0/desloppify/languages/typescript/detectors/_smell_effects.py +269 -0
  405. desloppify-0.7.0/desloppify/languages/typescript/detectors/_smell_helpers.py +226 -0
  406. desloppify-0.7.0/desloppify/languages/typescript/detectors/concerns.py +103 -0
  407. desloppify-0.7.0/desloppify/languages/typescript/detectors/contracts.py +24 -0
  408. desloppify-0.7.0/desloppify/languages/typescript/detectors/deprecated.py +220 -0
  409. desloppify-0.7.0/desloppify/languages/typescript/detectors/deps.py +398 -0
  410. desloppify-0.7.0/desloppify/languages/typescript/detectors/deps_runtime.py +56 -0
  411. desloppify-0.7.0/desloppify/languages/typescript/detectors/exports.py +47 -0
  412. desloppify-0.7.0/desloppify/languages/typescript/detectors/facade.py +60 -0
  413. desloppify-0.7.0/desloppify/languages/typescript/detectors/knip_adapter.py +114 -0
  414. desloppify-0.7.0/desloppify/languages/typescript/detectors/logs.py +142 -0
  415. desloppify-0.7.0/desloppify/languages/typescript/detectors/patterns.py +327 -0
  416. desloppify-0.7.0/desloppify/languages/typescript/detectors/props.py +112 -0
  417. desloppify-0.7.0/desloppify/languages/typescript/detectors/react.py +485 -0
  418. desloppify-0.7.0/desloppify/languages/typescript/detectors/security.py +373 -0
  419. desloppify-0.7.0/desloppify/languages/typescript/detectors/smells.py +520 -0
  420. desloppify-0.7.0/desloppify/languages/typescript/detectors/unused.py +359 -0
  421. desloppify-0.7.0/desloppify/languages/typescript/extractors.py +248 -0
  422. desloppify-0.7.0/desloppify/languages/typescript/extractors_components.py +183 -0
  423. desloppify-0.7.0/desloppify/languages/typescript/fixers/__init__.py +37 -0
  424. desloppify-0.7.0/desloppify/languages/typescript/fixers/common.py +439 -0
  425. desloppify-0.7.0/desloppify/languages/typescript/fixers/if_chain.py +69 -0
  426. desloppify-0.7.0/desloppify/languages/typescript/fixers/imports.py +231 -0
  427. desloppify-0.7.0/desloppify/languages/typescript/fixers/logs.py +315 -0
  428. desloppify-0.7.0/desloppify/languages/typescript/fixers/params.py +103 -0
  429. desloppify-0.7.0/desloppify/languages/typescript/fixers/useeffect.py +44 -0
  430. desloppify-0.7.0/desloppify/languages/typescript/fixers/vars.py +212 -0
  431. desloppify-0.7.0/desloppify/languages/typescript/move.py +156 -0
  432. desloppify-0.7.0/desloppify/languages/typescript/phases.py +675 -0
  433. desloppify-0.7.0/desloppify/languages/typescript/review.py +100 -0
  434. desloppify-0.7.0/desloppify/languages/typescript/review_data/__init__.py +1 -0
  435. desloppify-0.7.0/desloppify/languages/typescript/review_data/dimensions.override.json +22 -0
  436. desloppify-0.7.0/desloppify/languages/typescript/review_data/holistic_dimensions.override.json +19 -0
  437. desloppify-0.7.0/desloppify/languages/typescript/test_coverage.py +279 -0
  438. desloppify-0.7.0/desloppify/languages/typescript/tests/__init__.py +1 -0
  439. desloppify-0.7.0/desloppify/languages/typescript/tests/smells/test_ts_smell_helpers.py +401 -0
  440. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_commands.py +60 -0
  441. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_concerns.py +207 -0
  442. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_deprecated.py +218 -0
  443. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_deps.py +566 -0
  444. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_detector_contracts.py +97 -0
  445. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_exports_detector.py +154 -0
  446. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_extractors.py +326 -0
  447. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_facade.py +99 -0
  448. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_fixers.py +766 -0
  449. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_init.py +90 -0
  450. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_logs.py +135 -0
  451. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_move.py +43 -0
  452. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_patterns.py +211 -0
  453. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_phases.py +171 -0
  454. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_props.py +148 -0
  455. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_react.py +369 -0
  456. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_smells.py +441 -0
  457. desloppify-0.7.0/desloppify/languages/typescript/tests/test_ts_unused.py +209 -0
  458. desloppify-0.7.0/desloppify/languages/zig/__init__.py +22 -0
  459. desloppify-0.7.0/desloppify/scoring.py +82 -0
  460. desloppify-0.7.0/desloppify/search.py +76 -0
  461. desloppify-0.7.0/desloppify/state.py +128 -0
  462. desloppify-0.7.0/desloppify/utils.py +331 -0
  463. desloppify-0.7.0/desloppify/versioning.py +42 -0
  464. desloppify-0.7.0/desloppify.egg-info/PKG-INFO +216 -0
  465. desloppify-0.7.0/desloppify.egg-info/SOURCES.txt +469 -0
  466. desloppify-0.7.0/desloppify.egg-info/dependency_links.txt +1 -0
  467. desloppify-0.7.0/desloppify.egg-info/entry_points.txt +2 -0
  468. desloppify-0.7.0/desloppify.egg-info/requires.txt +4 -0
  469. desloppify-0.7.0/desloppify.egg-info/top_level.txt +1 -0
  470. desloppify-0.7.0/pyproject.toml +92 -0
  471. desloppify-0.7.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Peter O'Malley
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: desloppify
3
+ Version: 0.7.0
4
+ Summary: Multi-language codebase health scanner and technical debt tracker
5
+ Author-email: Peter O'Malley <pete@banodoco.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/peteromallet/desloppify
8
+ Project-URL: Repository, https://github.com/peteromallet/desloppify
9
+ Project-URL: Issues, https://github.com/peteromallet/desloppify/issues
10
+ Keywords: code-quality,technical-debt,linter,static-analysis,refactoring
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Quality Assurance
20
+ Classifier: Topic :: Software Development :: Testing
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: Pillow>=9.0.0
26
+ Provides-Extra: treesitter
27
+ Requires-Dist: tree-sitter-language-pack>=0.3; extra == "treesitter"
28
+ Dynamic: license-file
29
+
30
+ # Desloppify - an agent harness to make your codebase 🤌
31
+
32
+ Desloppify gives your AI coding agent the tools to identify, understand, and systematically improve codebase quality. It finds issues in two ways:
33
+
34
+ 1. **Subjective** — Examines the codebase from multiple subjective perspectives: abstraction quality, naming consistency, module boundaries, error handling patterns, convention drift, and language-specific questions. LLM evaluation scores these and tracks them as findings.
35
+
36
+ 2. **Mechanical** — Detects common mechanical issues like unused imports, dead code, overly long functions, duplication, and dependency cycles. Questionable issues are also flagged to the subjective agent for review.
37
+
38
+ Your agent works through a prioritized list — auto-fixing what it can, presenting the rest for your judgment. State persists across scans so it chips away over multiple sessions, and the scoring is designed to resist gaming: attestation requirements, strict scoring that penalizes dismissed issues, and cross-checked subjective assessments.
39
+
40
+ This produces a combined health score — our goal is that a score above 98 correlates with a codebase a seasoned engineer would call beautiful. That score generates a scorecard badge for your GitHub profile or README:
41
+
42
+ <img src="assets/scorecard.png" width="100%">
43
+
44
+ Currently supports 28 languages — full plugin depth for TypeScript, Python, C#, Dart, and GDScript; generic linter + tree-sitter support for Go, Rust, Ruby, Java, Kotlin, and 18 more.
45
+
46
+ ## For your agent's consideration...
47
+
48
+ Paste this prompt into your agent:
49
+
50
+ ```
51
+ Install or update desloppify, then scan this codebase for code quality issues (dead code,
52
+ duplication, complexity, smells). It tracks findings persistently across sessions and reports
53
+ a health score — state is cumulative, so each scan builds on previous progress.
54
+
55
+ pip install --upgrade git+https://github.com/peteromallet/desloppify.git
56
+ desloppify update-skill claude # pick yours: claude, cursor, codex, copilot, windsurf, gemini
57
+ desloppify scan --path .
58
+ desloppify status
59
+ desloppify next
60
+
61
+ --path is the directory to scan (use "." for the whole project, or "src/" etc).
62
+ Language is auto-detected. To override: desloppify --lang python scan --path .
63
+ (note: --lang goes BEFORE the subcommand)
64
+
65
+ Fix what it finds, then "desloppify resolve fixed <id> --note 'what changed' --attest 'I have actually [DESCRIBE THE CONCRETE CHANGE YOU MADE] and I am not gaming the score by resolving without fixing.'" and rescan.
66
+ For false positives: "desloppify resolve wontfix <id> --note 'reason' --attest 'I have actually verified this is intentional/false-positive and I am not gaming the score by resolving without fixing.'" (note is required — don't skip work; attestation must include the keywords "I have actually" and "not gaming").
67
+ Keep going until all issues are resolved.
68
+
69
+ If subjective scores feel stale or inflated, force a clean baseline:
70
+ desloppify scan --path . --reset-subjective
71
+
72
+ Because state persists, desloppify works best when run regularly. Ask the user if they'd
73
+ like to add a desloppify scan to their workflow — for example, adding "run desloppify scan
74
+ before each git push" to their CLAUDE.md, AGENTS.md, or equivalent agent instructions file,
75
+ so code health is checked at a natural interval.
76
+
77
+ If you notice anything wrong or confusing about
78
+ desloppify itself, tell me and ask if I want you to log an issue. If you need to understand
79
+ how desloppify works or debug an issue: git clone https://github.com/peteromallet/desloppify.git /tmp/desloppify
80
+ ```
81
+
82
+ ## From Vibe Coding to Vibe Engineering
83
+
84
+ Vibe coding gets things built fast. But the codebases it produces tend to rot in ways that are hard to see and harder to fix — not just the mechanical stuff like dead imports, but the structural kind. Abstractions that made sense at first stop making sense. Naming drifts. Error handling is done three different ways. The codebase works, but working in it gets worse over time.
85
+
86
+ LLMs are actually good at spotting this now, if you ask them the right questions. That's the core bet here — that an agent with the right framework can hold a codebase to a real standard, the kind that used to require a senior engineer paying close attention over months.
87
+
88
+ So we're trying to define what "good" looks like as a score that's actually worth optimizing. Not a lint score you game to 100 by suppressing warnings. Something where improving the number means the codebase genuinely got better. That's hard, and we're not done, but the anti-gaming stuff matters to us a lot — it's the difference between a useful signal and a vanity metric.
89
+
90
+ The hope is that anyone can use this to build something a seasoned engineer would look at and respect. That's the bar we're aiming for.
91
+
92
+ If you'd like to join a community of vibe engineers who want to build beautiful things, [come hang out](https://discord.gg/aZdzbZrHaY).
93
+
94
+ <img src="docs/engineering.png" width="100%">
95
+
96
+ ---
97
+
98
+ <details>
99
+ <summary><strong>Stuff you probably won't need to know</strong></summary>
100
+
101
+ #### Commands
102
+
103
+ | Command | Description |
104
+ |---------|-------------|
105
+ | `scan [--reset-subjective]` | Run all detectors, update state (optional: reset subjective baseline to 0 first) |
106
+ | `status` | Score + per-tier progress |
107
+ | `show <pattern>` | Findings by file, directory, detector, or ID |
108
+ | `next [--tier N] [--explain]` | Highest-priority open finding (--explain: with score context) |
109
+ | `resolve <status> <patterns>` | Mark fixed / wontfix / false_positive / ignore |
110
+ | `fix <fixer> [--dry-run]` | Auto-fix mechanical issues |
111
+ | `review --prepare` | Generate subjective review packet (`query.json`) |
112
+ | `review --import <file>` | Import subjective review findings |
113
+ | `issues` | Review findings queue (list/show/update) |
114
+ | `zone` | Show/set/clear zone classifications |
115
+ | `config` | Show/set/unset project configuration |
116
+ | `move <src> <dst>` | Move file/directory, update all imports |
117
+ | `detect <name>` | Run a single detector raw |
118
+ | `plan` | Prioritized markdown plan |
119
+ | `tree` | Annotated codebase tree |
120
+ | `viz` | Interactive HTML treemap |
121
+ | `dev scaffold-lang` | Generate a standardized language plugin scaffold |
122
+
123
+ #### Detectors
124
+
125
+ **TypeScript/React**: logs, unused, exports, deprecated, large, complexity, gods, single_use, props, passthrough, concerns, deps, dupes, smells, coupling, patterns, naming, cycles, orphaned, react
126
+
127
+ **Python**: unused, large, complexity, gods, props, smells, dupes, deps, cycles, orphaned, single_use, naming
128
+
129
+ **C#/.NET**: deps, cycles, orphaned, dupes, large, complexity
130
+
131
+ #### Tiers & scoring
132
+
133
+ | Tier | Fix type | Examples |
134
+ |------|----------|----------|
135
+ | T1 | Auto-fixable | Unused imports, debug logs |
136
+ | T2 | Quick manual | Unused vars, dead exports |
137
+ | T3 | Needs judgment | Near-dupes, single_use abstractions |
138
+ | T4 | Major refactor | God components, mixed concerns |
139
+
140
+ Score is weighted (T4 = 4x T1). Strict score penalizes both open and wontfix.
141
+
142
+ #### Configuration
143
+
144
+ | Variable | Default | Description |
145
+ |----------|---------|-------------|
146
+ | `DESLOPPIFY_ROOT` | cwd | Project root |
147
+ | `DESLOPPIFY_SRC` | `src` | Source directory (TS alias resolution) |
148
+ | `--lang <name>` | auto-detected | Language selection (each has own state) |
149
+ | `--exclude <pattern>` | none | Path patterns to skip (repeatable: `--exclude migrations --exclude tests`) |
150
+ | `--no-badge` | false | Skip scorecard image generation |
151
+ | `--badge-path <path>` | `scorecard.png` | Output path for scorecard image |
152
+ | `DESLOPPIFY_NO_BADGE` | — | Set to `true` to disable badge via env |
153
+ | `DESLOPPIFY_BADGE_PATH` | `scorecard.png` | Badge output path via env |
154
+
155
+ Project config values (stored in `.desloppify/config.json`) are managed via:
156
+ - `desloppify config show`
157
+ - `desloppify config set target_strict_score 95` (default: `95`, valid range: `0-100`)
158
+ - `desloppify config set badge_path scorecard.png` (or nested path like `assets/health.png`)
159
+
160
+ #### Adding or augmenting a language
161
+
162
+ Use the scaffold workflow documented in `desloppify/languages/README.md`:
163
+
164
+ ```bash
165
+ desloppify dev scaffold-lang <name> --extension .ext --marker <root-marker>
166
+ ```
167
+
168
+ Detect command keys are standardized to snake_case. CLI compatibility aliases
169
+ like `single-use` and legacy `passthrough` are still accepted.
170
+ Standard plugin shape: `__init__.py`, `commands.py`, `extractors.py`, `phases.py`,
171
+ `move.py`, `review.py`, `test_coverage.py`, plus `detectors/`, `fixers/`, and `tests/`.
172
+ Validated at registration. Zero shared code changes.
173
+
174
+ #### Architecture
175
+
176
+ ```
177
+ engine/detectors/ ← Generic algorithms (zero language knowledge)
178
+ hook_registry.py ← Detector-safe access to optional language hooks
179
+ languages/_framework/runtime.py ← LangRun (per-run mutable scan state)
180
+ languages/_framework/base/ ← Shared framework contracts + phase helpers
181
+ languages/_framework/generic.py ← generic_lang() factory for tool-based plugins
182
+ languages/_framework/treesitter/ ← Tree-sitter integration (optional)
183
+ languages/<name>/ ← Language config + phases + extractors + detectors + fixers
184
+ ```
185
+
186
+ Import direction: `languages/` → `engine/detectors/`. Never the reverse.
187
+ `LangConfig` stays static; runtime state lives on `LangRun`.
188
+
189
+ #### Command-Layer Boundaries
190
+
191
+ Command entry modules are intentionally thin orchestrators:
192
+
193
+ - `desloppify/app/commands/review/cmd.py` delegates to
194
+ `desloppify/app/commands/review/prepare.py`, `desloppify/app/commands/review/batches.py`, `desloppify/app/commands/review/import_cmd.py`, and `desloppify/app/commands/review/runtime.py`
195
+ - `desloppify/app/commands/scan/scan_reporting_dimensions.py` delegates to
196
+ `desloppify/app/commands/scan/scan_reporting_presentation.py` and `desloppify/app/commands/scan/scan_reporting_subjective.py`
197
+ - `desloppify/app/cli_support/parser.py` delegates subcommand construction to `desloppify/app/cli_support/parser_groups.py`
198
+
199
+ Public CLI behavior should be preserved when refactoring these orchestrators.
200
+
201
+ #### Allowed Dynamic Import Zones
202
+
203
+ Dynamic/optional loading is allowed only in explicit extension points:
204
+
205
+ - `desloppify/languages/__init__.py` for plugin discovery and registration
206
+ - `desloppify/hook_registry.py` for detector-safe optional hooks
207
+
208
+ Outside these zones, use static imports.
209
+
210
+ #### State Ownership
211
+
212
+ - `desloppify/state.py` and `desloppify/engine/_state/` own persisted schema and merge rules
213
+ - `desloppify/languages/_framework/runtime.py` (`LangRun`) owns per-run mutable execution state
214
+ - command modules may read/write state through state APIs, but should not define ad-hoc persisted fields
215
+
216
+ </details>
@@ -0,0 +1,187 @@
1
+ # Desloppify - an agent harness to make your codebase 🤌
2
+
3
+ Desloppify gives your AI coding agent the tools to identify, understand, and systematically improve codebase quality. It finds issues in two ways:
4
+
5
+ 1. **Subjective** — Examines the codebase from multiple subjective perspectives: abstraction quality, naming consistency, module boundaries, error handling patterns, convention drift, and language-specific questions. LLM evaluation scores these and tracks them as findings.
6
+
7
+ 2. **Mechanical** — Detects common mechanical issues like unused imports, dead code, overly long functions, duplication, and dependency cycles. Questionable issues are also flagged to the subjective agent for review.
8
+
9
+ Your agent works through a prioritized list — auto-fixing what it can, presenting the rest for your judgment. State persists across scans so it chips away over multiple sessions, and the scoring is designed to resist gaming: attestation requirements, strict scoring that penalizes dismissed issues, and cross-checked subjective assessments.
10
+
11
+ This produces a combined health score — our goal is that a score above 98 correlates with a codebase a seasoned engineer would call beautiful. That score generates a scorecard badge for your GitHub profile or README:
12
+
13
+ <img src="assets/scorecard.png" width="100%">
14
+
15
+ Currently supports 28 languages — full plugin depth for TypeScript, Python, C#, Dart, and GDScript; generic linter + tree-sitter support for Go, Rust, Ruby, Java, Kotlin, and 18 more.
16
+
17
+ ## For your agent's consideration...
18
+
19
+ Paste this prompt into your agent:
20
+
21
+ ```
22
+ Install or update desloppify, then scan this codebase for code quality issues (dead code,
23
+ duplication, complexity, smells). It tracks findings persistently across sessions and reports
24
+ a health score — state is cumulative, so each scan builds on previous progress.
25
+
26
+ pip install --upgrade git+https://github.com/peteromallet/desloppify.git
27
+ desloppify update-skill claude # pick yours: claude, cursor, codex, copilot, windsurf, gemini
28
+ desloppify scan --path .
29
+ desloppify status
30
+ desloppify next
31
+
32
+ --path is the directory to scan (use "." for the whole project, or "src/" etc).
33
+ Language is auto-detected. To override: desloppify --lang python scan --path .
34
+ (note: --lang goes BEFORE the subcommand)
35
+
36
+ Fix what it finds, then "desloppify resolve fixed <id> --note 'what changed' --attest 'I have actually [DESCRIBE THE CONCRETE CHANGE YOU MADE] and I am not gaming the score by resolving without fixing.'" and rescan.
37
+ For false positives: "desloppify resolve wontfix <id> --note 'reason' --attest 'I have actually verified this is intentional/false-positive and I am not gaming the score by resolving without fixing.'" (note is required — don't skip work; attestation must include the keywords "I have actually" and "not gaming").
38
+ Keep going until all issues are resolved.
39
+
40
+ If subjective scores feel stale or inflated, force a clean baseline:
41
+ desloppify scan --path . --reset-subjective
42
+
43
+ Because state persists, desloppify works best when run regularly. Ask the user if they'd
44
+ like to add a desloppify scan to their workflow — for example, adding "run desloppify scan
45
+ before each git push" to their CLAUDE.md, AGENTS.md, or equivalent agent instructions file,
46
+ so code health is checked at a natural interval.
47
+
48
+ If you notice anything wrong or confusing about
49
+ desloppify itself, tell me and ask if I want you to log an issue. If you need to understand
50
+ how desloppify works or debug an issue: git clone https://github.com/peteromallet/desloppify.git /tmp/desloppify
51
+ ```
52
+
53
+ ## From Vibe Coding to Vibe Engineering
54
+
55
+ Vibe coding gets things built fast. But the codebases it produces tend to rot in ways that are hard to see and harder to fix — not just the mechanical stuff like dead imports, but the structural kind. Abstractions that made sense at first stop making sense. Naming drifts. Error handling is done three different ways. The codebase works, but working in it gets worse over time.
56
+
57
+ LLMs are actually good at spotting this now, if you ask them the right questions. That's the core bet here — that an agent with the right framework can hold a codebase to a real standard, the kind that used to require a senior engineer paying close attention over months.
58
+
59
+ So we're trying to define what "good" looks like as a score that's actually worth optimizing. Not a lint score you game to 100 by suppressing warnings. Something where improving the number means the codebase genuinely got better. That's hard, and we're not done, but the anti-gaming stuff matters to us a lot — it's the difference between a useful signal and a vanity metric.
60
+
61
+ The hope is that anyone can use this to build something a seasoned engineer would look at and respect. That's the bar we're aiming for.
62
+
63
+ If you'd like to join a community of vibe engineers who want to build beautiful things, [come hang out](https://discord.gg/aZdzbZrHaY).
64
+
65
+ <img src="docs/engineering.png" width="100%">
66
+
67
+ ---
68
+
69
+ <details>
70
+ <summary><strong>Stuff you probably won't need to know</strong></summary>
71
+
72
+ #### Commands
73
+
74
+ | Command | Description |
75
+ |---------|-------------|
76
+ | `scan [--reset-subjective]` | Run all detectors, update state (optional: reset subjective baseline to 0 first) |
77
+ | `status` | Score + per-tier progress |
78
+ | `show <pattern>` | Findings by file, directory, detector, or ID |
79
+ | `next [--tier N] [--explain]` | Highest-priority open finding (--explain: with score context) |
80
+ | `resolve <status> <patterns>` | Mark fixed / wontfix / false_positive / ignore |
81
+ | `fix <fixer> [--dry-run]` | Auto-fix mechanical issues |
82
+ | `review --prepare` | Generate subjective review packet (`query.json`) |
83
+ | `review --import <file>` | Import subjective review findings |
84
+ | `issues` | Review findings queue (list/show/update) |
85
+ | `zone` | Show/set/clear zone classifications |
86
+ | `config` | Show/set/unset project configuration |
87
+ | `move <src> <dst>` | Move file/directory, update all imports |
88
+ | `detect <name>` | Run a single detector raw |
89
+ | `plan` | Prioritized markdown plan |
90
+ | `tree` | Annotated codebase tree |
91
+ | `viz` | Interactive HTML treemap |
92
+ | `dev scaffold-lang` | Generate a standardized language plugin scaffold |
93
+
94
+ #### Detectors
95
+
96
+ **TypeScript/React**: logs, unused, exports, deprecated, large, complexity, gods, single_use, props, passthrough, concerns, deps, dupes, smells, coupling, patterns, naming, cycles, orphaned, react
97
+
98
+ **Python**: unused, large, complexity, gods, props, smells, dupes, deps, cycles, orphaned, single_use, naming
99
+
100
+ **C#/.NET**: deps, cycles, orphaned, dupes, large, complexity
101
+
102
+ #### Tiers & scoring
103
+
104
+ | Tier | Fix type | Examples |
105
+ |------|----------|----------|
106
+ | T1 | Auto-fixable | Unused imports, debug logs |
107
+ | T2 | Quick manual | Unused vars, dead exports |
108
+ | T3 | Needs judgment | Near-dupes, single_use abstractions |
109
+ | T4 | Major refactor | God components, mixed concerns |
110
+
111
+ Score is weighted (T4 = 4x T1). Strict score penalizes both open and wontfix.
112
+
113
+ #### Configuration
114
+
115
+ | Variable | Default | Description |
116
+ |----------|---------|-------------|
117
+ | `DESLOPPIFY_ROOT` | cwd | Project root |
118
+ | `DESLOPPIFY_SRC` | `src` | Source directory (TS alias resolution) |
119
+ | `--lang <name>` | auto-detected | Language selection (each has own state) |
120
+ | `--exclude <pattern>` | none | Path patterns to skip (repeatable: `--exclude migrations --exclude tests`) |
121
+ | `--no-badge` | false | Skip scorecard image generation |
122
+ | `--badge-path <path>` | `scorecard.png` | Output path for scorecard image |
123
+ | `DESLOPPIFY_NO_BADGE` | — | Set to `true` to disable badge via env |
124
+ | `DESLOPPIFY_BADGE_PATH` | `scorecard.png` | Badge output path via env |
125
+
126
+ Project config values (stored in `.desloppify/config.json`) are managed via:
127
+ - `desloppify config show`
128
+ - `desloppify config set target_strict_score 95` (default: `95`, valid range: `0-100`)
129
+ - `desloppify config set badge_path scorecard.png` (or nested path like `assets/health.png`)
130
+
131
+ #### Adding or augmenting a language
132
+
133
+ Use the scaffold workflow documented in `desloppify/languages/README.md`:
134
+
135
+ ```bash
136
+ desloppify dev scaffold-lang <name> --extension .ext --marker <root-marker>
137
+ ```
138
+
139
+ Detect command keys are standardized to snake_case. CLI compatibility aliases
140
+ like `single-use` and legacy `passthrough` are still accepted.
141
+ Standard plugin shape: `__init__.py`, `commands.py`, `extractors.py`, `phases.py`,
142
+ `move.py`, `review.py`, `test_coverage.py`, plus `detectors/`, `fixers/`, and `tests/`.
143
+ Validated at registration. Zero shared code changes.
144
+
145
+ #### Architecture
146
+
147
+ ```
148
+ engine/detectors/ ← Generic algorithms (zero language knowledge)
149
+ hook_registry.py ← Detector-safe access to optional language hooks
150
+ languages/_framework/runtime.py ← LangRun (per-run mutable scan state)
151
+ languages/_framework/base/ ← Shared framework contracts + phase helpers
152
+ languages/_framework/generic.py ← generic_lang() factory for tool-based plugins
153
+ languages/_framework/treesitter/ ← Tree-sitter integration (optional)
154
+ languages/<name>/ ← Language config + phases + extractors + detectors + fixers
155
+ ```
156
+
157
+ Import direction: `languages/` → `engine/detectors/`. Never the reverse.
158
+ `LangConfig` stays static; runtime state lives on `LangRun`.
159
+
160
+ #### Command-Layer Boundaries
161
+
162
+ Command entry modules are intentionally thin orchestrators:
163
+
164
+ - `desloppify/app/commands/review/cmd.py` delegates to
165
+ `desloppify/app/commands/review/prepare.py`, `desloppify/app/commands/review/batches.py`, `desloppify/app/commands/review/import_cmd.py`, and `desloppify/app/commands/review/runtime.py`
166
+ - `desloppify/app/commands/scan/scan_reporting_dimensions.py` delegates to
167
+ `desloppify/app/commands/scan/scan_reporting_presentation.py` and `desloppify/app/commands/scan/scan_reporting_subjective.py`
168
+ - `desloppify/app/cli_support/parser.py` delegates subcommand construction to `desloppify/app/cli_support/parser_groups.py`
169
+
170
+ Public CLI behavior should be preserved when refactoring these orchestrators.
171
+
172
+ #### Allowed Dynamic Import Zones
173
+
174
+ Dynamic/optional loading is allowed only in explicit extension points:
175
+
176
+ - `desloppify/languages/__init__.py` for plugin discovery and registration
177
+ - `desloppify/hook_registry.py` for detector-safe optional hooks
178
+
179
+ Outside these zones, use static imports.
180
+
181
+ #### State Ownership
182
+
183
+ - `desloppify/state.py` and `desloppify/engine/_state/` own persisted schema and merge rules
184
+ - `desloppify/languages/_framework/runtime.py` (`LangRun`) owns per-run mutable execution state
185
+ - command modules may read/write state through state APIs, but should not define ad-hoc persisted fields
186
+
187
+ </details>
@@ -0,0 +1,3 @@
1
+ """Desloppify — Automated cruft detection + LLM-ready analysis."""
2
+
3
+ from __future__ import annotations
@@ -0,0 +1,5 @@
1
+ """Allow running as: python -m desloppify"""
2
+
3
+ from desloppify.cli import main
4
+
5
+ main()
@@ -0,0 +1 @@
1
+ """Application-layer packages: CLI, commands, and output surfaces."""
@@ -0,0 +1,2 @@
1
+ """CLI parser support modules."""
2
+
@@ -0,0 +1,122 @@
1
+ """CLI parser construction helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+
7
+ from desloppify.app.cli_support.parser_groups import (
8
+ _add_config_parser,
9
+ _add_detect_parser,
10
+ _add_dev_parser,
11
+ _add_fix_parser,
12
+ _add_ignore_parser,
13
+ _add_issues_parser,
14
+ _add_langs_parser,
15
+ _add_move_parser,
16
+ _add_next_parser,
17
+ _add_plan_parser,
18
+ _add_resolve_parser,
19
+ _add_review_parser,
20
+ _add_scan_parser,
21
+ _add_show_parser,
22
+ _add_status_parser,
23
+ _add_tree_parser,
24
+ _add_update_skill_parser,
25
+ _add_viz_parser,
26
+ _add_zone_parser,
27
+ )
28
+
29
+ USAGE_EXAMPLES = """
30
+ workflow:
31
+ scan Run all detectors, update state, show diff
32
+ status Score dashboard with per-tier progress
33
+ tree Annotated codebase tree (zoom with --focus)
34
+ show <pattern> Dig into findings by file/dir/detector/ID
35
+ resolve <pattern> <status> Mark findings as fixed/wontfix/false_positive
36
+ ignore <pattern> Suppress findings matching a pattern
37
+ zone show Show zone classifications for all files
38
+ zone set <file> <zone> Override zone for a file
39
+ review --prepare Prepare holistic codebase review data
40
+ review --import FILE Import review findings from JSON
41
+ issues Review findings work queue
42
+ plan Generate prioritized markdown plan
43
+
44
+ examples:
45
+ desloppify scan --skip-slow
46
+ desloppify --lang python scan --path scripts/desloppify
47
+ desloppify tree --focus shared/components --sort findings --depth 3
48
+ desloppify tree --detail --focus shared/components/MediaLightbox --min-loc 300
49
+ desloppify show src/shared/components/PromptEditorModal.tsx
50
+ desloppify show gods
51
+ desloppify show "src/shared/components/MediaLightbox"
52
+ desloppify resolve fixed "unused::src/foo.tsx::React" --note "removed unused React import" --attest "I have actually removed the unused React import from foo.tsx and I am not gaming the score by resolving without fixing."
53
+ desloppify resolve fixed "logs::src/foo.tsx::*" --note "removed debug logs" --attest "I have actually removed all console.log calls from foo.tsx and I am not gaming the score by resolving without fixing."
54
+ desloppify resolve wontfix deprecated --note "migration in progress" --attest "I have actually verified these are tracked in the migration plan and I am not gaming the score by resolving without fixing."
55
+ desloppify ignore "smells::*::async_no_await" --attest "I have actually verified these are intentional fire-and-forget patterns and I am not gaming the score by resolving without fixing."
56
+ desloppify detect logs --top 10
57
+ desloppify detect dupes --threshold 0.9
58
+ desloppify dev scaffold-lang go --extension .go --marker go.mod --default-src .
59
+ desloppify move src/shared/hooks/useFoo.ts src/shared/hooks/video/useFoo.ts --dry-run
60
+ desloppify move scripts/foo/bar.py scripts/foo/baz/bar.py
61
+ """
62
+
63
+
64
+ class _NoAbbrevArgumentParser(argparse.ArgumentParser):
65
+ """Argparse parser variant that disables long-option abbreviation."""
66
+
67
+ def __init__(self, *args, **kwargs):
68
+ kwargs.setdefault("allow_abbrev", False)
69
+ super().__init__(*args, **kwargs)
70
+
71
+
72
+ def create_parser(*, langs: list[str], detector_names: list[str]) -> argparse.ArgumentParser:
73
+ """Build top-level CLI parser with all subcommands."""
74
+ lang_help = ", ".join(langs) if langs else "registered languages"
75
+
76
+ parser = _NoAbbrevArgumentParser(
77
+ prog="desloppify",
78
+ description="Desloppify — codebase health tracker",
79
+ epilog=USAGE_EXAMPLES,
80
+ formatter_class=argparse.RawDescriptionHelpFormatter,
81
+ )
82
+ parser.add_argument(
83
+ "--lang",
84
+ type=str,
85
+ default=None,
86
+ help=f"Language to scan ({lang_help}). Auto-detected if omitted.",
87
+ )
88
+ parser.add_argument(
89
+ "--exclude",
90
+ action="append",
91
+ default=None,
92
+ metavar="PATTERN",
93
+ help="Path pattern to exclude (component/prefix match; repeatable)",
94
+ )
95
+ sub = parser.add_subparsers(
96
+ dest="command",
97
+ required=True,
98
+ parser_class=_NoAbbrevArgumentParser,
99
+ )
100
+ _add_scan_parser(sub)
101
+ _add_status_parser(sub)
102
+ _add_tree_parser(sub)
103
+ _add_show_parser(sub)
104
+ _add_next_parser(sub)
105
+ _add_resolve_parser(sub)
106
+ _add_ignore_parser(sub)
107
+ _add_fix_parser(sub, langs)
108
+ _add_plan_parser(sub)
109
+ _add_viz_parser(sub)
110
+ _add_detect_parser(sub, detector_names)
111
+ _add_move_parser(sub)
112
+ _add_review_parser(sub)
113
+ _add_issues_parser(sub)
114
+ _add_zone_parser(sub)
115
+ _add_config_parser(sub)
116
+ _add_dev_parser(sub)
117
+ _add_langs_parser(sub)
118
+ _add_update_skill_parser(sub)
119
+ return parser
120
+
121
+
122
+ __all__ = ["USAGE_EXAMPLES", "create_parser"]