Repository Analysis

feder-cr/AIHawk

Born as an AI web agent that applied to jobs in bulk. Becoming a general one: an agent you point at the web and tell what to do.

46.3 Strong AI signal View on GitHub

Analysis Overview

This report presents the forensic synthetic code analysis of feder-cr/AIHawk, a Python project with 30,307 GitHub stars. SynthScan v2.0 examined 10,787 lines of code across 65 source files, recording 252 pattern matches distributed across 9 syntactic categories. The overall adjusted score of 46.3 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).

46.3
Adjusted Score
46.3
Raw Score
100%
Time Factor
2026-09-03
Last Push
30.3K
Stars
Python
Language
10.8K
Lines of Code
65
Files
252
Pattern Hits
2026-09-03
Scan Date
0.32
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 21MEDIUM 51LOW 180

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 252 distinct pattern matches across 9 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.

Decorative Section Separators47 hits · 200 pts
SeverityFileLineSnippetContext
MEDIUMtests/test_cli_surface.py95# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_cli_surface.py97# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_cli_surface.py191# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_cli_surface.py193# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_cli_surface.py351# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_cli_surface.py353# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_cli_surface.py386# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_cli_surface.py388# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_cli_surface.py429# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_cli_surface.py431# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_web_service.py78# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_web_service.py80# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_web_service.py146# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_web_service.py148# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_web_service.py204# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_web_service.py206# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_web_service.py238# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_web_service.py240# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_openrouter_only.py147# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_openrouter_only.py149# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_openrouter_only.py223# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_openrouter_only.py225# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_openrouter_only.py280# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_openrouter_only.py282# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_openrouter_only.py320# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_openrouter_only.py327# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_agent_loop.py213# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_agent_loop.py215# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_agent_loop.py364# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_agent_loop.py366# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_agent_loop.py421# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_agent_loop.py423# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_agent_loop.py64# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_agent_loop.py66# --------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py42# ---------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py44# ---------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py93# ---------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py95# ---------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py137# ── what the mutation test asked for ────────────────────────────────────────COMMENT
MEDIUMtests/test_key_isolation.py215# ---------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py217# ---------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py297# ---------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py299# ---------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py329# ---------------------------------------------------------------------------COMMENT
MEDIUMtests/test_key_isolation.py331# ---------------------------------------------------------------------------COMMENT
MEDIUMscripts/check_english_only.py224# ── the selftest ────────────────────────────────────────────────────────────COMMENT
MEDIUM.github/workflows/publish-wiki.yml1# ─────────────────────────────────────────────────────────────────────────────COMMENT
Hyper-Verbose Identifiers145 hits · 140 pts
SeverityFileLineSnippetContext
LOWtests/test_readme_offers_both.py54def test_both_ways_in_are_offered():CODE
LOWtests/test_readme_offers_both.py85def test_the_offer_comes_within_the_first_screen():CODE
LOWtests/test_readme_offers_both.py105def test_the_check_fails_on_the_pages_as_they_used_to_be():CODE
LOWtests/test_readme_offers_both.py131def test_the_two_ways_are_offered_as_one_choice():CODE
LOWtests/test_readme_offers_both.py146def test_the_offer_says_what_each_one_costs_the_reader():CODE
LOWtests/test_readme_offers_both.py164def test_no_tool_name_that_does_not_exist():CODE
LOWtests/test_readme_offers_both.py184def test_no_hand_written_count_of_tools():CODE
LOWtests/test_agent.py60def test_result_text_falls_back_for_non_text_content():CODE
LOWtests/test_agent.py70def test_mcp_tools_to_openai_shape():CODE
LOWtests/test_agent.py77async def test_run_task_drives_tools_then_returns_final_answer():CODE
LOWtests/test_real_cli.py12def test_do_reads_a_data_url_heading():CODE
LOWtests/test_llm.py5def test_key_arg_wins_then_env_then_error():CODE
LOWtests/test_llm.py12def test_model_arg_env_default():CODE
LOWtests/test_cli_surface.py99def test_missing_key_exits_one_and_names_both_ways_to_supply_one(drive):CODE
LOWtests/test_cli_surface.py195def test_every_option_reaches_drive_with_the_right_name_and_type(drive):CODE
LOWtests/test_cli_surface.py355def test_the_result_is_printed_verbatim_with_one_trailing_newline(monkeypatch):CODE
LOWtests/test_cli_surface.py390def test_group_help_works_and_names_openrouter():CODE
LOWtests/test_cli_surface.py421def test_bare_invocation_shows_the_do_command():CODE
LOWtests/test_cli_surface.py433def test_the_key_is_never_echoed_on_any_path(monkeypatch):CODE
LOWtests/test_cli_surface.py116def test_explicit_key_wins_and_the_environment_is_not_consulted(drive, monkeypatch):CODE
LOWtests/test_cli_surface.py132def test_key_is_taken_from_the_environment_when_the_flag_is_absent(drive, monkeypatch):CODE
LOWtests/test_cli_surface.py144def test_an_openai_key_in_the_environment_is_not_accepted(drive, monkeypatch):CODE
LOWtests/test_cli_surface.py161def test_the_command_offers_no_second_provider():CODE
LOWtests/test_cli_surface.py177def test_the_cli_does_not_put_the_key_into_its_own_environment(drive, monkeypatch):CODE
LOWtests/test_cli_surface.py230def test_defaults_are_none_headless_and_the_default_model(drive):CODE
LOWtests/test_cli_surface.py250def test_the_option_names_are_the_ones_the_runner_reads(drive):CODE
LOWtests/test_cli_surface.py280def test_without_headed_the_child_is_left_headless(drive):CODE
LOWtests/test_cli_surface.py292def test_a_non_numeric_seed_is_a_usage_error(drive):CODE
LOWtests/test_cli_surface.py306def test_the_task_argument_is_required(drive):CODE
LOWtests/test_cli_surface.py319def test_an_unknown_option_is_a_usage_error(drive):CODE
LOWtests/test_cli_surface.py327def test_the_task_reaches_drive_verbatim(drive):CODE
LOWtests/test_cli_surface.py340def test_drive_is_called_exactly_once(drive):CODE
LOWtests/test_cli_surface.py372def test_an_empty_result_prints_only_a_newline(monkeypatch):CODE
LOWtests/test_cli_surface.py405def test_do_help_works_and_names_openrouter_and_the_env_variables():CODE
LOWtests/test_cli_surface.py480def test_the_key_detector_is_not_vacuous(monkeypatch):CODE
LOWtests/test_cli_surface.py499def test_the_key_option_cannot_echo_its_own_value_in_a_usage_error():CODE
LOWtests/test_web_service.py82async def test_the_instruction_is_emitted_by_the_service_not_added_by_the_page():CODE
LOWtests/test_web_service.py150async def test_stop_cancels_a_run_in_flight_and_says_so():CODE
LOWtests/test_web_service.py208async def test_the_app_exposes_exactly_the_routes_the_page_calls():CODE
LOWtests/test_web_service.py217async def test_the_live_view_asks_for_nothing_until_an_instruction_has_been_given():CODE
LOWtests/test_web_service.py98async def test_a_turn_brackets_itself_with_busy():CODE
LOWtests/test_web_service.py113async def test_state_is_not_transcript():CODE
LOWtests/test_web_service.py128async def test_the_replay_flag_is_on_history_and_not_on_live_events():CODE
LOWtests/test_web_service.py174async def test_stop_with_nothing_running_is_false_rather_than_an_error():CODE
LOWtests/test_web_service.py186async def test_a_failing_brain_reports_and_still_clears_busy():CODE
LOWtests/test_web_service.py257async def test_the_address_comes_from_the_active_tab():CODE
LOWtests/test_web_service.py280async def test_an_older_server_leaves_the_strip_empty_instead_of_breaking_the_pane():CODE
LOWtests/test_web_service.py293async def test_the_strip_asks_nothing_before_an_instruction():CODE
LOWtests/test_openrouter_only.py151def test_explicit_key_wins_over_the_environment():CODE
LOWtests/test_openrouter_only.py156def test_environment_key_is_used_when_no_argument_is_given():CODE
LOWtests/test_openrouter_only.py161def test_missing_key_raises_and_names_both_ways_to_supply_one():CODE
LOWtests/test_openrouter_only.py227def test_base_url_constant_points_at_openrouter_over_https():CODE
LOWtests/test_openrouter_only.py234def test_no_other_provider_host_appears_in_the_module():CODE
LOWtests/test_openrouter_only.py241def test_client_base_url_is_openrouter_even_with_openai_base_url_set(foreign_env):CODE
LOWtests/test_openrouter_only.py284def test_model_explicit_wins_over_the_environment():CODE
LOWtests/test_openrouter_only.py289def test_model_environment_used_when_no_argument():CODE
LOWtests/test_openrouter_only.py294def test_model_falls_back_to_the_default_constant():CODE
LOWtests/test_openrouter_only.py306def test_model_ignores_other_environment_names():CODE
LOWtests/test_openrouter_only.py313def test_empty_model_falls_through_to_the_default():CODE
LOWtests/test_openrouter_only.py337def test_environment_cannot_replace_the_outgoing_authorization_header(clean_env):CODE
85 more matches not shown…
Cross-Language Confusion21 hits · 120 pts
SeverityFileLineSnippetContext
HIGHtests/test_ui_drive.py180 window.clicked.push(index + 1);CODE
HIGHtests/test_ui_drive.py685 "() => { return document.querySelector('#late') !== null; }",CODE
HIGHtests/test_ui_drive.py710 " return ids.filter(function (id) { return document.getElementById(id) !== null; }).length; }"CODE
HIGHsrc/aihawk/web.py443 live = null;CODE
HIGHsrc/aihawk/web.py451 if(text.length <= LONG && text.indexOf('\n') < 0){CODE
HIGHsrc/aihawk/web.py461 p.append(el('span','sr', kind === 'err' ? 'error ' : ''), el('span', null, text));CODE
HIGHsrc/aihawk/web.py481 if(!busyNow){ flush(true, r); live = null; clearInterval(timer);CODE
HIGHsrc/aihawk/web.py482 if(queued){ const t = queued; queued = null; send(t); } }CODE
HIGHsrc/aihawk/web.py484 case 'you': flush(false, r); live = null; newTurn();CODE
HIGHsrc/aihawk/web.py377 if(c) e.className = c; if(x != null) e.textContent = x; return e; };CODE
HIGHsrc/aihawk/web.py394let turn = null, live = null, hold = null, n = 0, t0 = 0, timer = 0;CODE
HIGHsrc/aihawk/web.py395let busyNow = false, queued = null, pinned = false, settle = 0;CODE
HIGHsrc/aihawk/web.py410 if(hold === null) return;CODE
HIGHsrc/aihawk/web.py412 hold = null;CODE
HIGHsrc/aihawk/web.py423 lab.appendChild(el('b', null, (VERB[name] || ['Calling','Called'])[0]));CODE
HIGHsrc/aihawk/web.py424 if(arg){ lab.append(' ', el('code', null, arg)); }CODE
HIGHsrc/aihawk/web.py527chip.onclick = () => { i.value = queued; queued = null; i.focus();CODE
HIGHsrc/aihawk/web.py549 $('tok').textContent = k(u.last_prompt || 0) + ' ctx / ' +CODE
HIGHsrc/aihawk/web.py550 k((u.prompt || 0) + (u.completion || 0)) + ' total';CODE
HIGHsrc/aihawk/web.py604 if(!rows || rows.length < 2){ box.hidden = true; box.textContent = ''; return; }CODE
HIGHsrc/aihawk/web.py615 b.appendChild(el('span','t', r.title || host || r.id));CODE
Unused Imports18 hits · 15 pts
SeverityFileLineSnippetContext
LOWtests/test_readme_offers_both.py21CODE
LOWtests/test_cli_surface.py14CODE
LOWtests/test_web_service.py13CODE
LOWtests/test_openrouter_only.py23CODE
LOWtests/test_ui_drive.py28CODE
LOWtests/test_agent_loop.py45CODE
LOWtests/test_every_tool_reads_as_english.py18CODE
LOWtests/test_key_isolation.py18CODE
LOWscripts/check_english_only.py27CODE
LOWsrc/aihawk/link.py23CODE
LOWsrc/aihawk/runner.py14CODE
LOWsrc/aihawk/web.py26CODE
LOWsrc/aihawk/actions_help.py11CODE
LOWsrc/aihawk/llm.py2CODE
LOWsrc/aihawk/brain.py20CODE
LOWsrc/aihawk/cli.py2CODE
LOWsrc/aihawk/agent.py15CODE
LOWsrc/aihawk/agent.py18CODE
Modern AI Meta-Vocabulary4 hits · 9 pts
SeverityFileLineSnippetContext
MEDIUMdocs/is-openai-operator-still-available.md147- [OpenAI help: ChatGPT agent](https://help.openai.com/en/articles/11752874-chatgpt-agent) and [OpenAI help: Evolving AtCODE
MEDIUMdocs/best-ai-browser-agent.md166- [Wikipedia: OpenAI Operator](https://en.wikipedia.org/wiki/OpenAI_Operator), retrieved 2026-09-03, and [OpenAI help: ECODE
MEDIUMdocs/openai-operator-alternatives.md176- [OpenAI help: ChatGPT agent](https://help.openai.com/en/articles/11752874-chatgpt-agent) and [OpenAI help: Evolving AtCODE
MEDIUMsrc/aihawk/agent.py102 # size IS the current occupancy of the context window; adding them upCOMMENT
Over-Commented Block8 hits · 8 pts
SeverityFileLineSnippetContext
LOWpyproject.toml21 "Programming Language :: Python :: 3.12",COMMENT
LOWtests/test_key_isolation.py141# thinner than it looked: four of five mutations survived, and two of themCOMMENT
LOWscripts/check_english_only.py41#: add them will come back:COMMENT
LOWscripts/check_english_only.py101 return {w for w in ITALIANCOMMENT
LOWscripts/check_english_only.py121#: for Italian that sat in upstream code below the patch.COMMENT
LOW.github/workflows/publish.yml1name: publishCOMMENT
LOW.github/workflows/publish.yml81 # served 14 tools, the checkout offered 15, and the aihawk suite failed onCOMMENT
LOW.github/workflows/publish-wiki.yml1# ─────────────────────────────────────────────────────────────────────────────COMMENT
Excessive Try-Catch Wrapping6 hits · 6 pts
SeverityFileLineSnippetContext
LOWsrc/aihawk/link.py77 except Exception:CODE
LOWsrc/aihawk/link.py134 except Exception:CODE
LOWsrc/aihawk/web.py703 except Exception as exc:CODE
LOWsrc/aihawk/web.py753 except Exception as exc:CODE
LOWsrc/aihawk/web.py779 except Exception:CODE
LOWsrc/aihawk/agent.py153 except Exception as exc:CODE
Deep Nesting2 hits · 2 pts
SeverityFileLineSnippetContext
LOWscripts/build_wiki.py19CODE
LOWsrc/aihawk/brain.py51CODE
Overly Generic Function Names1 hit · 1 pts
SeverityFileLineSnippetContext
LOWsrc/aihawk/agent.py164async def run_task(mcp, task: str, *, client, model: str, max_turns: int = 25,CODE