AI Slop Code Risk Monitor

google-ai-edge/gallery

SlopCodeMonitor badge for google-ai-edge/gallery Adjusted legacy signal; badge bands: 25 / 50 / 75 (different from dashboard bands).

A gallery that showcases on-device ML/GenAI use cases and allows people to try and use models locally.

0.8 Low pattern signal View on GitHub

Open-Source Code Quality, Security and Technical Debt Review

This report summarizes scanner evidence for google-ai-edge/gallery, a Kotlin project with 25,167 GitHub stars. SynthScan examined 170,019 lines of code across 656 source files, recording 96 pattern matches distributed across 6 syntactic categories. The legacy adjusted pattern signal is 0.8 (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.

0.8
Adjusted Signal
0.8
Raw Pattern Score
100%
Time Factor
2026-10-31
Last Push
25.2K
Stars
Kotlin
Language
170.0K
Lines of Code
656
Files
96
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 4.0/100 · LOW

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

Hallucinated Dependency & Supply Chain Risk 0.1/100 · LOW

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

Agent Over-Engineering Ratio 0.0/100 · LOW

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

PR Review Velocity Impact 3.1/100 · LOW

Which changes need focused human review? 96 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 2MEDIUM 1LOW 93

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 96 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.

Structural Annotation Overuse36 hits · 57 pts
SeverityFileLineSnippetContext
LOWmcp/README.md18### Step 1: Start the Server in StreamableHTTP ModeCOMMENT
LOWmcp/README.md38### Step 2: Expose the Server via a Public URLCOMMENT
LOWmcp/README.md51### Step 3: Add MCP server URLCOMMENT
LOWmcp/README.md65### Step 4: Try a promptCOMMENT
LOW⚡mcp/README.md81### Step 1: Set Up Credentials in Google CloudCOMMENT
LOW⚡mcp/README.md85### Step 2: Add the Cloud Server with Custom HeadersCOMMENT
LOW⚡mcp/README.md95### Step 3: Try a PromptCOMMENT
LOW⚡…oogle/ai/edge/gallery/ui/llmchat/LlmChatModelHelper.kt484 // Step 1: Start the turn before processing the input, so its latency includes the inputCOMMENT
LOW⚡…oogle/ai/edge/gallery/ui/llmchat/LlmChatModelHelper.kt490 // Step 2: Assemble multimodal prompt attachments (images, audio clips, and text).COMMENT
LOW⚡…oogle/ai/edge/gallery/ui/llmchat/LlmChatModelHelper.kt503 // Step 3: Configure extra runtime parameters (such as thinking reasoning mode).COMMENT
LOW⚡…oogle/ai/edge/gallery/ui/llmchat/LlmChatModelHelper.kt512 // Step 4: Dispatch asynchronous streaming inference to the native LiteRT-LM engine.COMMENT
LOW⚡…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt879 // Step 7: Merge adjacent or overlapping matches for scrubber range indicators.COMMENT
LOW⚡…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt882 // Step 8: Publish search results (sorted by similarity score descending) and mergedCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt704 // Step 1: Update UI state to indicate that a search is in progress. Previous results areCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt718 // Step 2: Ensure the retrieval service is available.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt730 // Step 3: Validate video duration and local video file existence.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt753 // Step 4: Query the vector store for the top K windows belonging to this project.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt777 // Step 5: Map retrieved records back to their time windows.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt822 // Step 6: Extract representative preview frames for each unmerged moment in top-KCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1190 // Step 1: Validate video duration and file existence. A zero duration means the importCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1246 // Step 2: Calculate sliding time windows and sample frame timestamps.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1281 // Step 3: Decide whether this pass interleaves audio with the frames it indexes.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1317 // Step 4: Extract each window's frames and matching audio, then index their embedding.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1481 // Step 5: Persist configuration parameters to DataStore. The embeddings themselves nowCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1523 // Step 6: Update UI state with the processed project and clear progress.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1537 // Step 7: Automatically execute search if a pending query was specified.COMMENT
LOW…/main/assets/skills/query-wikipedia/scripts/index.html31 // Step 1: Fuzzy search to get the exact title and the clean introductionCOMMENT
LOW…/main/assets/skills/query-wikipedia/scripts/index.html56 // Step 2: Fetch the HTML of Section 0 (the top of the page) to grab the infoboxCOMMENT
LOW…/main/assets/skills/query-wikipedia/scripts/index.html96 // Step 3: Combine Infobox and ExtractCOMMENT
LOW…/main/assets/skills/query-wikipedia/scripts/index.html107 // Step 4: Apply language-based safety capsCOMMENT
LOWskills/built-in/query-wikipedia/scripts/index.html31 // Step 1: Fuzzy search to get the exact title and the clean introductionCOMMENT
LOWskills/built-in/query-wikipedia/scripts/index.html56 // Step 2: Fetch the HTML of Section 0 (the top of the page) to grab the infoboxCOMMENT
LOWskills/built-in/query-wikipedia/scripts/index.html96 // Step 3: Combine Infobox and ExtractCOMMENT
LOWskills/built-in/query-wikipedia/scripts/index.html107 // Step 4: Apply language-based safety capsCOMMENT
LOWskills/featured/mood-music/SKILL.md16### Step 1: Fetch Available GenresCOMMENT
LOWskills/featured/mood-music/SKILL.md21### Step 2: Analyze and GenerateCOMMENT
Verbosity Indicators27 hits · 41 pts
SeverityFileLineSnippetContext
LOW⚡…oogle/ai/edge/gallery/ui/llmchat/LlmChatModelHelper.kt484 // Step 1: Start the turn before processing the input, so its latency includes the inputCOMMENT
LOW⚡…oogle/ai/edge/gallery/ui/llmchat/LlmChatModelHelper.kt490 // Step 2: Assemble multimodal prompt attachments (images, audio clips, and text).COMMENT
LOW⚡…oogle/ai/edge/gallery/ui/llmchat/LlmChatModelHelper.kt503 // Step 3: Configure extra runtime parameters (such as thinking reasoning mode).COMMENT
LOW⚡…oogle/ai/edge/gallery/ui/llmchat/LlmChatModelHelper.kt512 // Step 4: Dispatch asynchronous streaming inference to the native LiteRT-LM engine.COMMENT
LOW⚡…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt879 // Step 7: Merge adjacent or overlapping matches for scrubber range indicators.COMMENT
LOW⚡…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt882 // Step 8: Publish search results (sorted by similarity score descending) and mergedCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt704 // Step 1: Update UI state to indicate that a search is in progress. Previous results areCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt718 // Step 2: Ensure the retrieval service is available.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt730 // Step 3: Validate video duration and local video file existence.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt753 // Step 4: Query the vector store for the top K windows belonging to this project.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt777 // Step 5: Map retrieved records back to their time windows.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt822 // Step 6: Extract representative preview frames for each unmerged moment in top-KCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1190 // Step 1: Validate video duration and file existence. A zero duration means the importCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1246 // Step 2: Calculate sliding time windows and sample frame timestamps.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1281 // Step 3: Decide whether this pass interleaves audio with the frames it indexes.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1317 // Step 4: Extract each window's frames and matching audio, then index their embedding.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1481 // Step 5: Persist configuration parameters to DataStore. The embeddings themselves nowCOMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1523 // Step 6: Update UI state with the processed project and clear progress.COMMENT
LOW…mtasks/videomomentfinder/VideoMomentFinderViewModel.kt1537 // Step 7: Automatically execute search if a pending query was specified.COMMENT
LOW…/main/assets/skills/query-wikipedia/scripts/index.html31 // Step 1: Fuzzy search to get the exact title and the clean introductionCOMMENT
LOW…/main/assets/skills/query-wikipedia/scripts/index.html56 // Step 2: Fetch the HTML of Section 0 (the top of the page) to grab the infoboxCOMMENT
LOW…/main/assets/skills/query-wikipedia/scripts/index.html96 // Step 3: Combine Infobox and ExtractCOMMENT
LOW…/main/assets/skills/query-wikipedia/scripts/index.html107 // Step 4: Apply language-based safety capsCOMMENT
LOWskills/built-in/query-wikipedia/scripts/index.html31 // Step 1: Fuzzy search to get the exact title and the clean introductionCOMMENT
LOWskills/built-in/query-wikipedia/scripts/index.html56 // Step 2: Fetch the HTML of Section 0 (the top of the page) to grab the infoboxCOMMENT
LOWskills/built-in/query-wikipedia/scripts/index.html96 // Step 3: Combine Infobox and ExtractCOMMENT
LOWskills/built-in/query-wikipedia/scripts/index.html107 // Step 4: Apply language-based safety capsCOMMENT
Over-Commented Block27 hits · 27 pts
SeverityFileLineSnippetContext
LOWmodel_allowlists/README.md1# This is a readme fileCOMMENT
LOW…c/main/java/com/google/ai/edge/gallery/MainActivity.kt141 // Show splash screen.COMMENT
LOW…om/google/ai/edge/gallery/ui/modelmanager/ModelList.kt441 alpha = animation.descriptionProgress * 0.6fCOMMENT
LOW…om/google/ai/edge/gallery/ui/modelmanager/ModelList.kt461// }COMMENT
LOW…/java/com/google/ai/edge/gallery/ui/common/TaskIcon.kt121// @ComposableCOMMENT
LOW…va/com/google/ai/edge/gallery/ui/common/ModelPicker.kt161 showMemoryWarning = falseCOMMENT
LOW…i/edge/gallery/ui/common/chat/BenchmarkConfigDialog.kt101// @Preview(showBackground = true)COMMENT
LOW…ai/edge/gallery/ui/common/chat/MessageBodyBenchmark.kt101 }COMMENT
LOW…ai/edge/gallery/ui/common/chat/MessageBodyBenchmark.kt121// "stat2" to 0.4f,COMMENT
LOW…ge/gallery/ui/common/chat/ModelInitializationStatus.kt81 }COMMENT
LOW…e/gallery/ui/common/chat/MessageBodyPromptTemplates.kt121 }COMMENT
LOW…e/gallery/ui/common/chat/MessageBodyPromptTemplates.kt141// templates =COMMENT
LOW…i/edge/gallery/ui/common/chat/TextInputHistorySheet.kt201// @ComposableCOMMENT
LOW…oogle/ai/edge/gallery/ui/common/chat/MessageLatency.kt41COMMENT
LOW…google/ai/edge/gallery/ui/common/chat/MessageSender.kt201// fun MessageSenderPreview() {COMMENT
LOW…google/ai/edge/gallery/ui/common/chat/MessageSender.kt221// values = listOf(),COMMENT
LOW…google/ai/edge/gallery/ui/common/chat/MessageSender.kt241// iterationTotal = 200,COMMENT
LOW…edge/gallery/ui/common/chat/MessageBodyBenchmarkLlm.kt41 DataCard(label = stat.label, unit = stat.unit, value = message.statValues[stat.id])COMMENT
LOW…edge/gallery/ui/common/chat/MessageBodyBenchmarkLlm.kt61// running = false,COMMENT
LOW…e/ai/edge/gallery/ui/common/chat/MessageBodyWarning.kt61// fun MessageBodyWarningPreview() {COMMENT
LOW…/ai/edge/gallery/ui/common/chat/MessageActionButton.kt81// MessageActionButton(label = "run", icon = Icons.Default.PlayArrow, onClick = {})COMMENT
LOW…ogle/ai/edge/gallery/ui/common/chat/MessageBodyInfo.kt61// GalleryTheme {COMMENT
LOW…ge/gallery/ui/common/chat/MessageBodyClassification.kt101// message =COMMENT
LOW…ogle/ai/edge/gallery/ui/common/modelitem/StatusIcon.kt121// fun StatusIconPreview() {COMMENT
LOW…e/ai/edge/gallery/customtasks/common/CustomTaskData.kt61 val onNavUp: () -> Unit,COMMENT
LOW…in/java/com/google/ai/edge/gallery/data/ConfigValue.kt21 // @SerializableCOMMENT
LOW…in/java/com/google/ai/edge/gallery/data/ConfigValue.kt41// override fun serialize(encoder: Encoder, value: ConfigValue) {COMMENT
AI Response Leakage2 hits · 10 pts
SeverityFileLineSnippetContext
HIGH…id/src/app/src/main/assets/tinygarden/main-K5DSW5YL.js19`);return r>=0?n.slice(0,r):n}function xa(e,t){return e?t?`${e} ${t}`:e:t||""}var Tm=U({__forward_ref__:U});function hi(CODE
HIGH…id/src/app/src/main/assets/tinygarden/main-K5DSW5YL.js19`);return r>=0?n.slice(0,r):n}function xa(e,t){return e?t?`${e} ${t}`:e:t||""}var Tm=U({__forward_ref__:U});function hi(CODE
Fake / Example Data3 hits · 3 pts
SeverityFileLineSnippetContext
LOW…/edge/gallery/ui/modelmanager/ModelManagerViewModel.kt127private const val PLACEHOLDER_FILENAME = "placeholder"CODE
LOW…gallery/ui/common/modelitem/OptionalComponentsPanel.kt79 return File(model.getPath(context = context, fileName = "placeholder")).parentFileCODE
LOW…gallery/ui/common/modelitem/OptionalComponentsPanel.kt80 ?: File(model.getPath(context = context, fileName = "placeholder"))CODE
Self-Referential Comments1 hit · 3 pts
SeverityFileLineSnippetContext
MEDIUM.github/workflows/static.yml36 # Create the nested directory structureCOMMENT