Skip to content

Fix audit bugs, verify AI bot classifications against primary sources - #11

Merged
vesivanov merged 6 commits into
mainfrom
fix/ai-agent-legacy-crawler-rows
Jul 23, 2026
Merged

Fix audit bugs, verify AI bot classifications against primary sources#11
vesivanov merged 6 commits into
mainfrom
fix/ai-agent-legacy-crawler-rows

Conversation

@vesivanov

Copy link
Copy Markdown
Owner

Summary

  • Fixes the critical/medium bugs from a full audit: UTC timezone mismatch in the daily trend chart, the GoogleAgent pattern not matching Google's real hyphenated Google-Agent token, a hand-maintained AI_BOT_NAMES_SQL list that had silently drifted (missing ClaudeBot), plus several smaller correctness/UX issues (row-key normalization, dead code, chart layout shift, pre-merge SQL LIMIT truncation, category filter on queryFiltered, empty-period gaps, empty-selection chart skeleton, a map-mutation bug).
  • Adds and rigorously re-verifies AI bot detection: two research passes added ~24 new bots, then a follow-up pass checked every addition against the operating company's own documentation (not just third-party aggregators). That check found real problems — removed 7 bots with no reliable evidence they exist (ExaBot even collided with an unrelated Exalead crawler), and recategorized 3 more (KagiBot, PetalBot, Google-CloudVertexBot) that had been tagged AI-search/training on "the company does AI stuff" reasoning rather than the bot's own documented purpose.
  • Codifies the classification bar in a comment at the top of bots.ts so that mistake isn't repeated.
  • Adds a UA smoke test (bots-smoke.test.ts) that builds a realistic User-Agent for every PATTERNS entry and asserts detectBot() resolves it correctly — catches pattern-ordering and version-qualifier mistakes automatically.

Test plan

  • npx vitest run src — 199/199 pass
  • npx tsc --noEmit — clean
  • npx eslint src — clean
  • npm run build — production build succeeds

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

vesivanov and others added 5 commits July 23, 2026 16:38
categoryFilterSql() only matched exact bot_category values at the SQL
level, but legacy rows persisted as 'ai_crawler' (before per-bot
categories existed) were excluded — normalizeBotCategory() never got
a chance to remap them. The daily trend and other SQL-filtered panels
would appear flat/empty when selecting specific AI chips like 'AI agent'.

Now ai_agent/ai_search/ai_training filters also match the relevant
ai_crawler rows via bot_name, matching the JS-side normalization.

Also adds claude-code and Google-NotebookLM to AI_AGENT_BOTS for
correct legacy remapping.
…normalized status rows

- Add PhindBot, Andibot, Grok-DeepSearch to AI_SEARCH_BOTS so legacy
  ai_crawler rows for these search bots are correctly remapped.
- Add all 36 missing AI-categorized bots to AI_BOT_NAMES_SQL for a
  complete name-based safety net in AI confidence queries.
- Merge normalized bot status rows in fetchStatusBatch to prevent
  duplicate React keys when legacy ai_crawler rows now correctly
  appear alongside their ai_agent/ai_search counterparts.
- fillDailyTrend used local-timezone date arithmetic while the server sends
  UTC-keyed data, shifting the whole trend window by a day for non-UTC
  users; now delegates to the already-correct, already-tested
  fillDatePeriods instead of a second, buggy reimplementation.
- GoogleAgent pattern only matched the no-hyphen variant; Google's real
  token is the hyphenated Google-Agent, so every user-triggered-agent
  request was previously invisible (fell through to null, not even a
  generic bot).
- AI_BOT_NAMES_SQL was a hand-maintained literal list that had drifted out
  of sync (missing ClaudeBot, Anthropic's own training crawler); now
  derived from PATTERNS at module load so it can't drift again.
- bots-table.tsx row key and overview-view.tsx's AiCrawlsVsVisits used raw/
  dead category values instead of normalized ones.
- Chart mode switch (total vs. category) caused a layout shift from a
  height-constrained wrapper only applied in one mode.
- Pre-merge SQL LIMITs on (bot_name, bot_category) groupings didn't account
  for JS-side category normalization collapsing two raw rows into one,
  silently truncating top-N results; doubled the raw limits to compensate
  (mirrors the existing LIMIT * 2 pattern in allBotDetails).
- queryFiltered()'s category filter used naive equality instead of
  categoryFilterSql(), so it wouldn't have handled the "ai" pseudo-category
  or ai_crawler remapping if the events view ever exposed a category filter.
- Category-trend view for week/month granularity didn't zero-fill empty
  periods like the total-trend view does; deselecting all categories still
  rendered empty chart axes instead of just the message; aggregateDailyCategory
  mutated map values in place instead of replacing them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two research passes: first added 15 missing bots the audit flagged, then a
wider web search surfaced 9 more from the ai.robots.txt registry. Re-checking
every addition against the operating company's own documentation (rather
than third-party aggregators) found real problems, now corrected:

- Removed CopilotBot, ExaBot, GoogleAgent-Mariner, Google-Gemini-CLI,
  Google-Firebase, Cursor, and Trae — no reliable evidence any of these UA
  tokens actually exist (ExaBot in particular collides with an unrelated,
  decades-old Exalead crawler; GoogleAgent-Mariner's underlying product,
  Project Mariner, was discontinued by Google before this was even added).
- Recategorized KagiBot, PetalBot, and Google-CloudVertexBot out of the ai_*
  buckets: each was tagged ai_search/ai_training on "the operator makes AI
  products elsewhere" reasoning, but their own docs describe them as
  general search-index or owner-initiated agent-building crawlers, not
  bots that train models or feed AI-generated answers.
- Kept the well-corroborated remainder (GoogleAgent-URLContext, TavilyBot,
  PanguBot, Ai2Bot-Dolma, Devin, Manus-User, NovaAct, TongyiBot, YiyanBot,
  ICC-Crawler, Google-GeminiNotebook, kagi-fetcher, KimiBot/Kimi-User,
  TikTokSpider), each confirmed by the operator's own docs or multiple
  independent trackers.
- Corrected "Manus Bot" (speculative, no evidence) to the verified
  "Manus-User" token.

Added a classification-rule comment at the top of bots.ts codifying the bar
for ai_training/ai_search/ai_agent, so this mistake isn't repeated: the
operating company's own docs must state THIS SPECIFIC bot's purpose, not
just that the company is an AI business.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Builds a realistic synthetic User-Agent for each bots.ts PATTERNS entry and
asserts detectBot() resolves it back to that exact name/category. Catches
mis-ordered patterns (a more specific token accidentally matched by an
earlier, broader pattern) and version/qualifier requirements (e.g.
Devin\/\d needing a version suffix) that a name-only glance wouldn't reveal.
A small override map covers entries where the display name intentionally
differs from the literal UA token the regex matches (e.g. "Slack" vs.
"Slackbot-LinkExpanding").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bot-observability Ready Ready Preview, Comment Jul 23, 2026 4:34pm

@vesivanov
vesivanov merged commit ff7117c into main Jul 23, 2026
6 checks passed
@vesivanov
vesivanov deleted the fix/ai-agent-legacy-crawler-rows branch July 23, 2026 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant