Repository Analysis

andreafrancia/trash-cli

Command line interface to the freedesktop.org trashcan.

37.9 Strong AI signal View on GitHub

Analysis Overview

This report presents the forensic synthetic code analysis of andreafrancia/trash-cli, a Python project with 4,430 GitHub stars. SynthScan v2.0 examined 15,854 lines of code across 434 source files, recording 549 pattern matches distributed across 5 syntactic categories. The overall adjusted score of 37.9 places this repository in the Strong AI signal band.

The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).

37.9
Adjusted Score
37.9
Raw Score
100%
Time Factor
2026-07-14
Last Push
4.4K
Stars
Python
Language
15.9K
Lines of Code
434
Files
549
Pattern Hits
2026-07-14
Scan Date
0.00
HC Hit Rate

What These Metrics Mean

Adjusted Score
Primary synthetic code indicator. Raw score normalised per 1,000 lines of code and multiplied by the temporal discount factor. This is the definitive comparative metric — use it to rank repositories by AI authorship density.
Raw Score
The unmodified sum of all severity-weighted, context-multiplied pattern match scores before temporal discounting. Reflects the absolute signal strength independent of when the repository was last active.
Time Factor
The temporal discount multiplier (0–100%) applied to the raw score. Repositories last updated before ChatGPT's launch (Nov 2022) receive a 5% factor. Full signal is only assigned to repositories active in the post-adoption era (Jan 2024+).
Pattern Hits
Total count of individual pattern matches across all files and categories. A high hit count with a low score may indicate a very large codebase with isolated AI snippets; a low count with a high score indicates dense, concentrated AI signatures.
HC Hit Rate
High+Critical pattern hits per file, averaged across the repository. This orthogonal signal catches repositories where a few files are densely packed with high-severity AI tells — a strong indicator even when the normalised score appears moderate due to codebase size.
Lines of Code / Files
Total lines and files analysed. The scanner examines 94 file extensions. These denominators are used to normalise the score, enabling fair comparison between repositories of vastly different sizes.

Score History

Longitudinal tracking requires multiple scan runs. Once this repository is re-scanned after new commits land, this chart will visualise how the synthetic code signal evolves over time — enabling you to detect whether AI authorship is growing, stabilising, or being actively corrected by human engineers.

No multi-scan history yet — run the scanner again to build trend data.

Severity Breakdown

Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.

CRITICAL 0HIGH 0MEDIUM 1LOW 548

Directory Score Breakdown

This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.

Pattern Findings

The scanner identified 549 distinct pattern matches across 5 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.

Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.

