AI Slop Code Risk Monitor

ChatLab/ChatLab

SlopCodeMonitor badge for ChatLab/ChatLab Adjusted legacy signal; badge bands: 25 / 50 / 75 (different from dashboard bands).

Local-first chat history analyzer with AI. | 本地优先的 AI 聊天记录分析工具

2.7 Low pattern signal View on GitHub

Open-Source Code Quality, Security and Technical Debt Review

This report summarizes scanner evidence for ChatLab/ChatLab, a TypeScript project with 7,604 GitHub stars. SynthScan examined 317,250 lines of code across 1715 source files, recording 772 pattern matches distributed across 6 syntactic categories. The legacy adjusted pattern signal is 2.7 (Low pattern signal); it is not an authorship estimate.

Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.

2.7
Adjusted Signal
2.7
Raw Pattern Score
100%
Time Factor
2026-10-30
Last Push
7.6K
Stars
TypeScript
Language
317.2K
Lines of Code
1.7K
Files
772
Pattern Hits
2026-10-31
Scan Date
0.00
HC Hit Rate

Risk Review · Payload v1

Use each vector to guide manual verification of the underlying findings.

Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.

Cognitive Ownership Risk 11.4/100 · LOW

Can maintainers explain intent, assumptions, and trade-offs? 727 finding(s).

Hallucinated Dependency & Supply Chain Risk 0.4/100 · LOW

Are imports declared and package/API names verified? 25 finding(s).

Agent Over-Engineering Ratio 11.8/100 · LOW

Are wrappers, guards, and repeated structures necessary? 732 finding(s).

PR Review Velocity Impact 12.0/100 · LOW

Which changes need focused human review? 772 finding(s).

What These Metrics Mean

Adjusted Signal
Legacy pattern score normalized per 1,000 scanned lines and multiplied by the repository-level time factor. It is not an estimate of AI authorship.
Raw Pattern Score
Sum of severity- and context-weighted pattern findings before applying the time factor.
Time Factor
A coarse multiplier based on repository last-push metadata. It does not identify when individual code was written.
Pattern Hits
Count of configured pattern findings. Review each location and surrounding code before acting.
HC Hit Rate
High- and critical-severity findings per scanned file. Severity is a configured detector weight, not proof of a vulnerability or authorship.
Lines / Files
Scan coverage denominators used by the legacy normalized score.

Pattern-Signal History

This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.

Severity Breakdown

Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.

CRITICAL 0HIGH 0MEDIUM 20LOW 752

Directory Score Breakdown

This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.

Pattern Findings

The scanner identified 772 distinct pattern matches across 6 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. 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 configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.

