Python library and shell utilities to monitor filesystem events.
This report presents the forensic synthetic code analysis of gorakhargosh/watchdog, a Python project with 7,393 GitHub stars. SynthScan v2.0 examined 15,362 lines of code across 79 source files, recording 189 pattern matches distributed across 10 syntactic categories. The overall adjusted score of 14.6 places this repository in the Low 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 189 distinct pattern matches across 10 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 | tests/test_inotify_c.py | 44 | def test_late_double_deletion(helper: Helper, p: P, event_queue: TestEventQueue, start_watching: StartWatching) -> None: | CODE |
| LOW | tests/test_kqueue.py | 19 | def test_register_kevent_ignores_permission_errors(tmpdir, err): | CODE |
| LOW | tests/test_logging_event_handler.py | 63 | def test_logging_event_handler_dispatch(): | CODE |
| LOW | tests/test_isolated.py | 13 | def test_observer_stops_in_eventlet(): | CODE |
| LOW | tests/test_isolated.py | 21 | def test_eventlet_skip_repeat_queue(): | CODE |
| LOW | tests/test_snapshot_diff.py | 44 | def test_move_to_with_context_manager(p): | CODE |
| LOW | tests/test_snapshot_diff.py | 93 | def test_dir_modify_on_create(p): | CODE |
| LOW | tests/test_snapshot_diff.py | 112 | def test_detect_modify_for_moved_files(p): | CODE |
| LOW | tests/test_snapshot_diff.py | 123 | def test_replace_dir_with_file(p): | CODE |
| LOW⚡ | tests/test_observer.py | 35 | def test_schedule_should_start_emitter_if_running(observer): | CODE |
| LOW⚡ | tests/test_observer.py | 42 | def test_schedule_should_not_start_emitter_if_not_running(observer): | CODE |
| LOW⚡ | tests/test_observer.py | 48 | def test_start_should_start_emitter(observer): | CODE |
| LOW⚡ | tests/test_observer.py | 55 | def test_stop_should_stop_emitter(observer): | CODE |
| LOW | tests/test_observer.py | 88 | def test_schedule_after_unschedule_all(observer): | CODE |
| LOW | tests/test_observer.py | 110 | def test_start_failure_should_not_prevent_further_try(observer): | CODE |
| LOW | tests/test_observer.py | 135 | def test_schedule_failure_should_not_prevent_future_schedules(observer): | CODE |
| LOW | tests/test_observer.py | 152 | def test_context_manager_starts_observer(): | CODE |
| LOW | tests/test_observer.py | 168 | def test_context_manager_with_already_started_observer(): | CODE |
| LOW | tests/test_observer.py | 186 | def test_context_manager_stops_on_exit(): | CODE |
| LOW | tests/test_observer.py | 202 | def test_context_manager_handles_exceptions(): | CODE |
| LOW | tests/test_observer.py | 222 | def test_context_manager_with_scheduled_watches(): | CODE |
| LOW | tests/test_fsevents.py | 72 | def test_coalesced_event_check(event, expectation): | CODE |
| LOW | tests/test_fsevents.py | 210 | def test_unschedule_removed_folder(observer: BaseObserver, p: P) -> None: | CODE |
| LOW | tests/test_fsevents.py | 232 | def test_converting_cfstring_to_pyunicode(p: P, start_watching: StartWatching, events_checker: EventsChecker) -> None: | CODE |
| LOW | tests/test_fsevents.py | 248 | def test_recursive_check_accepts_relative_paths(p: P) -> None: | CODE |
| LOW | tests/utils.py | 217 | def _check_events_without_order(self, found_events: list[FileSystemEvent]) -> None: | CODE |
| LOW | tests/test_0_watchmedo.py | 78 | def test_shell_command_wait_for_completion(tmpdir, capfd): | CODE |
| LOW | tests/test_0_watchmedo.py | 90 | def test_shell_command_subprocess_termination_nowait(tmpdir): | CODE |
| LOW | tests/test_0_watchmedo.py | 101 | def test_shell_command_subprocess_termination_not_happening_on_file_opened_event( | CODE |
| LOW | tests/test_0_watchmedo.py | 115 | def test_auto_restart_not_happening_on_file_opened_event(tmpdir, capfd): | CODE |
| LOW | tests/test_0_watchmedo.py | 131 | def test_auto_restart_on_file_change(tmpdir, capfd): | CODE |
| LOW | tests/test_0_watchmedo.py | 154 | def test_auto_restart_on_file_change_debounce(tmpdir, capfd): | CODE |
| LOW | tests/test_0_watchmedo.py | 190 | def test_auto_restart_subprocess_termination(tmpdir, capfd, restart_on_command_exit): | CODE |
| LOW | tests/test_0_watchmedo.py | 209 | def test_auto_restart_arg_parsing_basic(): | CODE |
| LOW | tests/test_0_watchmedo.py | 218 | def test_auto_restart_arg_parsing(): | CODE |
| LOW | tests/test_0_watchmedo.py | 237 | def test_auto_restart_events_echoed(tmpdir, caplog): | CODE |
| LOW | tests/test_0_watchmedo.py | 254 | def test_logger_events_echoed(caplog): | CODE |
| LOW | tests/test_0_watchmedo.py | 269 | def test_shell_command_arg_parsing(): | CODE |
| LOW | tests/test_skip_repeats_queue.py | 24 | def test_allow_nonconsecutive(): | CODE |
| LOW | tests/test_skip_repeats_queue.py | 40 | def test_put_with_watchdog_events(): | CODE |
| LOW | tests/test_skip_repeats_queue.py | 67 | def test_consecutives_allowed_across_empties(): | CODE |
| LOW | tests/test_observers_api.py | 12 | def test_observer_constructor(): | CODE |
| LOW | tests/test_events.py | 41 | def test_file_delete_event_is_directory(): | CODE |
| LOW | tests/test_events.py | 56 | def test_file_modified_event_is_directory(): | CODE |
| LOW | tests/test_events.py | 88 | def test_file_closed_no_write_event(): | CODE |
| LOW | tests/test_events.py | 128 | def test_file_system_event_handler_dispatch(): | CODE |
| LOW | tests/test_events.py | 227 | def test_generate_sub_moved_events_repeated_dirname(): | CODE |
| LOW | tests/test_regex_matching_event_handler.py | 185 | def test_logging_event_handler_dispatch(): | CODE |
| LOW | tests/test_inotify_watch_group.py | 78 | def test_move_internal_symlink_followed(p): | CODE |
| LOW | tests/test_inotify_watch_group.py | 117 | def test_delete_watched_directory(p): | CODE |
| LOW | tests/test_inotify_watch_group.py | 130 | def test_delete_watched_directory_symlink_followed(p): | CODE |
| LOW | tests/test_inotify_watch_group.py | 149 | def test_delete_watched_directory_symlink_followed_recursive(p): | CODE |
| LOW | tests/test_inotify_watch_group.py | 170 | def test_unmount_watched_directory_filesystem(p): | CODE |
| LOW | tests/test_inotify_watch_group.py | 200 | def test_watch_groups_are_independent(p): | CODE |
| LOW | tests/test_inotify_watch_group.py | 224 | def assert_inotify_root_events(inotify_root: InotifyWatchGroup) -> None: | CODE |
| LOW | tests/test_emitter.py | 87 | def test_create_wrong_encoding( | CODE |
| LOW | tests/test_emitter.py | 267 | def test_separate_consecutive_moves( | CODE |
| LOW | tests/test_emitter.py | 307 | def test_fast_subdirectory_creation_deletion( | CODE |
| LOW | tests/test_emitter.py | 328 | def test_passing_unicode_should_give_unicode(p: P, event_queue: TestEventQueue, start_watching: StartWatching) -> None: | CODE |
| LOW | tests/test_emitter.py | 339 | def test_passing_bytes_should_give_bytes(p: P, event_queue: TestEventQueue, start_watching: StartWatching) -> None: | CODE |
| 12 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_inotify_c.py | 1 | CODE | |
| LOW | tests/conftest.py | 1 | CODE | |
| LOW | tests/test_pattern_matching_event_handler.py | 1 | CODE | |
| LOW | tests/test_kqueue.py | 1 | CODE | |
| LOW | tests/test_logging_event_handler.py | 1 | CODE | |
| LOW | tests/test_snapshot_diff.py | 1 | CODE | |
| LOW | tests/test_delayed_queue.py | 1 | CODE | |
| LOW | tests/test_observer.py | 1 | CODE | |
| LOW | tests/test_fsevents.py | 1 | CODE | |
| LOW | tests/shell.py | 8 | CODE | |
| LOW | tests/test_patterns.py | 1 | CODE | |
| LOW | tests/test_observers_winapi.py | 1 | CODE | |
| LOW | tests/utils.py | 1 | CODE | |
| LOW | tests/test_0_watchmedo.py | 1 | CODE | |
| LOW | tests/test_skip_repeats_queue.py | 1 | CODE | |
| LOW | tests/test_observers_polling.py | 1 | CODE | |
| LOW | tests/test_observers_api.py | 1 | CODE | |
| LOW | tests/test_events.py | 1 | CODE | |
| LOW | tests/test_regex_matching_event_handler.py | 1 | CODE | |
| LOW | tests/test_examples.py | 1 | CODE | |
| LOW | tests/test_inotify_watch_group.py | 1 | CODE | |
| LOW | tests/test_emitter.py | 1 | CODE | |
| LOW | docs/source/examples/debounced.py | 1 | CODE | |
| LOW | docs/source/examples/simple.py | 1 | CODE | |
| LOW | src/watchdog/watchmedo.py | 7 | CODE | |
| LOW | src/watchdog/version.py | 1 | CODE | |
| LOW | src/watchdog/events.py | 82 | CODE | |
| LOW | src/watchdog/utils/patterns.py | 8 | CODE | |
| LOW | src/watchdog/utils/__init__.py | 15 | CODE | |
| LOW | src/watchdog/utils/event_debouncer.py | 1 | CODE | |
| LOW | src/watchdog/utils/dirsnapshot.py | 32 | CODE | |
| LOW | src/watchdog/utils/delayed_queue.py | 6 | CODE | |
| LOW | src/watchdog/utils/platform.py | 1 | CODE | |
| LOW | src/watchdog/utils/process_watcher.py | 1 | CODE | |
| LOW | src/watchdog/utils/bricks.py | 20 | CODE | |
| LOW | src/watchdog/utils/echo.py | 26 | CODE | |
| LOW | src/watchdog/observers/fsevents.py | 8 | CODE | |
| LOW | src/watchdog/observers/inotify_move_event_grouper.py | 9 | CODE | |
| LOW | src/watchdog/observers/inotify.py | 69 | CODE | |
| LOW | src/watchdog/observers/__init__.py | 37 | CODE | |
| LOW | src/watchdog/observers/api.py | 1 | CODE | |
| LOW | src/watchdog/observers/winapi.py | 12 | CODE | |
| LOW | src/watchdog/observers/read_directory_changes.py | 1 | CODE | |
| LOW | src/watchdog/observers/kqueue.py | 58 | CODE | |
| LOW | src/watchdog/observers/inotify_c.py | 1 | CODE | |
| LOW | src/watchdog/observers/polling.py | 22 | CODE | |
| LOW | src/watchdog/observers/fsevents2.py | 8 | CODE | |
| LOW | src/watchdog/tricks/__init__.py | 26 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/conftest.py | 0 | convenience function to join the temporary directory path with the provided arguments. | STRING |
| HIGH | tests/test_observers_winapi.py | 0 | convenience function to join the temporary directory path with the provided arguments. | STRING |
| HIGH | tests/test_observers_polling.py | 0 | convenience function to join the temporary directory path with the provided arguments. | STRING |
| HIGH | src/watchdog/observers/inotify.py | 0 | observer thread that schedules watching directories and dispatches calls to event handlers. | STRING |
| HIGH | src/watchdog/observers/read_directory_changes.py | 0 | observer thread that schedules watching directories and dispatches calls to event handlers. | STRING |
| HIGH | src/watchdog/observers/kqueue.py | 0 | observer thread that schedules watching directories and dispatches calls to event handlers. | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_inotify_c.py | 44 | CODE | |
| LOW | tests/utils.py | 217 | CODE | |
| LOW | tests/test_emitter.py | 346 | CODE | |
| LOW | tests/test_emitter.py | 387 | CODE | |
| LOW | src/watchdog/watchmedo.py | 269 | CODE | |
| LOW | src/watchdog/watchmedo.py | 463 | CODE | |
| LOW | src/watchdog/utils/backwards_compat.py | 24 | CODE | |
| LOW | src/watchdog/utils/backwards_compat.py | 96 | CODE | |
| LOW | src/watchdog/utils/event_debouncer.py | 49 | CODE | |
| LOW | src/watchdog/utils/dirsnapshot.py | 321 | CODE | |
| LOW | src/watchdog/observers/fsevents.py | 161 | CODE | |
| LOW | src/watchdog/observers/inotify.py | 210 | CODE | |
| LOW | src/watchdog/observers/inotify.py | 319 | CODE | |
| LOW | src/watchdog/observers/inotify.py | 442 | CODE | |
| LOW | src/watchdog/observers/inotify.py | 502 | CODE | |
| LOW | src/watchdog/observers/__init__.py | 53 | CODE | |
| LOW | src/watchdog/observers/read_directory_changes.py | 67 | CODE | |
| LOW | src/watchdog/observers/kqueue.py | 424 | CODE | |
| LOW | src/watchdog/observers/kqueue.py | 494 | CODE | |
| LOW | src/watchdog/observers/kqueue.py | 610 | CODE | |
| LOW | src/watchdog/observers/inotify_c.py | 376 | CODE | |
| LOW | src/watchdog/observers/fsevents2.py | 200 | CODE | |
| LOW | src/watchdog/tricks/__init__.py | 268 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | docs/source/conf.py | 1 | # watchdog documentation build configuration file, created by | COMMENT |
| LOW | .github/workflows/build-and-publish.yml | 1 | # Because this library provides extension modules for macOS, but not for other | COMMENT |
| LOW | src/pythoncapi_compat.h | 1 | // Header file providing new C API functions to old Python versions. | COMMENT |
| LOW | src/pythoncapi_compat.h | 21 | #include <Python.h> | COMMENT |
| LOW | src/pythoncapi_compat.h | 41 | # if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 201710L) \ | COMMENT |
| LOW | src/pythoncapi_compat.h | 121 | # define Py_IsNone(x) Py_Is(x, Py_None) | COMMENT |
| LOW | src/pythoncapi_compat.h | 481 | COMMENT | |
| LOW | src/pythoncapi_compat.h | 541 | #if PY_VERSION_HEX < 0x030B00C1 && !defined(PYPY_VERSION) | COMMENT |
| LOW | src/pythoncapi_compat.h | 1221 | # define PyHASH_IMAG _PyHASH_IMAG | COMMENT |
| LOW | src/pythoncapi_compat.h | 1921 | #if PY_VERSION_HEX < 0x030C00A3 | COMMENT |
| LOW | src/pythoncapi_compat.h | 1941 | COMMENT | |
| LOW | src/watchdog_fsevents.c | 21 | #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13 | COMMENT |
| LOW | src/watchdog/observers/fsevents.py | 181 | COMMENT | |
| LOW | src/watchdog/observers/inotify.py | 221 | if event.is_moved_from: | COMMENT |
| LOW | src/watchdog/observers/kqueue.py | 441 | # of created and deleted events for the path. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_inotify_c.py | 28 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/test_fsevents.py | 36 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/test_emitter.py | 33 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/watchdog/utils/event_debouncer.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/watchdog/utils/process_watcher.py | 12 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/watchdog/observers/inotify_move_event_grouper.py | 21 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/watchdog/observers/inotify.py | 114 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/watchdog/observers/__init__.py | 91 | __all__ = ["Observer"] | CODE |
| LOW | src/watchdog/observers/inotify_c.py | 22 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/watchdog/observers/fsevents2.py | 65 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/watchdog/tricks/__init__.py | 42 | logger = logging.getLogger(__name__) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | src/watchdog/watchmedo.py | 799 | print(f"Error: {exc.args[0]}", file=sys.stderr) # noqa:T201 | CODE |
| LOW | src/watchdog/utils/process_watcher.py | 29 | except Exception: | CODE |
| LOW | src/watchdog/observers/fsevents.py | 302 | except Exception: | CODE |
| LOW | src/watchdog/observers/fsevents.py | 311 | except Exception: | CODE |
| LOW⚡ | src/watchdog/observers/__init__.py | 62 | except Exception: | CODE |
| LOW⚡ | src/watchdog/observers/__init__.py | 65 | except Exception: | CODE |
| LOW⚡ | src/watchdog/observers/__init__.py | 75 | except Exception: | CODE |
| LOW | src/watchdog/observers/api.py | 308 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_snapshot_diff.py | 169 | # Create a file and take a snapshot. | COMMENT |
| MEDIUM | tests/test_snapshot_diff.py | 206 | # Create a file and declare a DirectorySnapshot and a EmptyDirectorySnapshot. | COMMENT |
| MEDIUM | docs/source/conf.py | 4 | # This file is execfile()d with the current directory set to its containing dir. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/watchdog/observers/fsevents.py | 228 | # Check if we have a corresponding destination event in the watched path. | COMMENT |
| LOW | src/watchdog/observers/inotify_move_event_grouper.py | 73 | # Check if move_from is in delayqueue already | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/watchdog/utils/echo.py | 21 | def my_function(args): | STRING |