Hyper-Verbose Identifiers252 hits · 304 pts
SeverityFileLineSnippetContext
LOW…t_empty/cmd/test_empty_cmd_with_multiple_volumes_fs.py60 def test_it_removes_trashinfo_from_specified_trash_dir(self):CODE
LOW…t_empty/cmd/test_empty_cmd_with_multiple_volumes_fs.py70 def make_proper_top_trash_dir(path):CODE
LOWtests/test_empty/cmd/test_empty_cmd_fs.py43 def test_trash_empty_will_skip_unreadable_dir(self):CODE
LOW…mpty/components/test_empty_end_to_end_with_argument.py50 def test_it_should_kept_files_with_invalid_deletion_date(self):CODE
LOWtests/test_empty/components/test_guard.py28 def test_it_just_calls_the_emptier(self):CODE
LOWtests/test_empty/components/test_empty_end_to_end.py77 def test_on_trash_date_not_parsable(self):STRING
LOWtests/test_empty/components/test_make_parser.py16 def test_non_interactive_default_is_non_interactive(self):CODE
LOWtests/test_empty/components/test_make_parser.py22 def test_interactive_default_is_interactive(self):CODE
LOWtests/test_empty/components/test_make_parser.py28 def test_interactive_made_non_interactive(self):CODE
LOW…ts/test_empty/components/test_existing_file_remover.py8 def test_remove_file_if_exists_fails_when_file_does_not_exists(self):CODE
LOW…pty/components/test_empty_end_to_end_with_trash_dir.py44 def test_non_trash_info_is_not_deleted(self):CODE
LOWtests/test_empty/components/test_clock.py27 def test_return_true_now_whe_fake_time_is_invalid(self):CODE
LOW…ools/test_make_scripts/test_list_of_created_scripts.py11 def test_is_empty_on_start_up(self):CODE
LOW…ools/test_make_scripts/test_list_of_created_scripts.py14 def test_collect_added_script(self):CODE
LOW…s/test_dev_tools/test_make_scripts/test_make_script.py26 def test_should_set_executable_permission(self):CODE
LOW…s/test_dev_tools/test_make_scripts/test_make_script.py29 def test_should_write_the_script(self):CODE
LOW…s/test_dev_tools/test_make_scripts/test_make_script.py33 def test_the_script_should_call_the_right_function_from_the_right_module(self):CODE
LOWtests/test_dev_tools/cmds/test_bump_cmd.py38 def test_when_clean_and_dry_run(self):CODE
LOWtests/test_list/cmd/test_version.py9 def test_should_output_the_version(self, user):CODE
LOWtests/test_list/cmd/test_trash_list.py9 def test_should_output_nothing_when_trashcan_is_empty(self, user):CODE
LOWtests/test_list/cmd/test_trash_list.py14 def test_should_output_deletion_date_and_path(self, user):CODE
LOWtests/test_list/cmd/test_trash_list.py22 def test_should_output_info_for_multiple_files(self, user):CODE
LOWtests/test_list/cmd/test_trash_list.py33 def test_should_output_unknown_dates_with_question_marks(self, user):CODE
LOWtests/test_list/cmd/test_trash_list.py40 def test_should_output_invalid_dates_using_question_marks(self, user):CODE
LOWtests/test_list/cmd/test_trash_list.py49 def test_should_warn_about_empty_trashinfos(self, user):CODE
LOWtests/test_list/cmd/test_trash_list.py58 def test_should_warn_about_unreadable_trashinfo(self, user):CODE
LOWtests/test_list/cmd/test_trash_list.py68 def test_should_warn_about_unexistent_path_entry(self, user):CODE
LOWtests/test_list/cmd/test_with_a_top_trash_dir.py15 def test_should_list_its_contents_if_parent_is_sticky(self, user):CODE
LOWtests/test_list/cmd/test_with_a_top_trash_dir.py23 def test_and_should_warn_if_parent_is_not_sticky(self, user):CODE
LOWtests/test_list/cmd/test_with_a_top_trash_dir.py32 def test_but_it_should_not_warn_when_the_parent_is_unsticky_but_there_is_no_trashdir(CODE
LOWtests/test_list/cmd/test_with_a_top_trash_dir.py41 def test_should_ignore_trash_from_a_unsticky_topdir(self, user):CODE
LOWtests/test_list/cmd/test_with_a_top_trash_dir.py50 def test_it_should_skip_a_symlink(self, user):CODE
LOW…st_list/cmd/test_trash_list_sanitizes_control_chars.py16def test_on_a_terminal_the_name_is_shell_escaped(trash_list_user):CODE
LOW…st_list/cmd/test_trash_list_sanitizes_control_chars.py29def test_when_piped_the_name_is_printed_raw(trash_list_user):CODE
LOW…s/test_list/components/test_deletion_date_extractor.py11 def test_extract_attribute_default(self):CODE
LOW…s/test_list/components/test_deletion_date_extractor.py15 def test_extract_attribute_value(self):CODE
LOWtests/test_list/components/test_trash_list_parser.py18 def test_trash_dir_not_specified(self):CODE
LOWtests/test_rm/cmd/test_trash_rm.py32 def test_without_pattern_argument(self):CODE
LOWtests/test_rm/components/test_file_remover.py13 def test_remove_file_fails_when_file_does_not_exists(self):CODE
LOWtests/test_rm/components/test_filter.py20 def test_example_with_star_dot_o(self):CODE
LOWtests/test_put/cmd/test_put_option_shaped_filename.py15 def test_it_refuses_an_existing_file_that_looks_like_an_option(self):CODE
LOWtests/test_put/cmd/test_put_option_shaped_filename.py23 def test_the_double_dash_separator_still_lets_you_trash_such_a_file(self):CODE
LOWtests/test_put/cmd/test_put_option_shaped_filename.py32 def test_a_real_option_is_unaffected_when_no_such_file_exists(self):CODE
LOWtests/test_put/cmd/test_put.py31 def test_when_needs_a_different_suffix(self):CODE
LOWtests/test_put/cmd/test_put.py39 def test_when_needs_a_random_suffix(self):CODE
LOWtests/test_put/cmd/test_put.py48 def test_when_a_trashinfo_file_already_exists(self):CODE
LOWtests/test_put/cmd/test_put.py63 def test_when_moving_file_in_trash_dir_fails(self):CODE
LOWtests/test_put/cmd/test_put.py74 def test_should_not_trash_dot_entry(self):CODE
LOWtests/test_put/cmd/test_put.py81 def test_should_not_trash_dot_dot_entry(self):CODE
LOWtests/test_put/cmd/test_put.py114 def test_when_file_does_not_exist(self):CODE
LOWtests/test_put/cmd/test_put.py122 def test_when_file_does_not_exist_with_force(self):CODE
LOWtests/test_put/cmd/test_put.py128 def test_put_does_not_try_to_trash_non_existing_file(self):CODE
LOWtests/test_put/cmd/test_put.py138 def test_when_file_cannot_be_trashed(self):CODE
LOWtests/test_put/cmd/test_put.py177 def test_when_there_is_no_working_trash_dir(self):CODE
LOWtests/test_put/cmd/test_put.py209 def test_when_it_fails_to_prepare_trash_info_data(self):CODE
LOWtests/test_put/cmd/test_put.py254 def test_when_file_move_fails(self):CODE
LOWtests/test_put/cmd/test_put.py287 def test_when_a_error_during_move(self):CODE
LOWtests/test_put/cmd/test_put_symlinked_trash_dir.py19 def test_it_does_not_trash_into_a_symlinked_info_dir(self):CODE
LOWtests/test_put/cmd/test_put_script.py15 def test_trash_put_touch_filesystem(self):CODE
LOWtests/test_put/cmd/test_put_unwritable_trash_dir.py22 def test_it_reports_an_error_when_the_trashinfo_cannot_be_written(self):CODE
192 more matches not shown…
Unused Imports283 hits · 283 pts
SeverityFileLineSnippetContext
LOWtests/test_empty/components/test_guard.py3CODE
LOWtests/test_empty/components/test_make_parser.py2CODE
LOWtests/test_dev_tools/support/run_set_dev_version.py6CODE
LOWtests/test_put/cmd/test_put.py1CODE
LOWtests/test_put/cmd/test_put.py2CODE
LOWtests/test_put/cmd/test_put.py13CODE
LOWtests/test_put/cmd/e2e/test_on_symbolic_links.py7CODE
LOWtests/test_put/cmd/e2e/run_trash_put/put_result.py3CODE
LOW…sts/test_put/cmd/e2e/run_trash_put/directory_layout.py1CODE
LOWtests/test_put/cmd/e2e/run_trash_put/__init__.py1CODE
LOWtests/test_put/cmd/e2e/run_trash_put/__init__.py2CODE
LOWtests/test_put/cmd/e2e/run_trash_put/__init__.py5CODE
LOWtests/test_put/cmd/e2e/run_trash_put/__init__.py6CODE
LOWtests/test_put/cmd/e2e/run_trash_put/__init__.py8CODE
LOWtests/test_put/cmd/e2e/run_trash_put/__init__.py9CODE
LOWtests/test_put/components/test_move_file.py3CODE
LOWtests/test_put/components/test_trash_put_reporter.py1CODE
LOWtests/test_put/components/test_trash_put_reporter.py3CODE
LOWtests/test_put/components/test_trash_put_reporter.py6CODE
LOWtests/test_put/components/test_volume_of_parent.py2CODE
LOWtests/test_put/components/test_volume_of_parent.py4CODE
LOWtests/test_put/components/test_volume_of_parent.py7CODE
LOWtests/test_put/components/test_volume_of_parent.py8CODE
LOWtests/test_put/components/test_trash_dir_volume.py3CODE
LOW…t/components/trashing_checker/test_trashing_checker.py1CODE
LOWtests/test_put/support/result.py1CODE
LOWtests/test_put/support/result.py2CODE
LOWtests/test_put/support/result.py4CODE
LOWtests/test_put/support/result.py5CODE
LOWtests/test_put/support/logs.py5CODE
LOWtests/test_put/support/recording_backend.py1CODE
LOWtests/test_put/support/recording_backend.py3CODE
LOWtests/test_put/support/recording_backend.py7CODE
LOWtests/test_put/support/recording_backend.py8CODE
LOWtests/support/py2mock.py4CODE
LOWtests/support/py2mock.py6CODE
LOWtests/support/tools/version_from_date.py1CODE
LOWtests/support/tools/set_dev_version.py1CODE
LOWtests/support/put/fake_random.py1CODE
LOWtests/support/put/fake_fs/inode.py3CODE
LOWtests/support/put/fake_fs/directory.py2CODE
LOWtests/support/put/fake_fs/directory.py3CODE
LOWtests/support/put/fake_fs/fake_fs.py9CODE
LOWtests/support/put/fake_fs/fake_fs.py10CODE
LOWtests/support/fakes/fake_is_mount.py2CODE
LOWtests/support/fakes/fake_volume_of.py2CODE
LOWtests/support/fakes/mock_dir_reader.py3CODE
LOWtests/support/restore/has_been_restored_matcher.py3CODE
LOWtests/support/restore/restore_user.py3CODE
LOWtests/support/restore/restore_user.py6CODE
LOWtests/support/restore/restore_user.py8CODE
LOWtests/support/restore/restore_user.py8CODE
LOWtests/support/restore/restore_user.py8CODE
LOWtests/support/restore/restore_user.py8CODE
LOWtests/test_restore/support/restore_fake_fs.py3CODE
LOWtests/test_restore/support/fake_logger.py1CODE
LOWtrashcli/trash_dirs_scanner.py2CODE
LOWtrashcli/trash_dirs_scanner.py6CODE
LOWtrashcli/trash_dirs_scanner.py7CODE
LOWtrashcli/trash_dirs_scanner.py8CODE
223 more matches not shown…
Deep Nesting9 hits · 9 pts
SeverityFileLineSnippetContext
LOWtrashcli/trash_dirs_scanner.py77CODE
LOWtrashcli/put/describer.py8CODE
LOWtrashcli/put/janitor_tools/info_file_persister.py71CODE
LOWtrashcli/list/list_trash_action.py90CODE
LOWtrashcli/list/minor_actions/list_trash_dirs.py22CODE
LOWtrashcli/restore/trashed_files.py29CODE
LOWtrashcli/restore/trashed_files.py46CODE
LOWtrashcli/restore/real_output.py29CODE
LOWtrashcli/rm/rm_cmd.py37CODE
Excessive Try-Catch Wrapping3 hits · 4 pts
SeverityFileLineSnippetContext
LOWtests/support/capture_error.py4 except Exception as e:CODE
MEDIUMtests/support/capture_error.py1def capture_error(callable):CODE
LOWtrashcli/lib/sanitize.py51 except Exception:CODE
AI Structural Patterns2 hits · 2 pts
SeverityFileLineSnippetContext
LOWtests/test_put/cmd/e2e/run_trash_put/__init__.py55CODE
LOWtests/support/put/fake_fs/failing_fake_fs.py38CODE