AI Slop Code Risk Monitor

betaflight/betaflight-configurator

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

Cross platform configuration and management application for the Betaflight firmware

0.5 Low pattern signal View on GitHub

Open-Source Code Quality, Security and Technical Debt Review

This report summarizes scanner evidence for betaflight/betaflight-configurator, a TypeScript project with 3,345 GitHub stars. SynthScan examined 449,826 lines of code across 932 source files, recording 179 pattern matches distributed across 9 syntactic categories. The legacy adjusted pattern signal is 0.5 (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.5
Adjusted Signal
0.5
Raw Pattern Score
100%
Time Factor
2026-10-31
Last Push
3.3K
Stars
TypeScript
Language
449.8K
Lines of Code
932
Files
179
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.0/100 · LOW

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

Hallucinated Dependency & Supply Chain Risk 0.0/100 · LOW

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

Agent Over-Engineering Ratio 1.9/100 · LOW

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

PR Review Velocity Impact 2.4/100 · LOW

Which changes need focused human review? 179 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 21LOW 158

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 179 distinct pattern matches across 9 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 Identifiers113 hits · 124 pts
SeverityFileLineSnippetContext
LOWvite.config.js130function stripManifestFromSecondaryEntriesPlugin() {CODE
LOWtest/js/serial_backend.test.ts296function establishVirtualConnection() {CODE
LOWtest/js/osd_preview_limits.test.js14function buildArtificialHorizonPreview() {CODE
LOWtest/js/osd_preview_limits.test.js25function buildHorizonSidebarsPreview() {CODE
LOWtest/js/simplifiedTuning.test.ts33function enableFilterFeatureDetection() {CODE
LOWtest/blackbox-viewer/workspace_io.test.ts55function createExistingWorkspaceState() {CODE
LOW⚡src/composables/useTuningSliders.ts101export function readGyroFilterSliderPosition(): GyroFilterSliderPosition {CODE
LOW⚡src/composables/useTuningSliders.ts109export function readDTermFilterSliderPosition(): DTermFilterSliderPosition {CODE
LOWsrc/composables/useOsdPreview.ts166function normalizeSelectedPosition(position: number, totalSize: number): number {CODE
LOWsrc/composables/useOsdPreview.ts322export function clampStringPreviewPosition(CODE
LOWsrc/composables/useOsdPreview.ts347export function clampStringArrayPreviewPosition(CODE
LOWsrc/composables/useOsdPreview.ts379export function clampObjectArrayPreviewPosition(CODE
LOWsrc/composables/useOsdPreview.ts415export function clampArrayPreviewPosition(CODE
LOWsrc/composables/useFlightPlan.ts162function validatePositionalWaypoint(waypointData: WaypointInput): boolean {CODE
LOWsrc/composables/useMspCliSession.ts215export function findCliSettingAllowedValues(lines: string[] | null | undefined): string[] | null {CODE
LOWsrc/composables/useOsdRuler.ts186function getHorizontalAxisGeometry(axis: HorizontalAxis, params: RulerLayout, tick: number) {CODE
LOWsrc/composables/usePreflight.ts860function refreshIpGeolocationConsent(): boolean {CODE
LOWsrc/composables/usePreflight.ts913function updateMagneticDeclination() {CODE
LOWsrc/composables/useDataflashErase.ts42export function getDataflashEraseTimeoutMs(totalSize: number): number {CODE
LOWsrc/composables/useVtx.ts136function buildPowerOptionsFromTable(powerLevelList: VtxTablePowerLevel[], count: number) {CODE
LOWsrc/composables/useVtx.ts156function buildPowerOptionsFromRange(range: PowerRange) {CODE
LOWsrc/composables/ports/softSerial.ts37export function unreportedSoftSerialIdentifiers(CODE
LOWsrc/composables/ports/portNames.ts113export function findPortIdentifierByCliName(CODE
LOWsrc/js/tab_switch.ts162export function selectDefaultTabWhenConnected(): void {CODE
LOWsrc/js/main.ts196async function openDeleteAccountFromLink() {CODE
LOWsrc/js/serial_backend.ts699function finishUnexpectedDisconnect() {CODE
LOWsrc/js/serial_backend.ts715function dropStalledRebootConnection() {CODE
LOWsrc/js/serial_backend.ts853function showConnectionFailedDialog(text: string, title = i18n.getMessage("connectionFailedTitle")) {CODE
LOWsrc/js/serial_backend.ts869function showVersionMismatchAndCli(message: string) {CODE
LOWsrc/js/serial_backend.ts1103async function processBuildConfiguration() {CODE
LOWsrc/js/serial_backend.ts1514function clearLiveDataRefreshTimer() {CODE
LOWsrc/js/serial_backend.ts1521function startLiveDataRefreshTimer() {CODE
LOWsrc/js/peripherals.ts38function adjustBoxNameIfPeripheralWithModeID(modeId: number, defaultName: string): string {CODE
LOWsrc/js/simplifiedTuning.ts102function sliderFactorsFromTuningSliders(sliders: TuningSliders): SliderFactors {CODE
LOWsrc/js/simplifiedTuning.ts148export function calculateSimplifiedPidValues(factors: SliderFactors): AxisPidValues[] {CODE
LOWsrc/js/simplifiedTuning.ts164export function calculateSimplifiedGyroFilterValues(multiplier: number): GyroFilterValues {CODE
LOWsrc/js/simplifiedTuning.ts190export function calculateSimplifiedDtermFilterValues(multiplier: number): DtermFilterValues {CODE
LOW⚡src/js/simplifiedTuning.ts229export function applySimplifiedGyroFilters(sliders: TuningSliders = useFlightControllerStore().tuningSliders): void {CODE
LOW⚡src/js/simplifiedTuning.ts237export function applySimplifiedDtermFilters(sliders: TuningSliders = useFlightControllerStore().tuningSliders): void {CODE
LOW⚡src/js/simplifiedTuning.ts245export function validateVirtualSimplifiedTuning(): void {CODE
LOWsrc/js/blackbox/spectral_analysis.ts581function findMaxAchievablePhaseMargin(tf: TransferFunction, openLoop: OpenLoopResponse) {CODE
LOWsrc/js/utils/magModelExport.ts357export function buildCharacterizationModel({CODE
LOWsrc/js/utils/magCharacterizationCompute.ts102export function isFirmwareCustomMagAlignCapable(versionString: string | null | undefined): boolean {CODE
LOWsrc/js/utils/deleteAccountLink.ts32export function requestDeleteAccountFocus(): void {CODE
LOWsrc/js/utils/deleteAccountLink.ts39export function consumeDeleteAccountFocus(): boolean {CODE
LOWsrc/js/utils/debugModes.ts231export function debugContextFromSysConfig(sysConfig?: DebugSysConfig | null): DebugContext {CODE
LOWsrc/js/utils/debugModes.ts2266export function decodeDebugFieldToFriendly(CODE
LOWsrc/js/utils/sphereFit.ts396export function computeDirectionalCoverage(points: Point3[], center: Point3, minHits = 3): DirectionalCoverage {CODE
LOW⚡src/stores/osd.ts324 function setSelectedPreviewProfile(profile: number) {CODE
LOW⚡src/stores/osd.ts329 function updateDisplayItemVisibility(itemIndex: number, profileIndex: number, visible: boolean) {CODE
LOW⚡src/stores/osd.ts335 function refreshDisplayItemPreview(displayItem: OsdDisplayItem) {CODE
LOWsrc/stores/osd.ts355 function syncStoreFromDecodedOsdData() {CODE
LOWsrc/stores/presets_helpers.ts114export function createSecondaryOfficialSource(): PresetSource {CODE
LOWsrc/stores/presets_helpers.ts147export function sanitizeActiveSourceIndexes(storedIndexes: unknown, sourceCount: number): number[] {CODE
LOWsrc/stores/presets_helpers.ts183export function getDefaultFirmwareSelections(CODE
LOWsrc/stores/presets_helpers.ts280export function applySelectedOptionIdsToOptions(CODE
LOWsrc/stores/presets_helpers.ts314export function presetSearchPriorityComparer(entryA: PresetSortEntry, entryB: PresetSortEntry): number {CODE
LOW⚡src/stores/presets_helpers.ts335export function isPresetFitSearchStatuses(preset: Preset, searchParams: PresetSearchParams): boolean {CODE
LOW⚡src/stores/presets_helpers.ts340export function isPresetFitSearchCategories(preset: Preset, searchParams: PresetSearchParams): boolean {CODE
LOW⚡src/stores/presets_helpers.ts348export function isPresetFitSearchKeywords(preset: Preset, searchParams: PresetSearchParams): boolean {CODE
53 more matches not shown…
Decorative Section Separators15 hits · 46 pts
SeverityFileLineSnippetContext
MEDIUMtest/js/magModelExport.test.ts18// ── Synthetic inputs ────────────────────────────────────────────────────────COMMENT
MEDIUMtest/js/magModelExport.test.ts73// ── Tests ───────────────────────────────────────────────────────────────────COMMENT
MEDIUMtest/js/magCalibration.invariance.test.ts146// ── Tests ───────────────────────────────────────────────────────────────────COMMENT
MEDIUMsrc/composables/useTuningSliders.ts34// ── Constants ────────────────────────────────────────────────────────────────COMMENT
MEDIUMsrc/composables/useTuningSliders.ts43// ── Types ────────────────────────────────────────────────────────────────────COMMENT
MEDIUMsrc/composables/useTuningSliders.ts68// ── Pure utilities ───────────────────────────────────────────────────────────COMMENT
MEDIUMsrc/composables/useTuningSliders.ts84// ── Initialization helpers (read fcStore.tuningSliders → plain objects) ──────────COMMENT
MEDIUM⚡src/composables/useTuningSliders.ts117// ── MSP actions ──────────────────────────────────────────────────────────────COMMENT
MEDIUMsrc/composables/usePreflight.ts414// ── Module-scoped singleton state ──────────────────────────────────────────────COMMENT
MEDIUMsrc/composables/usePreflight.ts1030// ── Public API (singleton) ─────────────────────────────────────────────────────COMMENT
MEDIUMsrc/js/utils/ellipsoidFit.ts223// ── Internal helpers ──────────────────────────────────────────────────────────COMMENT
MEDIUMsrc/js/utils/magCharacterizationCompute.ts90// ── Firmware version gate ───────────────────────────────────────────────────COMMENT
MEDIUMsrc/js/utils/magCharacterizationCompute.ts255// ── Quality assessment ──────────────────────────────────────────────────────COMMENT
MEDIUMsrc/components/tabs/PreflightTab.vue1641 // ── NOTAM logic ──────────────────────────────────────────────────────────COMMENT
MEDIUMsrc/components/tabs/PreflightTab.vue1752 // ── End NOTAM logic ───────────────────────────────────────────────────────COMMENT
Over-Commented Block40 hits · 40 pts
SeverityFileLineSnippetContext
LOWcrowdin.yml1# ID used by the upload action to CrowdinCOMMENT
LOWtest/js/webbluetooth.test.ts21COMMENT
LOWtest/js/tauri_serial.test.js1import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";COMMENT
LOWtest/js/boardAlignment.test.ts41// - Drone nose faces AWAY from the user during calibration (+X = forward).COMMENT
LOWtest/js/webserial.test.js1import { beforeEach, afterEach, describe, expect, it, vi } from "vitest";COMMENT
LOWtest/js/device_handler.test.ts21COMMENT
LOWtest/js/usbdfu_h7_erase.test.js1import { beforeEach, describe, expect, it, vi } from "vitest";COMMENT
LOWtest/js/serial_backend.test.ts801COMMENT
LOWtest/js/usbdfu_open_failure.test.js1import { beforeEach, describe, expect, it, vi } from "vitest";COMMENT
LOWtest/js/usbdfu_stm32c5.test.js1import { beforeEach, describe, expect, it, vi } from "vitest";COMMENT
LOWtest/js/serial_send_callback.test.ts21COMMENT
LOWtest/js/utils/debugFieldAnnotations.test.ts101COMMENT
LOW.github/workflows/tauri-release-assets.yml1name: Release platform assetsCOMMENT
LOW.github/workflows/tauri-nightly.yml1name: Nightly downloadsCOMMENT
LOW.github/workflows/android-play-release.yml1name: Android Play releaseCOMMENT
LOWsrc-tauri/Cargo.toml21serde_json = "1.0"COMMENT
LOWsrc-tauri/src/tcp.rs1//! Raw TCP client commands for the configurator.COMMENT
LOWsrc-tauri/src/mdns/mod.rs1//! mDNS discovery of Betaflight bridges (github.com/betaflight/bridge).COMMENT
LOWsrc/composables/adjustments/useAdjustmentsData.ts41// configurator's adjustmentsFunctionN locale labels reflect the dispatchCOMMENT
LOWsrc/js/serial_backend.ts81// Re-entrancy guard for the live-data poller. update_live_status is async and awaits aCOMMENT
LOWsrc/js/serial_backend.ts101// from an unexpected one (unplug / FC reboot / BLE drop) so we don't tear downCOMMENT
LOWsrc/js/serial_backend.ts221 const connectionStore = useConnectionStore();COMMENT
LOWsrc/js/serial_backend.ts421COMMENT
LOWsrc/js/serial_backend.ts1601}COMMENT
LOWsrc/js/serial_backend.ts1641 rebootReconnectTimerId = false;COMMENT
LOWsrc/js/blackbox/spectral_analysis.ts761 return 1 - lowFreqErrorDb * 0.05;COMMENT
LOWsrc/js/blackbox/spectral_analysis.ts781 // fragile by a measure this file already computes.COMMENT
LOWsrc/js/blackbox/spectral_analysis.ts801 const admissibleMax = clamp(requestedGain, GAIN_SCALE_MIN, GAIN_SCALE_MAX);COMMENT
LOWsrc/js/blackbox/spectral_analysis.ts821 // rather than implied. Judged against the admissible ceiling with aCOMMENT
LOWsrc/js/blackbox/spectral_analysis.ts841 // per-axis, and yaw conventionally runs no D at all, so a per-axis DCOMMENT
LOWsrc/js/blackbox/spectral_analysis.ts861 // instability/flyaway on arm. So this may only ever tighten filtering.COMMENT
LOWsrc/js/utils/connectDeeplink.ts21COMMENT
LOWsrc/js/protocols/usbdfu.ts521 getChipInfo(_interface: number, callback: (chipInfo: ChipInfo, resultCode: number) => void): void {COMMENT
LOWsrc/js/protocols/usbdfu.ts561 // "@Option Bytes /0x1FFF7800/01*048 e/0x1FFFF800/01*048 e"COMMENT
LOWsrc/js/protocols/usbdfu.ts741 }COMMENT
LOW…c/components/dialogs/mag-calibration/MagSphereView.vue521 // 1. set(x,-y,-z,w) is the conjugation p·q·p* (p = _BASE_180_X = Rx180)COMMENT
LOWsrc/blackbox-viewer/imu.ts41 PITCH = 1,COMMENT
LOWsrc/blackbox-viewer/flightlog_parser.ts621 //Predict that this field is the same as the average of the last two history items:COMMENT
LOWsrc/blackbox-viewer/leaflet-global.ts21COMMENT
LOWsrc/blackbox-viewer/flight3d/fcAttitude.ts21COMMENT
AI Slop Vocabulary3 hits · 8 pts
SeverityFileLineSnippetContext
MEDIUMpackage-lock.json14870 "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz",CODE
MEDIUMsrc/js/utils/AutoBackup.ts84// More robust prompt detection with multiple patternsCOMMENT
MEDIUMsrc/js/utils/AutoBackup.ts291 // Process and save the output - more robust parsingCOMMENT
Modern AI Meta-Vocabulary2 hits · 5 pts
SeverityFileLineSnippetContext
MEDIUMAGENTS.md8Standards for AI-assisted contributions to Betaflight Configurator. Adapted from the [awesome-copilot Vue 3 instructionsCODE
MEDIUMAGENTS.md17## Architecture guardrailsCOMMENT
Fake / Example Data3 hits · 3 pts
SeverityFileLineSnippetContext
LOWsrc/js/localization.ts65type LocalizedProperty = "innerHTML" | "title" | "value" | "placeholder";CODE
LOWsrc/js/localization.ts320 { attr: "i18n_placeholder", prop: "placeholder" },CODE
LOWsrc/components/user-session/UserSession.stories.ts86 args: { isLoggedIn: true, userEmail: "user@example.com", userName: "Sample User" },CODE
Slop Phrases1 hit · 2 pts
SeverityFileLineSnippetContext
MEDIUMlocales/en/messages.json6996 "message": "Here you can configure the values for your Video Transmitter (VTX). You can view and change the tranCODE
Verbosity Indicators1 hit · 2 pts
SeverityFileLineSnippetContext
LOW…c/components/dialogs/mag-calibration/MagSphereView.vue552 // Step 2: cancels the conjugation's p* → net Rx180·q. Dots and live-magCOMMENT
Structural Annotation Overuse1 hit · 2 pts
SeverityFileLineSnippetContext
LOW…c/components/dialogs/mag-calibration/MagSphereView.vue552 // Step 2: cancels the conjugation's p* → net Rx180·q. Dots and live-magCOMMENT