AI Slop Code Risk Monitor

streamyfin/streamyfin

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

A modern Jellyfin client built with Expo

0.6 Low pattern signal View on GitHub

Open-Source Code Quality, Security and Technical Debt Review

This report summarizes scanner evidence for streamyfin/streamyfin, a TypeScript project with 5,326 GitHub stars. SynthScan examined 292,192 lines of code across 1606 source files, recording 144 pattern matches distributed across 10 syntactic categories. The legacy adjusted pattern signal is 0.6 (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.6
Adjusted Signal
0.6
Raw Pattern Score
100%
Time Factor
2026-10-30
Last Push
5.3K
Stars
TypeScript
Language
292.2K
Lines of Code
1.6K
Files
144
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 2.3/100 · LOW

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

Hallucinated Dependency & Supply Chain Risk 0.5/100 · LOW

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

Agent Over-Engineering Ratio 1.2/100 · LOW

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

PR Review Velocity Impact 3.1/100 · LOW

Which changes need focused human review? 144 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 2HIGH 2MEDIUM 6LOW 134

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 144 distinct pattern matches across 10 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.

Over-Commented Block73 hits · 73 pts
SeverityFileLineSnippetContext
LOWmetro.config.js1// Learn more https://docs.expo.io/guides/customizing-metroCOMMENT
LOWapp/+native-intent.ts1// Expo Router's hook for the links the system opens the app with. The logic isCOMMENT
LOWapp/(auth)/(tabs)/(libraries)/[libraryId].tsx521 // The policy is covered by utils/library/libraryTabs.test.ts, the counts byCOMMENT
LOWapp/(auth)/(tabs)/(home)/_layout.tsx21import { userAtom } from "@/providers/JellyfinProvider";COMMENT
LOWproviders/WebSocketProvider.tsx461 // session expiry (the auth interceptor handles it). What remains isCOMMENT
LOWproviders/JellyfinProvider.tsx201 // approves it with the token it already holds, so Seerr opens an ordinaryCOMMENT
LOWproviders/JellyfinProvider.tsx261 // the dead token stays in storage, so every reload re-fires authed calls →COMMENT
LOWproviders/NativePlayerProvider.tsx1101 });COMMENT
LOWproviders/PlaySettingsProvider.tsx121 [api, user, settings, playSettings],COMMENT
LOWutils/sentry.ts21// allows submitting events, so shipping it in the client bundle is fine.COMMENT
LOWutils/sentry.ts241 enableSwizzling: false,COMMENT
LOWutils/errors.ts61// - 523: the origin is unreachable (routing, DNS)COMMENT
LOWutils/errors.ts81export const isGatewayStatus = (status: number): boolean =>COMMENT
LOWutils/errors.ts381// space, a slash, a comment or a list separator. A dot or a colon after itCOMMENT
LOWutils/httpFailureGate.ts21// in search, by every screen that mounts the same request, and by each layerCOMMENT
LOWutils/atoms/settings.ts1081 const stillCurrent = () => {COMMENT
LOWutils/jellyfin/getDefaultPlaySettings.ts321 }COMMENT
LOWutils/tvDiscovery/payload.ts81COMMENT
LOWcomponents/settings/LocalNetworkSettings.tsx161 // `192.168.1.10` became the API base path on home Wi-Fi and crashed theCOMMENT
LOWcomponents/video-player/controls/SkipSegmentOverlay.tsx41COMMENT
LOW…s/video-player/controls/NextEpisodeCountDownButton.tsx61 // Advancing is one-way per appearance: without this, any re-render insideCOMMENT
LOWcomponents/video-player/controls/Controls.tsx481 // only shifts left when the icon is actually shown.COMMENT
LOWcomponents/video-player/controls/Controls.tsx501 // can't swap Skip Credits, the countdown and the prompt around under theCOMMENT
LOWhooks/usePushRegistration.ts41 // one goes out.COMMENT
LOWhooks/useAppLanguage.ts21 notifications: Notifications | null,COMMENT
LOWhooks/useMediaPreferences.ts241 // session-start concern, so it keys off the user's identity instead.COMMENT
LOW.github/workflows/release.yml1name: 🚀 Release (EAS build + submit)COMMENT
LOWmodules/mpv-player/ios/PlayerAudioSession.swift1import AVFoundationCOMMENT
LOWmodules/mpv-player/ios/PlayerEngine.swift121 name: UIApplication.didEnterBackgroundNotification, object: nil)COMMENT
LOWmodules/mpv-player/ios/PlayerEngine.swift341COMMENT
LOWmodules/mpv-player/ios/MPVLayerRenderer.swift161COMMENT
LOWmodules/mpv-player/ios/MPVLayerRenderer.swift341 // Moving this elsewhere causes tvOS to freeze when exiting the player.COMMENT
LOWmodules/mpv-player/ios/MPVLayerRenderer.swift361 #if os(tvOS)COMMENT
LOWmodules/mpv-player/ios/MPVLayerRenderer.swift381 //COMMENT
LOWmodules/mpv-player/ios/MPVLayerRenderer.swift441 /// Step 3 is the one that breaks on Apple platforms: CoreText answers with aCOMMENT
LOWmodules/mpv-player/ios/MPVLayerRenderer.swift601 // Clear wakeup callback first to stop event processingCOMMENT
LOWmodules/mpv-player/ios/MPVLayerRenderer.swift621 // this can be the layer's final reference. A CALayer that hasCOMMENT
LOWmodules/mpv-player/ios/MPVLayerRenderer.swift781 // MARK: - Property HelpersCOMMENT
LOWmodules/mpv-player/ios/MPVLayerRenderer.swift1221 COMMENT
LOW…ules/mpv-player/ios/NativePlayer/PlayerViewModel.swift21/// Bridges MPVPlayerEngine callbacks into SwiftUI state and dual-emits everyCOMMENT
LOW…ules/mpv-player/ios/NativePlayer/PlayerViewModel.swift161 /// Custom proxy auth headers for the thumbnails above (see RemoteImage).COMMENT
LOW…ules/mpv-player/ios/NativePlayer/PlayerViewModel.swift221 private(set) var sleepTimerEndDate: Date?COMMENT
LOW…ules/mpv-player/ios/NativePlayer/PlayerViewModel.swift241 /// stream) and a second onNextEpisodeRequested fires mid-swap.COMMENT
LOW…ayer/ios/NativePlayer/NativePlayerViewController.swift1import CombineCOMMENT
LOW…ayer/ios/NativePlayer/NativePlayerViewController.swift21 #if os(iOS)COMMENT
LOW…ayer/ios/NativePlayer/NativePlayerViewController.swift61COMMENT
LOW…ayer/ios/NativePlayer/NativePlayerViewController.swift121COMMENT
LOW…ayer/ios/NativePlayer/NativePlayerViewController.swift221 // two-finger pinch can be observed without entering the SwiftUI gestureCOMMENT
LOW…ayer/ios/NativePlayer/NativePlayerViewController.swift381 }COMMENT
LOW…ayer/ios/NativePlayer/Views/PlayerCenterControls.swift1#if os(iOS)COMMENT
LOW…ayer/ios/NativePlayer/Views/TV/TVChromeLayerView.swift1#if os(tvOS)COMMENT
LOW…ayer/ios/NativePlayer/Views/TV/TVChromeLayerView.swift141/// deliberately does not publish the ~30Hz clock (see PlaybackTimeModel).COMMENT
LOW…yer/ios/NativePlayer/Views/TV/TVFocusCoordinator.swift41/// what makes or breaks it:COMMENT
LOW…yer/ios/NativePlayer/Views/TV/TVFocusCoordinator.swift141 private static let establishGrace: TimeInterval = 0.05COMMENT
LOW…yer/ios/NativePlayer/Views/TV/TVFocusCoordinator.swift261 ///COMMENT
LOW…player/ios/NativePlayer/Views/TV/TVOverlayLayers.swift1#if os(tvOS)COMMENT
LOW…v-player/ios/NativePlayer/Views/TV/TVControlsRow.swift1#if os(tvOS)COMMENT
LOW…player/ios/NativePlayer/Views/TV/TVTrickplayCard.swift1#if os(tvOS)COMMENT
LOW…c/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt141 //COMMENT
LOW…c/main/java/expo/modules/mpvplayer/MPVLayerRenderer.kt281 // Hardware decoder codecs (shared)COMMENT
13 more matches not shown…
Hyper-Verbose Identifiers54 hits · 54 pts
SeverityFileLineSnippetContext
LOW…bs)/(home)/settings/appearance/hide-libraries/page.tsx16export default function AppearanceHideLibrariesPage() {CODE
LOW…p/(auth)/(tabs)/(home)/settings/notifications/page.tsx5export default function NotificationsSettingsPage() {CODE
LOWplugins/withTVOSTopShelf.ts32function getKeychainAccessGroupIdentifier(config: ExpoConfig): string {CODE
LOWplugins/withTVOSTopShelf.ts56function ensureKeychainAccessGroup(CODE
LOWproviders/AudioStorage/index.ts80function withCurrentContainerPaths(CODE
LOWproviders/Downloads/fileOperations.ts162export function deletePendingDownloadFiles(download: AbandonedDownload): void {CODE
LOWproviders/Downloads/fileOperations.ts219export function calculateTotalDownloadedSize(): number {CODE
LOWproviders/Downloads/utils.ts75export function liveActivityPosterFileName(item: BaseItemDto): string {CODE
LOWproviders/Downloads/liveActivity.ts120export async function buildDownloadActivityMetadata({CODE
LOWproviders/Downloads/liveActivity.ts152export function setDownloadLiveActivityEnabled(enabled: boolean): void {CODE
LOWproviders/Downloads/hooks/useDownloadReconciliation.ts104export function useDownloadReconciliation({CODE
LOWutils/background-tasks.ts11export async function registerBackgroundFetchAsync(): Promise<boolean> {CODE
LOWutils/background-tasks.ts44export async function unregisterBackgroundFetchAsync(): Promise<boolean> {CODE
LOWutils/background-tasks.ts58export async function unregisterBackgroundFetchAsyncSessions(): Promise<boolean> {CODE
LOWutils/background-tasks.ts74export async function registerBackgroundFetchAsyncSessions(): Promise<boolean> {CODE
LOWutils/seriesTrackMemory.ts63export function rememberSeriesTrackFromRow(options: {CODE
LOWutils/downloadSize.ts53export function estimateDownloadActivitySize(CODE
LOWutils/secureCredentials.ts185export async function getCredentialOrForgetAccount(CODE
LOWutils/secureCredentials.ts420export function updateServerCustomHeaders(CODE
LOWutils/secureCredentials.ts628export function makeServerHeadersReadableWhileLocked(): void {CODE
LOWutils/secureCredentials.ts831export async function migrateCurrentSessionToSecureStorage(CODE
LOWutils/atoms/downloadedSubtitles.ts136export function removeAllSubtitlesForItem(itemId: string): void {CODE
LOWutils/atoms/downloadedSubtitles.ts159export function getAllDownloadedSubtitles(): DownloadedSubtitle[] {CODE
LOWutils/jellyfin/userConfiguration.ts23export function buildUserConfigurationPayload(CODE
LOWutils/jellyfin/createApi.ts76export function createApiWithCustomHeaders(CODE
LOWutils/customHeaders/integrations.ts80export function updateIntegrationHeaderConfig(CODE
LOWutils/customHeaders/integrations.ts103export function getIntegrationHeaderConfig(CODE
LOWutils/customHeaders/integrations.ts126export function makeIntegrationHeadersReadableWhileLocked(): void {CODE
LOWutils/customHeaders/integrations.ts157export function resolveIntegrationHeaders(CODE
LOWutils/customHeaders/secureValues.ts59function secureValueKeyScopeMatches(CODE
LOWutils/customHeaders/secureValues.ts128export function resolveCustomHeaderValues(CODE
LOWutils/customHeaders/secureValues.ts148export function secureCustomHeaderMetadata(CODE
LOWutils/customHeaders/secureValues.ts201export function deleteSecureCustomHeaderValues(headers: CustomHeader[]): void {CODE
LOWutils/customHeaders/secureValues.ts228export function recreateLegacySecureValues(CODE
LOWutils/customHeaders/normalize.ts19function hasInvalidHeaderValueCharacters(value: string): boolean {CODE
LOWutils/customHeaders/resolve.ts102function getSavedServerHeadersForUrl(CODE
LOWutils/customHeaders/optionalHeaders.ts15export function sourceWithOptionalHeaders(CODE
LOWutils/nativePlayer/resolveFailedPresentation.ts21export function resolveFailedPresentation(input: {CODE
LOWutils/nativePlayer/syncPlay.ts86export async function dispatchNativeSyncPlayAction(CODE
LOWutils/query/networkAwareInvalidate.ts12export function invalidateQueriesWhenOnline(CODE
LOWutils/downloads/offline-series.ts16export function getDownloadedEpisodesForSeries(CODE
LOWutils/downloads/offline-series.ts30export function getDownloadedEpisodesForSeason(CODE
LOWutils/downloads/offline-series.ts43export function getDownloadedEpisodesBySeasonId(CODE
LOWutils/downloads/offline-series.ts57export function getDownloadedSeasonNumbers(CODE
LOWutils/downloads/offline-series.ts99export function buildOfflineSeriesFromEpisodes(CODE
LOWutils/directPlayer/sessionPosition.ts42export function resolveSessionPositionTicks(session: {CODE
LOWcomponents/tv/settings/TVCustomHeadersSection.tsx91function TVIntegrationHeaderEditor({CODE
LOWhooks/useRevalidatePlaybackProgressCache.ts8export function useInvalidatePlaybackProgressCache() {CODE
LOWhooks/useTVBackPress.ts19export function enableTVMenuKeyInterception() {CODE
LOWhooks/useTVBackPress.ts25export function disableTVMenuKeyInterception() {CODE
LOWhooks/useNetworkAwareQueryClient.ts22export function useNetworkAwareQueryClient(): NetworkAwareQueryClient {CODE
LOWhooks/useDismissKeyboardOnLeave.ts16export function useDismissKeyboardOnLeave() {CODE
LOWscripts/typecheck.ts76function parseErrorsAndCreateSummary(errorOutput: string): {CODE
LOWmodules/tv-user-profile/index.ts44export function isProfileSwitchingSupported(): boolean {CODE
Hallucination Indicators2 hits · 20 pts
SeverityFileLineSnippetContext
CRITICAL…s/mpvplayer/nativeplayer/ui/SyncPlayQueuePhoneSheet.kt416private fun androidx.compose.foundation.layout.RowScope.TransportButton(CODE
CRITICAL…ain/java/expo/modules/exoplayerplayer/ExoPlayerView.kt408 androidx.media3.exoplayer.audio.AudioCapabilities.getCapabilities(context)CODE
Excessive Try-Catch Wrapping5 hits · 10 pts
SeverityFileLineSnippetContext
MEDIUMdocs/ks-player/SwiftUIUsage.md81 print("Error: \(error)")CODE
MEDIUMdocs/ks-player/KSPlayerLayer.md282 print("Error occurred")CODE
MEDIUMdocs/ks-player/UIKitUsage.md149 print("Error occurred")CODE
MEDIUMmodules/mpv-player/ios/Logger.swift118 print("Error managing log file: \(error)")CODE
MEDIUMmodules/mpv-player/ios/Logger.swift141 print("Error truncating log file: \(error)")CODE
Structural Annotation Overuse4 hits · 6 pts
SeverityFileLineSnippetContext
LOWdocs/tv-modal-guide.md37### Step 1: Create the AtomCOMMENT
LOWdocs/tv-modal-guide.md54### Step 2: Create the HookCOMMENT
LOWdocs/tv-modal-guide.md76### Step 3: Create the Modal PageCOMMENT
LOWdocs/tv-modal-guide.md154### Step 4: Add Stack.Screen ConfigurationCOMMENT
Magic Placeholder Names1 hit · 5 pts
SeverityFileLineSnippetContext
HIGHdocs/ks-player/SubtitleSupport.md289let openSubSource = OpenSubtitleDataSouce(apiKey: "your-api-key")CODE
Empty Error Handlers1 hit · 5 pts
SeverityFileLineSnippetContext
HIGHe2e/syncplay/setup.py37except (OSError, ValueError):CODE
AI Slop Vocabulary1 hit · 3 pts
SeverityFileLineSnippetContext
MEDIUMutils/jellyfin/subtitleUtils.ts579 // 1) Exact identity by external filename — robust against hidden-embedded offset.COMMENT
Fake / Example Data2 hits · 2 pts
SeverityFileLineSnippetContext
LOWcomponents/search/LoadingSkeleton.tsx56 Lorem ipsumCODE
LOWmodules/tv-search/ios/TvSearchModule.swift10 Prop("placeholder") { (view: TvSearchView, value: String?) inCODE
Deep Nesting1 hit · 1 pts
SeverityFileLineSnippetContext
LOWe2e/syncplay/setup.py30CODE