Command line interface to the freedesktop.org trashcan.
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).
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.
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.
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.
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.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …t_empty/cmd/test_empty_cmd_with_multiple_volumes_fs.py | 60 | def test_it_removes_trashinfo_from_specified_trash_dir(self): | CODE |
| LOW | …t_empty/cmd/test_empty_cmd_with_multiple_volumes_fs.py | 70 | def make_proper_top_trash_dir(path): | CODE |
| LOW | tests/test_empty/cmd/test_empty_cmd_fs.py | 43 | def test_trash_empty_will_skip_unreadable_dir(self): | CODE |
| LOW | …mpty/components/test_empty_end_to_end_with_argument.py | 50 | def test_it_should_kept_files_with_invalid_deletion_date(self): | CODE |
| LOW | tests/test_empty/components/test_guard.py | 28 | def test_it_just_calls_the_emptier(self): | CODE |
| LOW | tests/test_empty/components/test_empty_end_to_end.py | 77 | def test_on_trash_date_not_parsable(self): | STRING |
| LOW⚡ | tests/test_empty/components/test_make_parser.py | 16 | def test_non_interactive_default_is_non_interactive(self): | CODE |
| LOW⚡ | tests/test_empty/components/test_make_parser.py | 22 | def test_interactive_default_is_interactive(self): | CODE |
| LOW⚡ | tests/test_empty/components/test_make_parser.py | 28 | def test_interactive_made_non_interactive(self): | CODE |
| LOW | …ts/test_empty/components/test_existing_file_remover.py | 8 | 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.py | 44 | def test_non_trash_info_is_not_deleted(self): | CODE |
| LOW | tests/test_empty/components/test_clock.py | 27 | def test_return_true_now_whe_fake_time_is_invalid(self): | CODE |
| LOW | …ools/test_make_scripts/test_list_of_created_scripts.py | 11 | def test_is_empty_on_start_up(self): | CODE |
| LOW | …ools/test_make_scripts/test_list_of_created_scripts.py | 14 | def test_collect_added_script(self): | CODE |
| LOW⚡ | …s/test_dev_tools/test_make_scripts/test_make_script.py | 26 | def test_should_set_executable_permission(self): | CODE |
| LOW⚡ | …s/test_dev_tools/test_make_scripts/test_make_script.py | 29 | def test_should_write_the_script(self): | CODE |
| LOW⚡ | …s/test_dev_tools/test_make_scripts/test_make_script.py | 33 | def test_the_script_should_call_the_right_function_from_the_right_module(self): | CODE |
| LOW | tests/test_dev_tools/cmds/test_bump_cmd.py | 38 | def test_when_clean_and_dry_run(self): | CODE |
| LOW | tests/test_list/cmd/test_version.py | 9 | def test_should_output_the_version(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 9 | def test_should_output_nothing_when_trashcan_is_empty(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 14 | def test_should_output_deletion_date_and_path(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 22 | def test_should_output_info_for_multiple_files(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 33 | def test_should_output_unknown_dates_with_question_marks(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 40 | def test_should_output_invalid_dates_using_question_marks(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 49 | def test_should_warn_about_empty_trashinfos(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 58 | def test_should_warn_about_unreadable_trashinfo(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_trash_list.py | 68 | def test_should_warn_about_unexistent_path_entry(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 15 | def test_should_list_its_contents_if_parent_is_sticky(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 23 | def test_and_should_warn_if_parent_is_not_sticky(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 32 | def test_but_it_should_not_warn_when_the_parent_is_unsticky_but_there_is_no_trashdir( | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 41 | def test_should_ignore_trash_from_a_unsticky_topdir(self, user): | CODE |
| LOW⚡ | tests/test_list/cmd/test_with_a_top_trash_dir.py | 50 | def test_it_should_skip_a_symlink(self, user): | CODE |
| LOW | …st_list/cmd/test_trash_list_sanitizes_control_chars.py | 16 | def test_on_a_terminal_the_name_is_shell_escaped(trash_list_user): | CODE |
| LOW | …st_list/cmd/test_trash_list_sanitizes_control_chars.py | 29 | def test_when_piped_the_name_is_printed_raw(trash_list_user): | CODE |
| LOW | …s/test_list/components/test_deletion_date_extractor.py | 11 | def test_extract_attribute_default(self): | CODE |
| LOW | …s/test_list/components/test_deletion_date_extractor.py | 15 | def test_extract_attribute_value(self): | CODE |
| LOW | tests/test_list/components/test_trash_list_parser.py | 18 | def test_trash_dir_not_specified(self): | CODE |
| LOW | tests/test_rm/cmd/test_trash_rm.py | 32 | def test_without_pattern_argument(self): | CODE |
| LOW | tests/test_rm/components/test_file_remover.py | 13 | def test_remove_file_fails_when_file_does_not_exists(self): | CODE |
| LOW | tests/test_rm/components/test_filter.py | 20 | def test_example_with_star_dot_o(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put_option_shaped_filename.py | 15 | def test_it_refuses_an_existing_file_that_looks_like_an_option(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put_option_shaped_filename.py | 23 | def test_the_double_dash_separator_still_lets_you_trash_such_a_file(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put_option_shaped_filename.py | 32 | def test_a_real_option_is_unaffected_when_no_such_file_exists(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put.py | 31 | def test_when_needs_a_different_suffix(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put.py | 39 | def test_when_needs_a_random_suffix(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put.py | 48 | def test_when_a_trashinfo_file_already_exists(self): | CODE |
| LOW | tests/test_put/cmd/test_put.py | 63 | def test_when_moving_file_in_trash_dir_fails(self): | CODE |
| LOW | tests/test_put/cmd/test_put.py | 74 | def test_should_not_trash_dot_entry(self): | CODE |
| LOW | tests/test_put/cmd/test_put.py | 81 | def test_should_not_trash_dot_dot_entry(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put.py | 114 | def test_when_file_does_not_exist(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put.py | 122 | def test_when_file_does_not_exist_with_force(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put.py | 128 | def test_put_does_not_try_to_trash_non_existing_file(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put.py | 138 | def test_when_file_cannot_be_trashed(self): | CODE |
| LOW | tests/test_put/cmd/test_put.py | 177 | def test_when_there_is_no_working_trash_dir(self): | CODE |
| LOW | tests/test_put/cmd/test_put.py | 209 | def test_when_it_fails_to_prepare_trash_info_data(self): | CODE |
| LOW | tests/test_put/cmd/test_put.py | 254 | def test_when_file_move_fails(self): | CODE |
| LOW | tests/test_put/cmd/test_put.py | 287 | def test_when_a_error_during_move(self): | CODE |
| LOW | tests/test_put/cmd/test_put_symlinked_trash_dir.py | 19 | def test_it_does_not_trash_into_a_symlinked_info_dir(self): | CODE |
| LOW | tests/test_put/cmd/test_put_script.py | 15 | def test_trash_put_touch_filesystem(self): | CODE |
| LOW⚡ | tests/test_put/cmd/test_put_unwritable_trash_dir.py | 22 | def test_it_reports_an_error_when_the_trashinfo_cannot_be_written(self): | CODE |
| 192 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_empty/components/test_guard.py | 3 | CODE | |
| LOW | tests/test_empty/components/test_make_parser.py | 2 | CODE | |
| LOW | tests/test_dev_tools/support/run_set_dev_version.py | 6 | CODE | |
| LOW | tests/test_put/cmd/test_put.py | 1 | CODE | |
| LOW | tests/test_put/cmd/test_put.py | 2 | CODE | |
| LOW | tests/test_put/cmd/test_put.py | 13 | CODE | |
| LOW | tests/test_put/cmd/e2e/test_on_symbolic_links.py | 7 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/put_result.py | 3 | CODE | |
| LOW | …sts/test_put/cmd/e2e/run_trash_put/directory_layout.py | 1 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 1 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 2 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 5 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 6 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 8 | CODE | |
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 9 | CODE | |
| LOW | tests/test_put/components/test_move_file.py | 3 | CODE | |
| LOW | tests/test_put/components/test_trash_put_reporter.py | 1 | CODE | |
| LOW | tests/test_put/components/test_trash_put_reporter.py | 3 | CODE | |
| LOW | tests/test_put/components/test_trash_put_reporter.py | 6 | CODE | |
| LOW | tests/test_put/components/test_volume_of_parent.py | 2 | CODE | |
| LOW | tests/test_put/components/test_volume_of_parent.py | 4 | CODE | |
| LOW | tests/test_put/components/test_volume_of_parent.py | 7 | CODE | |
| LOW | tests/test_put/components/test_volume_of_parent.py | 8 | CODE | |
| LOW | tests/test_put/components/test_trash_dir_volume.py | 3 | CODE | |
| LOW | …t/components/trashing_checker/test_trashing_checker.py | 1 | CODE | |
| LOW | tests/test_put/support/result.py | 1 | CODE | |
| LOW | tests/test_put/support/result.py | 2 | CODE | |
| LOW | tests/test_put/support/result.py | 4 | CODE | |
| LOW | tests/test_put/support/result.py | 5 | CODE | |
| LOW | tests/test_put/support/logs.py | 5 | CODE | |
| LOW | tests/test_put/support/recording_backend.py | 1 | CODE | |
| LOW | tests/test_put/support/recording_backend.py | 3 | CODE | |
| LOW | tests/test_put/support/recording_backend.py | 7 | CODE | |
| LOW | tests/test_put/support/recording_backend.py | 8 | CODE | |
| LOW | tests/support/py2mock.py | 4 | CODE | |
| LOW | tests/support/py2mock.py | 6 | CODE | |
| LOW | tests/support/tools/version_from_date.py | 1 | CODE | |
| LOW | tests/support/tools/set_dev_version.py | 1 | CODE | |
| LOW | tests/support/put/fake_random.py | 1 | CODE | |
| LOW | tests/support/put/fake_fs/inode.py | 3 | CODE | |
| LOW | tests/support/put/fake_fs/directory.py | 2 | CODE | |
| LOW | tests/support/put/fake_fs/directory.py | 3 | CODE | |
| LOW | tests/support/put/fake_fs/fake_fs.py | 9 | CODE | |
| LOW | tests/support/put/fake_fs/fake_fs.py | 10 | CODE | |
| LOW | tests/support/fakes/fake_is_mount.py | 2 | CODE | |
| LOW | tests/support/fakes/fake_volume_of.py | 2 | CODE | |
| LOW | tests/support/fakes/mock_dir_reader.py | 3 | CODE | |
| LOW | tests/support/restore/has_been_restored_matcher.py | 3 | CODE | |
| LOW | tests/support/restore/restore_user.py | 3 | CODE | |
| LOW | tests/support/restore/restore_user.py | 6 | CODE | |
| LOW | tests/support/restore/restore_user.py | 8 | CODE | |
| LOW | tests/support/restore/restore_user.py | 8 | CODE | |
| LOW | tests/support/restore/restore_user.py | 8 | CODE | |
| LOW | tests/support/restore/restore_user.py | 8 | CODE | |
| LOW | tests/test_restore/support/restore_fake_fs.py | 3 | CODE | |
| LOW | tests/test_restore/support/fake_logger.py | 1 | CODE | |
| LOW | trashcli/trash_dirs_scanner.py | 2 | CODE | |
| LOW | trashcli/trash_dirs_scanner.py | 6 | CODE | |
| LOW | trashcli/trash_dirs_scanner.py | 7 | CODE | |
| LOW | trashcli/trash_dirs_scanner.py | 8 | CODE | |
| 223 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | trashcli/trash_dirs_scanner.py | 77 | CODE | |
| LOW | trashcli/put/describer.py | 8 | CODE | |
| LOW | trashcli/put/janitor_tools/info_file_persister.py | 71 | CODE | |
| LOW | trashcli/list/list_trash_action.py | 90 | CODE | |
| LOW | trashcli/list/minor_actions/list_trash_dirs.py | 22 | CODE | |
| LOW | trashcli/restore/trashed_files.py | 29 | CODE | |
| LOW | trashcli/restore/trashed_files.py | 46 | CODE | |
| LOW | trashcli/restore/real_output.py | 29 | CODE | |
| LOW | trashcli/rm/rm_cmd.py | 37 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/support/capture_error.py | 4 | except Exception as e: | CODE |
| MEDIUM | tests/support/capture_error.py | 1 | def capture_error(callable): | CODE |
| LOW | trashcli/lib/sanitize.py | 51 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_put/cmd/e2e/run_trash_put/__init__.py | 55 | CODE | |
| LOW | tests/support/put/fake_fs/failing_fake_fs.py | 38 | CODE |