Hyper-Verbose Identifiers712 hits · 738 pts
SeverityFileLineSnippetContext
LOWtests/chart-runtime/real-llm-chart-flow.e2e.test.ts77function convertJsonSchemaToParameters(schema: ToolDefinition['inputSchema']) {CODE
LOWtests/e2e/helpers/app-launcher.js31async function findAvailablePortWithReservation(CODE
LOWtests/e2e/helpers/app-launcher.js130function resolveElectronExecutable(deps = {}) {CODE
LOWpackages/web-runtime/src/capabilities.ts3export function detectBrowserCapabilities(): BrowserCapabilityReport {CODE
LOWpackages/web-runtime/src/sqlite/workspace-lease.ts20export async function acquireWebRuntimeWorkspaceLease(CODE
LOWpackages/web-runtime/src/sqlite/opfs.ts50export function normalizeOpfsPoolInitializationError(error: unknown): unknown {CODE
LOWpackages/web-runtime/src/worker/controller.ts578function createRequestCancelledError(): WebRuntimeError {CODE
LOWpackages/web-runtime/src/rpc/protocol.ts278export function isRpcWorkerRequestEnvelope(value: unknown): value is RpcWorkerRequestEnvelope {CODE
LOWpackages/web-runtime/src/import/browser-parser.ts67export function normalizeBrowserImportFormatId(formatId: string | undefined): BrowserImportFormatId | undefined {CODE
LOWpackages/web-runtime/src/import/browser-parser.ts73export async function detectBrowserImportFormat(source: BrowserParseSource): Promise<BrowserImportFormatId | null> {CODE
LOWpackages/web-runtime/src/import/browser-parser.ts89export async function scanBrowserMultiChatSource(CODE
LOWpackages/tools/src/agent-adapter.ts71export function createCrossChatAgentToolAdapters(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.test.ts134function privateContactsRankingResult(): CrossChatPrivateContactsRankingResult {CODE
LOWpackages/tools/src/definitions/cross-chat-tools.test.ts178function groupSessionsRankingResult(): CrossChatGroupSessionsRankingResult {CODE
LOWpackages/tools/src/definitions/cross-chat-tools.test.ts223function globalActivitySummaryResult(CODE
LOW…ckages/tools/src/definitions/retrieve-chat-evidence.ts184function keywordMessagesToCandidates(CODE
LOWpackages/tools/src/definitions/memory-tools.ts188async function assertResolvableEntityScope(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts469async function rankPrivateContactsHandler(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts539async function globalActivitySummaryHandler(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts557function buildGlobalActivityModelData(result: CrossChatGlobalActivitySummaryResult) {CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts594async function inspectContactSessionsHandler(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts633async function inspectSharedInteractionsHandler(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts972 function findLargestOverviewDetailLimit(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts987 function findLargestOverviewItemSlice(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1038function limitGlobalActivitySummaryToBudget(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1120function limitContactPageSizeToBudget(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1140function limitSharedRequestToBudget(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1203function limitContactResultToBudget(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1270function limitSharedModelResultToBudget(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1448function limitEntityResolutionToBudget(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1482function buildEntityResolutionScopePriority(resolution: CrossChatEntityResolution): EntityResolutionScopeItem[] {CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1508function buildEntityResolutionPayload(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1591function buildMinimalEntityResolutionPayload(CODE
LOWpackages/tools/src/definitions/cross-chat-tools.ts1675function summarizeEvidenceSelection(messages: CrossChatMessageSource[]): Record<string, number> {CODE
LOWpackages/tools/src/definitions/search-context.ts12export function trimMessagesPreservingHits(messages: RawMessage[], hitIds: number[], limit: number): RawMessage[] {CODE
LOWpackages/tools/src/sql/executor.ts69export function createAllSqlToolDefinitions(defs: SqlToolDef[]): ToolDefinition[] {CODE
LOWpackages/core/src/version.ts19function parseComparableCurrentVersion(version: string): ParsedComparableVersion | null {CODE
LOWpackages/core/src/merger/algorithms.ts78export function getCollidingPlatformIdsFromMessages(CODE
LOWpackages/core/src/merger/algorithms.ts118export function detectConflictsInMessages(CODE
LOWpackages/core/src/merger/algorithms.ts219export function deduplicateAndSortMessages(CODE
LOWpackages/core/src/ai/tool-catalog.ts24export function normalizeBuiltinToolNames(toolNames: readonly string[]): string[] {CODE
LOWpackages/core/src/ai/model-catalog.ts890export function getBuiltinModelsByProvider(providerId: string): ModelDefinition[] {CODE
LOWpackages/core/src/ai/thinking.ts228export function getSupportedThinkingLevels(provider: string, modelId: string): ThinkingLevel[] {CODE
LOWpackages/core/src/ai/streaming-think-parser.ts140export function needsStreamingThinkParsing(provider: string, _modelId: string): boolean {CODE
LOWpackages/core/src/nlp/text-utils.ts60export function stripVoiceTranscriptionPrefix(text: string): string {CODE
LOWpackages/core/src/nlp/text-utils.ts70export function isMediaPlaceholderContent(text: string): boolean {CODE
LOWpackages/core/src/query/message-sql.ts115export function buildExcludeKeywordsConditions(CODE
LOWpackages/core/src/query/message-query-functions.ts180export async function fetchSearchMessageContext(CODE
LOWpackages/core/src/query/global-insight.ts64export function getAnnualSummarySessionFacts(CODE
LOWpackages/core/src/query/global-insight.ts144export function aggregateAnnualSummaryFacts(CODE
LOWpackages/core/src/query/global-insight.ts243function getPrivateDirectContactsByDay(CODE
LOWpackages/core/src/query/global-insight.ts268function getGroupDirectContactsByDay(CODE
LOWpackages/core/src/query/global-insight.ts320function buildMonthlyDirectContacts(CODE
LOWpackages/core/src/query/contact-identity.ts5export function shouldScopeContactToSession(platform: ChatPlatform, contact: ContactMemberRef): boolean {CODE
LOWpackages/core/src/query/basic-queries.ts306export function getMessageLengthDistribution(db: DatabaseAdapter, filter?: TimeFilter): MessageLengthDistribution {CODE
LOWpackages/core/src/query/time-investment.ts61export function getTimeInvestmentSessionFacts(CODE
LOWpackages/core/src/query/time-investment.ts113export function estimateTimeInvestmentIntervals(CODE
LOWpackages/core/src/query/time-investment.ts158export function aggregateTimeInvestmentFacts(CODE
LOWpackages/core/src/query/time-investment.ts312function allocateIntervalsBySession(facts: TimeInvestmentAnalyzedFacts[]): Map<string, number> {CODE
LOWpackages/core/src/query/message-queries.ts530function getMemberNameHistoryFromMessages(db: DatabaseAdapter, memberId: number): MemberNameHistoryEntry[] {CODE
652 more matches not shown…
Decorative Section Separators20 hits · 60 pts
SeverityFileLineSnippetContext
MEDIUMpackages/core/src/ai/thinking.ts13// ── Types ─────────────────────────────────────────────────────────────────────COMMENT
MEDIUMpackages/core/src/ai/thinking.ts41// ── Internal: per-type level tables ──────────────────────────────────────────COMMENT
MEDIUMpackages/core/src/ai/thinking.ts117// ── Internal: model → ThinkingType classification ─────────────────────────────COMMENT
MEDIUMpackages/core/src/ai/thinking.ts220// ── Public API ────────────────────────────────────────────────────────────────COMMENT
MEDIUMpackages/http-routes/src/routes/web/merge.ts39 // ── parse (dual-mode) ──────────────────────────────────────────────COMMENT
MEDIUMpackages/http-routes/src/routes/web/merge.ts108 // ── conflicts ──────────────────────────────────────────────────────COMMENT
MEDIUMpackages/http-routes/src/routes/web/merge.ts131 // ── execute ────────────────────────────────────────────────────────COMMENT
MEDIUMpackages/http-routes/src/routes/web/merge.ts208 // ── clear ──────────────────────────────────────────────────────────COMMENT
MEDIUMpackages/http-routes/src/routes/web/merge.ts220 // ── export sessions for merge ──────────────────────────────────────COMMENT
MEDIUMpackages/node-runtime/src/cache/session-cache.test.ts55// ──────────────────────────────────────────────────────────────────────────────COMMENT
MEDIUMpackages/node-runtime/src/cache/session-cache.test.ts57// ──────────────────────────────────────────────────────────────────────────────COMMENT
MEDIUMpackages/node-runtime/src/cache/session-cache.test.ts90// ──────────────────────────────────────────────────────────────────────────────COMMENT
MEDIUMpackages/node-runtime/src/cache/session-cache.test.ts92// ──────────────────────────────────────────────────────────────────────────────COMMENT
MEDIUMpackages/node-runtime/src/cache/session-cache.test.ts119// ──────────────────────────────────────────────────────────────────────────────COMMENT
MEDIUMpackages/node-runtime/src/cache/session-cache.test.ts121// ──────────────────────────────────────────────────────────────────────────────COMMENT
MEDIUMapps/cli/src/daemon/service.ts52// ── Public types ──────────────────────────────────────────────────────COMMENT
MEDIUMapps/cli/src/daemon/service.ts69// ── macOS (launchd) ───────────────────────────────────────────────────COMMENT
MEDIUMapps/cli/src/daemon/service.ts185// ── Linux (systemd --user) ────────────────────────────────────────────COMMENT
MEDIUMapps/cli/src/daemon/service.ts275// ── Public API ────────────────────────────────────────────────────────COMMENT
MEDIUMsrc/components/AIChat/chat/ChatStatusBar.vue109// ── Thinking level selector ───────────────────────────────────────────────────COMMENT
Fake / Example Data25 hits · 25 pts
SeverityFileLineSnippetContext
LOWpackages/parser/src/native/shuakami-qq-native.test.ts156 message('placeholder', { uin: '0', uid: '未知', name: 'System' }, { text: 'skipped' }),CODE
LOWpackages/node-runtime/src/database-manager.test.ts1269 fs.writeFileSync(path.join(paths.getDatabaseDir(), 'session-with-topics.db'), 'placeholder')CODE
LOWpackages/node-runtime/src/database-manager.test.ts1308 fs.writeFileSync(dbPath, 'placeholder')CODE
LOWsrc/components/AIChat/input/AIChatComposer.vue283 :placeholder="placeholder"CODE
LOWsrc/components/common/Settings/AI/ApiKeyInput.vue56 :placeholder="placeholder"CODE
LOWsrc/i18n/locales/ja-JP/ai.json270 "placeholder": "質問を入力、または {'@'} で連絡先やグループを選択..."CODE
LOWsrc/i18n/locales/ja-JP/ai.json329 "placeholder": "SQL クエリを入力...",CODE
LOWsrc/i18n/locales/ja-JP/ai.json357 "placeholder": "例:発言数が最も多い上位10名のメンバーを検索、1日あたりのメッセージ数を集計、「旅行」というキーワードを含むメッセージを検索...",CODE
LOWsrc/i18n/locales/ja-JP/common.json129 "placeholder": "メンバーを検索",CODE
LOWsrc/i18n/locales/ja-JP/layout.json20 "placeholder": "新しい名前を入力してください"CODE
LOWsrc/i18n/locales/zh-CN/ai.json270 "placeholder": "输入问题,输入 {'@'} 选择联系人或群聊..."CODE
LOWsrc/i18n/locales/zh-CN/ai.json329 "placeholder": "输入 SQL 查询语句...",CODE
LOWsrc/i18n/locales/zh-CN/ai.json357 "placeholder": "例如:查找发言最多的前 10 个成员、统计每天的消息数量、找出包含「买房」关键词的消息...",CODE
LOWsrc/i18n/locales/zh-CN/common.json129 "placeholder": "搜索成员",CODE
LOWsrc/i18n/locales/zh-CN/layout.json20 "placeholder": "请输入新名称"CODE
LOWsrc/i18n/locales/zh-TW/ai.json270 "placeholder": "輸入問題,輸入 {'@'} 選擇聯絡人或群聊..."CODE
LOWsrc/i18n/locales/zh-TW/ai.json329 "placeholder": "輸入 SQL 查詢語句...",CODE
LOWsrc/i18n/locales/zh-TW/ai.json357 "placeholder": "例如:查找發言最多的前 10 個成員、統計每天的訊息數量、找出包含「買房」關鍵字的訊息...",CODE
LOWsrc/i18n/locales/zh-TW/common.json129 "placeholder": "搜尋成員",CODE
LOWsrc/i18n/locales/zh-TW/layout.json20 "placeholder": "請輸入新名稱"CODE
LOWsrc/i18n/locales/en-US/ai.json270 "placeholder": "Ask a question, or type {'@'} to select contacts or groups..."CODE
LOWsrc/i18n/locales/en-US/ai.json329 "placeholder": "Enter SQL query...",CODE
LOWsrc/i18n/locales/en-US/ai.json357 "placeholder": "E.g.: Find top 10 members by message count, count daily messages, find messages containing 'keyworCODE
LOWsrc/i18n/locales/en-US/common.json129 "placeholder": "Search members",CODE
LOWsrc/i18n/locales/en-US/layout.json20 "placeholder": "Enter new name"CODE
Structural Annotation Overuse8 hits · 16 pts
SeverityFileLineSnippetContext
LOWdocs/en/usage/quick-start.md9## Step 1: Import chat recordsCOMMENT
LOWdocs/en/usage/quick-start.md32## Step 2: Configure AICOMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts283 // Step 1: 创建系统目录COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts286 // Step 2: 如果当前 user_data_dir 指向了别处(如 CLI 写入的默认路径),COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts305 // Step 3: 写入 config.toml(数据库保留在旧 Electron 路径)COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts315 // Step 4: 复制系统数据(合并,不覆盖 ~/.chatlab/ 下已有的文件)COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts339 // Step 5: 删除旧路径下的系统数据(仅成功复制的目录)COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts349 // Step 6: 留说明文件COMMENT
Verbosity Indicators6 hits · 14 pts
SeverityFileLineSnippetContext
LOW⚡apps/desktop/main/paths/legacy-migration.ts283 // Step 1: 创建系统目录COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts286 // Step 2: 如果当前 user_data_dir 指向了别处(如 CLI 写入的默认路径),COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts305 // Step 3: 写入 config.toml(数据库保留在旧 Electron 路径)COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts315 // Step 4: 复制系统数据(合并,不覆盖 ~/.chatlab/ 下已有的文件)COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts339 // Step 5: 删除旧路径下的系统数据(仅成功复制的目录)COMMENT
LOW⚡apps/desktop/main/paths/legacy-migration.ts349 // Step 6: 留说明文件COMMENT
Over-Commented Block1 hit · 1 pts
SeverityFileLineSnippetContext
LOWpackages/parser-native/src/input.rs1//! Kernel input abstraction (first iteration).COMMENT