{"version": "2.1.0", "$schema": "https://json.schemastore.org/sarif-2.1.0.json", "runs": [{"tool": {"driver": {"name": "Repobility", "informationUri": "https://repobility.com", "rules": [{"id": "scanner-5a9777fb6ff32d51", "name": "Possibly dead Python function: fetch_case", "shortDescription": {"text": "Possibly dead Python function: fetch_case"}, "fullDescription": {"text": "No callers detected by AST scan in this repo. Could be exported for external callers or a framework handler."}, "properties": {"scanner": "scanner-primary", "layer": "software", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f41667c957c40a59", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/ChaptersMenu.tsx:137", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/ChaptersMenu.tsx:137"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-7a2209a5bce53108", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/QualityMenu.tsx:146", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/QualityMenu.tsx:146"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-8be544909ee3769c", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/AudioTrackMenu.tsx:167", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/AudioTrackMenu.tsx:167"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-91712b20ebdc90ad", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/PlayingNextScreen.tsx:423", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/PlayingNextScreen.tsx:423"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-fa6be24d5f0d9605", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/PlaybackInfoOverlay.tsx:91", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/PlaybackInfoOverlay.tsx:91"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-59339bb99a6d8de8", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/SubtitleSearchModal.tsx:345", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/SubtitleSearchModal.tsx:345"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-54b1d8d4ea10f0f9", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/SeekBar.tsx:320", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/SeekBar.tsx:320"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-140629a15fd82e28", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/NowListeningHero.tsx:186", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/NowListeningHero.tsx:186"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4c2322e72af2ed0d", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/RecommendationGrid.tsx:33", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/RecommendationGrid.tsx:33"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f241376f8ea1b7b6", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/SideNav.tsx:75", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/SideNav.tsx:75"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-9b729fb7bf0f038d", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/AppSidebar.tsx:460", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/AppSidebar.tsx:460"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-642d0fb320ad5154", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ContinueWatchingCard.tsx:288", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ContinueWatchingCard.tsx:288"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b4c03bf9f823f794", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/SectionItemCard.tsx:101", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/SectionItemCard.tsx:101"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-bf2afb24b0a69935", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/GlobalSearch.tsx:93", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/GlobalSearch.tsx:93"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f30010ed00481f64", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/WatchTonightCard.tsx:152", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/WatchTonightCard.tsx:152"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-172474b82c949eac", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/LibraryMultiSelect.tsx:94", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/LibraryMultiSelect.tsx:94"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-dd883a2012768f45", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/AddToCollectionDialog.tsx:160", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/AddToCollectionDialog.tsx:160"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-0074eaa85937da4c", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ImpersonationBanner.tsx:45", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ImpersonationBanner.tsx:45"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1d0b6d6e5fa54fce", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CrewList.tsx:47", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CrewList.tsx:47"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2e6b793b8fd616c3", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CastCarousel.tsx:106", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CastCarousel.tsx:106"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-cf33980f8167ab94", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ItemCard.tsx:245", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ItemCard.tsx:245"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-c9ff5aa192bbb20c", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/RequestToAddSection.tsx:129", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/RequestToAddSection.tsx:129"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-691eeca246667471", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionSearchableSelect.tsx:72", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionSearchableSelect.tsx:72"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-3fbc8524c0c0f2dd", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/LibraryHeader.tsx:68", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/LibraryHeader.tsx:68"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4a87cfd797151091", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ThemeSwitcher.tsx:43", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ThemeSwitcher.tsx:43"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-442e54da720b13b3", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/RequestPosterCard.tsx:207", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/RequestPosterCard.tsx:207"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-06689a5dbb827033", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/EpisodeRow.tsx:71", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/EpisodeRow.tsx:71"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-82292cda3e27daa7", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/MatchItemDialog.tsx:217", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/MatchItemDialog.tsx:217"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-dcf2f62481c3987b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/FolderBrowser.tsx:268", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/FolderBrowser.tsx:268"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b989d56f8883287b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ServerActivity.tsx:305", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ServerActivity.tsx:305"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-99fb352c0f43c701", "name": "\"active\" state uses light bg in a dark theme \u2014 web/src/components/settings/SubtitleAppearancePanelView.tsx:297", "shortDescription": {"text": "\"active\" state uses light bg in a dark theme \u2014 web/src/components/settings/SubtitleAppearancePanelView.tsx:297"}, "fullDescription": {"text": "A ternary like `active ? 'bg-white' : '...'` (or bg-gray-100/200) on a dark theme produces jarring white pills. Use a dark-emphasized active state instead \u2014 border + ring or slightly brighter dark bg. Example: `active ? 'bg-gray-800 border-gray-500 ring-1 ring-blue-500/30' : '\u2026'`.\n\nWhy: P-E in CHECKLIST.md \u2014 light bg in a dark theme is a class of regression.\nRule id: fq.active-light-bg"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8fea595f84a2a07d", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/audiobooks/AudiobookGroupsView.tsx:200", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/audiobooks/AudiobookGroupsView.tsx:200"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b9bc90f51180a9f6", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionTemplateGallery/MDBListBrowser.tsx:86", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionTemplateGallery/MDBListBrowser.tsx:86"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-aebaaec1b01091da", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionTemplateGallery/CollectionTemplateCard", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionTemplateGallery/CollectionTemplateCard.tsx:45"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-19586d1d0ff4d028", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionTemplateGallery/TemplatePosterField.ts", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionTemplateGallery/TemplatePosterField.tsx:58"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-15b55aadd47a4b14", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ui/facet-search-select.tsx:124", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ui/facet-search-select.tsx:124"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-23d1bc050923e973", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ui/person-search-select.tsx:89", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ui/person-search-select.tsx:89"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-fbf09f75a9885951", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ui/searchable-select.tsx:85", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ui/searchable-select.tsx:85"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-411f0507f57595db", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/admin/deviceOverrides.tsx:612", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/admin/deviceOverrides.tsx:612"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-88a7f9b32733b052", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/admin/libraries/LibraryEditorDialog.tsx:132", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/admin/libraries/LibraryEditorDialog.tsx:132"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-8594bfc658e6fdb3", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/ManualCollectionItemsEditor.tsx:111", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/ManualCollectionItemsEditor.tsx:111"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b1e7bab1dc20868f", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/CollectionPreviewPane.tsx:51", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/CollectionPreviewPane.tsx:51"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-acd1f38712916430", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/CollectionPosterCard.tsx:61", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/CollectionPosterCard.tsx:61"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a322d2657956fa2b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/admin/CollectionRow.tsx:89", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/admin/CollectionRow.tsx:89"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-c07009f8f5dcbd4d", "name": "Icon-only button without accessible name \u2014 web/src/components/RecipeGallery/RecipeGalleryModal.tsx:83", "shortDescription": {"text": "Icon-only button without accessible name \u2014 web/src/components/RecipeGallery/RecipeGalleryModal.tsx:83"}, "fullDescription": {"text": "A `<button>` whose only child is a single glyph or symbol needs `title=` or `aria-label=` so screen readers (and tooltips on hover) work.\n\nWhy: P3 in CHECKLIST.md \u2014 icon-only buttons skipped a title.\nRule id: fq.button.no-label"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c689b8eb4f50a595", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/FilterEasyMode/PreviewBox.tsx:45", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/FilterEasyMode/PreviewBox.tsx:45"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4625a2b1baf03122", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/profiles/HouseholdStreamsPanel.tsx:77", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/profiles/HouseholdStreamsPanel.tsx:77"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f0087e2c8e3a89aa", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/calendar/CalendarEventCard.tsx:85", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/calendar/CalendarEventCard.tsx:85"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-796352672b7715a2", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/calendar/WeekNavigator.tsx:48", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/calendar/WeekNavigator.tsx:48"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-cc2bc75153b2cc9d", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminHistoryImport.tsx:724", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminHistoryImport.tsx:724"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e134fc2c05d6f20b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminMarkerHistory.tsx:115", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminMarkerHistory.tsx:115"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4d094459f4e9427a", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/WatchTogetherRoomPage.tsx:127", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/WatchTogetherRoomPage.tsx:127"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f93f4757411bf50b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/RequestBrowse.tsx:103", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/RequestBrowse.tsx:103"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f315a572e5ad3012", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminDashboard.tsx:528", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminDashboard.tsx:528"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-802fbe6a2c078a1f", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminCollections.tsx:552", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminCollections.tsx:552"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-6de89454cbf53819", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/EbookReader.tsx:538", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/EbookReader.tsx:538"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-044b71dedeb26ea5", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/WatchTogetherSuggestionPanel.tsx:103", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/WatchTogetherSuggestionPanel.tsx:103"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4926defc43a7e63a", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminDevices.tsx:1004", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminDevices.tsx:1004"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-85aaf0967125af46", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminTaskDetail.tsx:151", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminTaskDetail.tsx:151"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-bf130d4315a572b8", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminPlugins.tsx:579", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminPlugins.tsx:579"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-04635337d8f0c523", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminLibraries.tsx:816", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminLibraries.tsx:816"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4700f8d997a0da73", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ImportedCollectionEditor.tsx:748", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ImportedCollectionEditor.tsx:748"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-529a29f0cf6adc8f", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminActivity.tsx:580", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminActivity.tsx:580"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-66c8bb602533e152", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/Notifications.tsx:160", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/Notifications.tsx:160"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-30469f2a5de95ef9", "name": "TODO/FIXME marker in shipping code \u2014 web/src/pages/ProfileCustomizeHome.tsx:248", "shortDescription": {"text": "TODO/FIXME marker in shipping code \u2014 web/src/pages/ProfileCustomizeHome.tsx:248"}, "fullDescription": {"text": "Track in /reviews or /issues, not as a code comment that rots.\n\nWhy: Drift control \u2014 shouldn't be the same as Quality TODO scanner.\nRule id: fq.todo-marker"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-f6d8962b8c291b65", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/ProfilesSettings.tsx:145", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/ProfilesSettings.tsx:145"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-5555e3943fe3da3d", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/LibrarySettings.tsx:269", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/LibrarySettings.tsx:269"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d6b68c45233bc28b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/WatchProvidersSettings.tsx:131", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/WatchProvidersSettings.tsx:131"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-61fc25599803519c", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/WebhookSyncSettings.tsx:971", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/WebhookSyncSettings.tsx:971"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4299219c7ee4dd66", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/NotificationsSettings.tsx:647", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/NotificationsSettings.tsx:647"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-5ee3f58cf4200c2d", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/NarratorPicker.tsx:67", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/NarratorPicker.tsx:67"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-da6bf42ae4443e2e", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/ChaptersSection.tsx:149", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/ChaptersSection.tsx:149"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d9dfd65466ee2595", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/RelatedRail.tsx:53", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/RelatedRail.tsx:53"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-fa832a3b96e9dc53", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/NarratorCard.tsx:23", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/NarratorCard.tsx:23"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-0bbf99008b779b8d", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/setup-wizard/steps/ServerStorageStep.tsx:469", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/setup-wizard/steps/ServerStorageStep.tsx:469"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-37872131f8784053", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/admin/autoscan/ConnectionsPanel.tsx:302", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/admin/autoscan/ConnectionsPanel.tsx:302"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-b7861fbcb65329df", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/admin/autoscan/SourcesPanel.tsx:637", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/admin/autoscan/SourcesPanel.tsx:637"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-65d81c0d7b8ae9a6", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/SeasonCarousel.tsx:101", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/SeasonCarousel.tsx:101"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-cb7b21ca8b3b57d0", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/SubtitlesPopover.tsx:236", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/SubtitlesPopover.tsx:236"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-548c6daa9c3a80ce", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/AudioTracksPopover.tsx:100", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/AudioTracksPopover.tsx:100"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-cfb04d87c388ff42", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/SeasonEpisodeGrid.tsx:107", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/SeasonEpisodeGrid.tsx:107"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-3dcb8ab62672757b", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/VersionDropdown.tsx:70", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/VersionDropdown.tsx:70"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-4472a929efd973a5", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/SubtitleSearchDialog.tsx:233", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/SubtitleSearchDialog.tsx:233"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-c8dbeaf4a3e81247", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/VersionFlyout.tsx:79", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/VersionFlyout.tsx:79"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-6273a059bf876054", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/EpisodeCarousel.tsx:162", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/EpisodeCarousel.tsx:162"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-63d5fb0cae91f8a5", "name": "`truncate` class without `title=` for hover reveal \u2014 web/src/playback/WatchPlaybackChrome.tsx:927", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/playback/WatchPlaybackChrome.tsx:927"}, "fullDescription": {"text": "A truncated value should reveal the full text on hover. Pass the full string via `title={...}` so the user can read it.\n\nWhy: P2 in CHECKLIST.md \u2014 truncate without hover-reveal.\nRule id: fq.truncate.no-title"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d63da3583b14afc0", "name": "Dockerfile runs as root: Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: Dockerfile"}, "fullDescription": {"text": "No non-root USER set. Containers running as root expand the blast radius of any vulnerability inside the image."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-93e02e0d67c8f3e8", "name": "Docker base image is tag-pinned but not digest-pinned: node:22-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: node:22-slim"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-34d41f64da56cd8b", "name": "Docker base image is tag-pinned but not digest-pinned: golang:1.26", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: golang:1.26"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-84019dfd8d98a34d", "name": "Docker base image is tag-pinned but not digest-pinned: debian:bookworm-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: debian:bookworm-slim"}, "fullDescription": {"text": "Container tags can be retagged upstream. Pin production base images to a reviewed digest (`image@sha256:...`) when reproducibility and supply-chain integrity matter."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-aa5acaa49eb8315b", "name": "Containers defined but no K8s/orchestration manifest found", "shortDescription": {"text": "Containers defined but no K8s/orchestration manifest found"}, "fullDescription": {"text": "Repo has Dockerfiles/compose but no Kubernetes/Nomad manifests. If the target deployment is K8s, the manifests may live in a separate ops repo."}, "properties": {"scanner": "scanner-primary", "layer": "hardware", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6993af2e694a7917", "name": "Possible secret in internal/mail/mail.go", "shortDescription": {"text": "Possible secret in internal/mail/mail.go"}, "fullDescription": {"text": "Detected pattern matching password_literal. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-779d5ec2e07a8e00", "name": "Insecure pattern 'cors_wildcard' in internal/api/handlers/stream.go:353", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in internal/api/handlers/stream.go:353"}, "fullDescription": {"text": "Found a known-risky pattern (cors_wildcard). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-942433c3a7c461e1", "name": "Possible secret in internal/subtitles/opensubtitles/opensubtitles.go", "shortDescription": {"text": "Possible secret in internal/subtitles/opensubtitles/opensubtitles.go"}, "fullDescription": {"text": "Detected pattern matching generic_api_key. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-f38d02255ac06826", "name": "Possible secret in internal/metadata/tmdb/client.go", "shortDescription": {"text": "Possible secret in internal/metadata/tmdb/client.go"}, "fullDescription": {"text": "Detected pattern matching generic_api_key. Rotate the credential and move to a secret manager."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "critical", "confidence": 1.0}}, {"id": "scanner-7f0f9976570faa6d", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/checkout@v5 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-68a2b8f5c8cd6b53", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-de53ac274e5b4ecf", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/checkout@v4 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-37716d9c0a33ad5c", "name": "GitHub Actions workflow grants broad write permissions", "shortDescription": {"text": "GitHub Actions workflow grants broad write permissions"}, "fullDescription": {"text": "CI tokens with write permissions increase blast radius when an action, dependency, or PR workflow is compromised. Prefer job-level least-privilege permissions."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9ae56bc4b9d36417", "name": "GitHub Action is tag-pinned rather than SHA-pinned", "shortDescription": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "fullDescription": {"text": "actions/github-script@v7 can move without a code change in this repo. Pin third-party actions to a reviewed 40-character commit SHA."}, "properties": {"scanner": "scanner-primary", "layer": "cicd", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9a9f882b748428d5", "name": "Very large file: internal/recommendations/repo.go (1946 lines)", "shortDescription": {"text": "Very large file: internal/recommendations/repo.go (1946 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2bb504716120100a", "name": "Very large file: internal/requests/service_test.go (2697 lines)", "shortDescription": {"text": "Very large file: internal/requests/service_test.go (2697 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-34bbc2d65a89fd1a", "name": "Very large file: internal/requests/service.go (1833 lines)", "shortDescription": {"text": "Very large file: internal/requests/service.go (1833 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-557e3aa6374233ec", "name": "Very large file: internal/api/router.go (2916 lines)", "shortDescription": {"text": "Very large file: internal/api/router.go (2916 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-502171769c6181e1", "name": "Very large file: internal/api/handlers/admin.go (2164 lines)", "shortDescription": {"text": "Very large file: internal/api/handlers/admin.go (2164 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e95321e5e49a8a13", "name": "Very large file: internal/api/handlers/playback_test.go (1505 lines)", "shortDescription": {"text": "Very large file: internal/api/handlers/playback_test.go (1505 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-46a3b96af2302b80", "name": "Very large file: internal/api/handlers/playback.go (2648 lines)", "shortDescription": {"text": "Very large file: internal/api/handlers/playback.go (2648 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-172908bf49648220", "name": "Very large file: internal/api/handlers/items.go (1815 lines)", "shortDescription": {"text": "Very large file: internal/api/handlers/items.go (1815 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a64eb7145acf51a5", "name": "Very large file: internal/api/handlers/sections.go (1566 lines)", "shortDescription": {"text": "Very large file: internal/api/handlers/sections.go (1566 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-740ade55288048bd", "name": "Very large file: internal/api/handlers/library_collections.go (3722 lines)", "shortDescription": {"text": "Very large file: internal/api/handlers/library_collections.go (3722 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a3a93c19fc4180cf", "name": "Very large file: internal/api/handlers/libraries.go (2561 lines)", "shortDescription": {"text": "Very large file: internal/api/handlers/libraries.go (2561 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-4516077f41094629", "name": "Very large file: internal/api/handlers/plugins.go (1619 lines)", "shortDescription": {"text": "Very large file: internal/api/handlers/plugins.go (1619 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d3507221982647f9", "name": "Very large file: internal/jellycompat/handlers_items.go (2526 lines)", "shortDescription": {"text": "Very large file: internal/jellycompat/handlers_items.go (2526 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-89a14f5296ec6291", "name": "Very large file: internal/jellycompat/streams.go (1441 lines)", "shortDescription": {"text": "Very large file: internal/jellycompat/streams.go (1441 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9bfd21396f01b022", "name": "Very large file: internal/catalog/catalog_resolver.go (2338 lines)", "shortDescription": {"text": "Very large file: internal/catalog/catalog_resolver.go (2338 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b32cd2e7db5b2711", "name": "Very large file: internal/catalog/query_builder.go (1760 lines)", "shortDescription": {"text": "Very large file: internal/catalog/query_builder.go (1760 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f165a60bbbede717", "name": "Very large file: internal/catalog/item_repo.go (1641 lines)", "shortDescription": {"text": "Very large file: internal/catalog/item_repo.go (1641 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-46a05b5030effd6e", "name": "Very large file: internal/catalog/detail.go (2795 lines)", "shortDescription": {"text": "Very large file: internal/catalog/detail.go (2795 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-086adbdb0c4eb5f6", "name": "Very large file: internal/collections/templates/builtin.go (1883 lines)", "shortDescription": {"text": "Very large file: internal/collections/templates/builtin.go (1883 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d1938a3fd542c1ea", "name": "Very large file: internal/sections/fetcher.go (3112 lines)", "shortDescription": {"text": "Very large file: internal/sections/fetcher.go (3112 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a2345ce74174e98b", "name": "Very large file: internal/catalogseed/service.go (2604 lines)", "shortDescription": {"text": "Very large file: internal/catalogseed/service.go (2604 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a9d1c02a816952ef", "name": "Very large file: internal/watchtogether/service.go (2012 lines)", "shortDescription": {"text": "Very large file: internal/watchtogether/service.go (2012 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a6bffd770b7834db", "name": "Very large file: internal/scanner/scanner.go (2801 lines)", "shortDescription": {"text": "Very large file: internal/scanner/scanner.go (2801 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f3aaff9d4a6b0ce2", "name": "Very large file: internal/scanner/file_repo.go (3043 lines)", "shortDescription": {"text": "Very large file: internal/scanner/file_repo.go (3043 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b617849cd5bab5d5", "name": "Very large file: internal/scanner/ebook_test.go (1896 lines)", "shortDescription": {"text": "Very large file: internal/scanner/ebook_test.go (1896 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ccc47f9b2c743e2b", "name": "Very large file: internal/metadata/service_test.go (2209 lines)", "shortDescription": {"text": "Very large file: internal/metadata/service_test.go (2209 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fb26aeda82035151", "name": "Very large file: internal/metadata/service.go (5543 lines)", "shortDescription": {"text": "Very large file: internal/metadata/service.go (5543 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e9966c122fa16e86", "name": "Very large file: internal/playback/transcode.go (1856 lines)", "shortDescription": {"text": "Very large file: internal/playback/transcode.go (1856 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-af7d71a50e5ce35a", "name": "Very large file: internal/userstore/storetest/suite.go (1690 lines)", "shortDescription": {"text": "Very large file: internal/userstore/storetest/suite.go (1690 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a07c9a62b46675b8", "name": "Very large file: internal/watchsync/service_test.go (1944 lines)", "shortDescription": {"text": "Very large file: internal/watchsync/service_test.go (1944 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ce535521d3dfd938", "name": "Very large file: internal/watchsync/service.go (2147 lines)", "shortDescription": {"text": "Very large file: internal/watchsync/service.go (2147 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cde9db784632eddf", "name": "Very large file: cmd/silo/main.go (2651 lines)", "shortDescription": {"text": "Very large file: cmd/silo/main.go (2651 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-909c70caa07cbd73", "name": "Very large file: web/src/player/components/VideoPlayer.tsx (2417 lines)", "shortDescription": {"text": "Very large file: web/src/player/components/VideoPlayer.tsx (2417 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c0ae2aa1791a07da", "name": "Very large file: web/src/api/types.ts (4063 lines)", "shortDescription": {"text": "Very large file: web/src/api/types.ts (4063 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-472867be3f665a1d", "name": "Very large file: web/src/pages/AdminHistoryImport.tsx (1373 lines)", "shortDescription": {"text": "Very large file: web/src/pages/AdminHistoryImport.tsx (1373 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-164f71a9d5b66c7a", "name": "Very large file: web/src/pages/AdminRequests.tsx (1458 lines)", "shortDescription": {"text": "Very large file: web/src/pages/AdminRequests.tsx (1458 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-dc9599664d5b62aa", "name": "Very large file: web/src/pages/AdminDevices.tsx (1800 lines)", "shortDescription": {"text": "Very large file: web/src/pages/AdminDevices.tsx (1800 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b0e51402d80cea5f", "name": "Very large file: web/src/pages/adminCollectionsShared.tsx (1712 lines)", "shortDescription": {"text": "Very large file: web/src/pages/adminCollectionsShared.tsx (1712 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-35c7eb19361a8b74", "name": "Very large file: web/src/pages/AdminLibraries.tsx (2060 lines)", "shortDescription": {"text": "Very large file: web/src/pages/AdminLibraries.tsx (2060 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-01733c7b5333a854", "name": "Very large file: web/src/pages/settings/WebhookSyncSettings.tsx (1401 lines)", "shortDescription": {"text": "Very large file: web/src/pages/settings/WebhookSyncSettings.tsx (1401 lines)"}, "fullDescription": {"text": "Files with >800 lines often hide complexity hotspots and discourage tests."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3ab5d313dda8e5f9", "name": "Debug logging residue appears in source files", "shortDescription": {"text": "Debug logging residue appears in source files"}, "fullDescription": {"text": "Found 53 console/debugger/print-style debug statements in non-test source. This is a common fast-generation residue before production cleanup."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-72b2a6250083a784", "name": "Placeholder or mock-heavy implementation detected", "shortDescription": {"text": "Placeholder or mock-heavy implementation detected"}, "fullDescription": {"text": "Found 464 placeholder/mock markers across 170 source files. This often means the repo looks complete while core flows still use generated scaffolding or fake data."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9d79c4077342a7d0", "name": "Runtime service client appears to use placeholder configuration", "shortDescription": {"text": "Runtime service client appears to use placeholder configuration"}, "fullDescription": {"text": "A runtime source file appears to wire Supabase/Firebase/AI/payment-style clients to placeholder URLs, keys, or fallback values. In the Fable corpus this often means the UI/API shape is present while the backend service is not actually configured."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d0c7b7ab8f8aacf", "name": "Critical user flow still appears backed by mock or placeholder data", "shortDescription": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "fullDescription": {"text": "A payment/auth/admin/order/billing-style flow contains mock, fake, TODO, dummy, or placeholder markers in runtime source. In the Fable corpus this is a high-leverage completeness smell: the app can look finished while the money, identity, or tenant flow is still scaffolded."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ea8f3013f588db25", "name": "Shallow git history limits provenance confidence", "shortDescription": {"text": "Shallow git history limits provenance confidence"}, "fullDescription": {"text": "The repository is a shallow clone. Origin/evolution analysis cannot distinguish fresh generation, imported legacy code, or long-lived human code with high confidence."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8424db9c75e04ba4", "name": "Very short observed git history", "shortDescription": {"text": "Very short observed git history"}, "fullDescription": {"text": "The repo has multiple source files but two or fewer visible commits. This is not a failure by itself, but it lowers confidence in evolution-based diagnosis."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-8de13436c4db26a8", "name": "Commented-code block (5 lines) in scripts/dedup_audiobooks.py:51", "shortDescription": {"text": "Commented-code block (5 lines) in scripts/dedup_audiobooks.py:51"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-830ab2cf3d2332d3", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/player/utils/subtitleFonts.ts:126", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/player/utils/subtitleFonts.ts:126"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-62a7a861d70d1f58", "name": "Commented-code block (5 lines) in web/src/player/components/VideoPlayer.tsx:562", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/player/components/VideoPlayer.tsx:562"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-80f51e5b43cff916", "name": "Commented-code block (6 lines) in web/src/player/hooks/usePGSSubtitles.ts:30", "shortDescription": {"text": "Commented-code block (6 lines) in web/src/player/hooks/usePGSSubtitles.ts:30"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-fd092db9dfd3783d", "name": "Commented-code block (5 lines) in web/src/player/hooks/useASSSubtitles.test.tsx:186", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/player/hooks/useASSSubtitles.test.tsx:186"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-73e39666288bbf87", "name": "Commented-code block (7 lines) in web/src/player/hooks/useTranscodeQuality.ts:223", "shortDescription": {"text": "Commented-code block (7 lines) in web/src/player/hooks/useTranscodeQuality.ts:223"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-7233add4e4d2a21f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/player/hooks/useWatchProgress.ts:61", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/player/hooks/useWatchProgress.ts:61"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ff3f2b4493213a60", "name": "Commented-code block (6 lines) in web/src/player/hooks/useSubtitleTracks.ts:263", "shortDescription": {"text": "Commented-code block (6 lines) in web/src/player/hooks/useSubtitleTracks.ts:263"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-c4e37ee7eb12bc66", "name": "Commented-code block (6 lines) in web/src/player/hooks/useASSSubtitles.ts:34", "shortDescription": {"text": "Commented-code block (6 lines) in web/src/player/hooks/useASSSubtitles.ts:34"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-9d8accde7ea31109", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/api/client.ts:346", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/api/client.ts:346"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d2ec6fa43750b839", "name": "Commented-code block (5 lines) in web/src/components/RealtimeEventsProvider.tsx:804", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/components/RealtimeEventsProvider.tsx:804"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-5d109a8fe8dcf806", "name": "Commented-code block (6 lines) in web/src/components/HeroBanner.tsx:84", "shortDescription": {"text": "Commented-code block (6 lines) in web/src/components/HeroBanner.tsx:84"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-664cf387a15d72d4", "name": "Commented-code block (5 lines) in web/src/components/ContinueWatchingCard.tsx:189", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/components/ContinueWatchingCard.tsx:189"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-0a5ab906b0187746", "name": "Commented-code block (5 lines) in web/src/components/SectionRow.tsx:87", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/components/SectionRow.tsx:87"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-5f359627131b92a3", "name": "Commented-code block (6 lines) in web/src/components/CollectionTemplateGallery/CollectionTemplateConfigForm.tsx:347", "shortDescription": {"text": "Commented-code block (6 lines) in web/src/components/CollectionTemplateGallery/CollectionTemplateConfigForm.tsx:347"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e470ef4417a8bfec", "name": "Legacy-named symbol `lc_old` in web/src/components/CollectionTemplateGallery/CollectionTemplateGallery.test.tsx:314", "shortDescription": {"text": "Legacy-named symbol `lc_old` in web/src/components/CollectionTemplateGallery/CollectionTemplateGallery.test.tsx:314"}, "fullDescription": {"text": "Names with suffixes like `_old`, `_v1`, `_deprecated` usually indicate replaced-but-not-removed code (typical AI-coder leftover). Confirm and delete, or rename if it's the active version."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-39c8c25d9c018a69", "name": "Commented-code block (9 lines) in web/src/components/admin/deviceOverrides.tsx:161", "shortDescription": {"text": "Commented-code block (9 lines) in web/src/components/admin/deviceOverrides.tsx:161"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2c04a62593c49cc0", "name": "Commented-code block (5 lines) in web/src/lib/permissions.ts:31", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/lib/permissions.ts:31"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-a7e690404bc889a7", "name": "Commented-code block (6 lines) in web/src/lib/querySortOptions.ts:59", "shortDescription": {"text": "Commented-code block (6 lines) in web/src/lib/querySortOptions.ts:59"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-7958d80e6b19c536", "name": "Commented-code block (31 lines) in web/src/lib/design-system.ts:179", "shortDescription": {"text": "Commented-code block (31 lines) in web/src/lib/design-system.ts:179"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2c63546f7ef74795", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/lib/plexAuth.ts:99", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/lib/plexAuth.ts:99"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9350df376e729864", "name": "Commented-code block (5 lines) in web/src/lib/overlays/presets.ts:3", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/lib/overlays/presets.ts:3"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1bc92d3edfcf6be6", "name": "Commented-code block (6 lines) in web/src/lib/overlays/registry/ribbons.ts:3", "shortDescription": {"text": "Commented-code block (6 lines) in web/src/lib/overlays/registry/ribbons.ts:3"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e7a62177b96181fa", "name": "Commented-code block (5 lines) in web/src/pages/Collections.tsx:251", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/pages/Collections.tsx:251"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-48bd02bdcfd3894a", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/pages/OAuthComplete.tsx:14", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/pages/OAuthComplete.tsx:14"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9e97e05b51689d8f", "name": "Commented-code block (5 lines) in web/src/pages/LibraryPage.tsx:65", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/pages/LibraryPage.tsx:65"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1d4a508af668befa", "name": "Commented-code block (8 lines) in web/src/pages/AdminRequests.tsx:679", "shortDescription": {"text": "Commented-code block (8 lines) in web/src/pages/AdminRequests.tsx:679"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-1bff06ebce665e0a", "name": "Commented-code block (7 lines) in web/src/pages/AdminDevices.tsx:1164", "shortDescription": {"text": "Commented-code block (7 lines) in web/src/pages/AdminDevices.tsx:1164"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-d5035c9226ee6f76", "name": "Commented-code block (7 lines) in web/src/pages/ProfileCustomizeHome.tsx:31", "shortDescription": {"text": "Commented-code block (7 lines) in web/src/pages/ProfileCustomizeHome.tsx:31"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e73e9c4e7a39b932", "name": "Commented-code block (7 lines) in web/src/pages/admin-settings/BrandingSettings.tsx:28", "shortDescription": {"text": "Commented-code block (7 lines) in web/src/pages/admin-settings/BrandingSettings.tsx:28"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-2ca5c20f19c69c9f", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/reader/readest/libs/document.ts:228", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/reader/readest/libs/document.ts:228"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-bca3f02041621e94", "name": "Commented-code block (5 lines) in web/src/hooks/queries/collections.ts:134", "shortDescription": {"text": "Commented-code block (5 lines) in web/src/hooks/queries/collections.ts:134"}, "fullDescription": {"text": "A long run of `//` or `#` lines usually means abandoned code. Delete or move to git history. Keeps the canvas + dead-code detection honest."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "info", "confidence": 1.0}}, {"id": "scanner-e8bf0c1f53a233c9", "name": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/hooks/queries/admin/libraries.ts:85", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/hooks/queries/admin/libraries.ts:85"}, "fullDescription": {"text": "Bare `fetch(...)` will throw an unhandled rejection on network failure. Wrap in try/catch, attach a `.catch(...)`, or pass an AbortSignal with a timeout."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d0b17c8c07a7421d", "name": "8 env vars used in code but missing from .env.example", "shortDescription": {"text": "8 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `GEMINI_API_KEY`, `OPENAI_API_KEY`, `PGDATABASE`, `PGHOST`, `PGPASSWORD`, `PGPORT`, `PGUSER`, `SILO_LIBRARY_ID`. Add them (with a placeholder/comment) to .env.example so onboarding doesn't break."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2c04133e54348533", "name": "Near-duplicate function bodies in 2 places", "shortDescription": {"text": "Near-duplicate function bodies in 2 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nscripts/dedup_audiobooks.py:find_duplicate_pairs, scripts/dedup_audiobooks.py:find\n\nThis is *the* AI-coder failure mode (4\u00d7 more duplication in vibe-coded repos \u2014 see https://jw.hn/ai-code-hygiene). Consolidate or document why they're separate."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1293c5d6ff4a28cd", "name": "Frontend route `/login/oauth-complete` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/login/oauth-complete` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c36df52adcc29f38", "name": "Frontend route `/activate` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/activate` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-140acc5da60aebac", "name": "Frontend route `/signup` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/signup` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d368f7604311fb8e", "name": "Frontend route `/*` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/*` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d861f7aed9b787fe", "name": "Frontend route `/watch/:id` has no Link/navigate to it \u2014 web/src/pages/WatchRoute.component.test.tsx", "shortDescription": {"text": "Frontend route `/watch/:id` has no Link/navigate to it \u2014 web/src/pages/WatchRoute.component.test.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-93bdeddaa820924b", "name": "Frontend route `/reader/ebook/:contentId` has no Link/navigate to it \u2014 web/src/pages/EbookReader.test.tsx", "shortDescription": {"text": "Frontend route `/reader/ebook/:contentId` has no Link/navigate to it \u2014 web/src/pages/EbookReader.test.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1c8e4d522b79f330", "name": "Frontend route `/admin/*` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/admin/*` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-20edd36017ec926d", "name": "Frontend route `activity` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `activity` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e344e9dcf1228e55", "name": "Frontend route `logs` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `logs` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-aa20352120955009", "name": "Frontend route `maintenance` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `maintenance` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-bc766704dff857a5", "name": "Frontend route `collections` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `collections` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-d6f29d073e392c3f", "name": "Frontend route `collections/new` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `collections/new` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ebade5b710227dca", "name": "Frontend route `collections/:id/edit` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `collections/:id/edit` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1231de0e658a8f9f", "name": "Frontend route `requests` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `requests` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-aba86cf0afa08228", "name": "Frontend route `autoscan` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `autoscan` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f39b9f6a9d13c086", "name": "Frontend route `history` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `history` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e1ad599d38ef05f8", "name": "Frontend route `marker-history` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `marker-history` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-11b2684a442d3153", "name": "Frontend route `users` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `users` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f4a131417b2c7a04", "name": "Frontend route `users/:id` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `users/:id` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-231a99f177a79e97", "name": "Frontend route `devices` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `devices` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-762432e309fc26a1", "name": "Frontend route `devices/:userId/:deviceId` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `devices/:userId/:deviceId` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a666ef09c03ea030", "name": "Frontend route `nodes` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `nodes` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c182b49fbebd8f09", "name": "Frontend route `sections` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `sections` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6ae280707dbadf3f", "name": "Frontend route `plugins` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `plugins` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-88cf01eced5e2d03", "name": "Frontend route `settings` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `settings` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-be24191a6de828fe", "name": "Frontend route `recommendations` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `recommendations` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-446754b3ab8c8944", "name": "Frontend route `api-keys` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `api-keys` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1b09ff635eebea0a", "name": "Frontend route `subtitles` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `subtitles` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c409e623e39e9533", "name": "Frontend route `tasks` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `tasks` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0ea43e2388ebfdab", "name": "Frontend route `tasks/:key` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `tasks/:key` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-cadd0e76955b661a", "name": "Frontend route `stats` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `stats` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2d60b9b56cbd5729", "name": "Frontend route `/settings/*` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/settings/*` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-03592e083bd3814b", "name": "Frontend route `plex-webhooks` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `plex-webhooks` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-6fcf4a27b8598a9e", "name": "Frontend route `/catalog` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/catalog` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7f69614adf386202", "name": "Frontend route `/library/:libraryId` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/library/:libraryId` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-02520f191bf5157e", "name": "Frontend route `/search` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/search` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-96a949112c653352", "name": "Frontend route `/browse` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/browse` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ced46130dbfa6dee", "name": "Frontend route `/item/:id` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/item/:id` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-079d76fb1be1afe5", "name": "Frontend route `/person/:id` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/person/:id` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7930eb3548edc83c", "name": "Frontend route `/rooms/:roomId` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/rooms/:roomId` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0aadbf98f0f45ba0", "name": "Frontend route `/favorites` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/favorites` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-12fb0dad41526043", "name": "Frontend route `/watchlist` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/watchlist` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-0afa231a717c83ab", "name": "Frontend route `/history` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/history` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-bfd1f189cffaa936", "name": "Frontend route `/collections/new` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/collections/new` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-342c6f4671568980", "name": "Frontend route `/collections/:id/edit` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/collections/:id/edit` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-667f9eed74ead38c", "name": "Frontend route `/collections/:id` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/collections/:id` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7d013c4311929a51", "name": "Frontend route `/requests/:mediaType/:tmdbId` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/requests/:mediaType/:tmdbId` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-24962dca4a3e01c4", "name": "Frontend route `/requests/browse/studio/:slug` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/requests/browse/studio/:slug` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ff1c78ab8e967677", "name": "Frontend route `/requests/browse/network/:slug` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/requests/browse/network/:slug` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-7a584f199677ac53", "name": "Frontend route `/requests/browse/genre/:slug` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/requests/browse/genre/:slug` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-44d30f78fa22c203", "name": "Frontend route `/recommendations/section/:kind` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/recommendations/section/:kind` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-39cc2347c30e896b", "name": "Frontend route `/recommendations/section/:kind/:key` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/recommendations/section/:kind/:key` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-bdd4a80a38b42ebd", "name": "Frontend route `/profile/customize-home` has no Link/navigate to it \u2014 web/src/App.tsx", "shortDescription": {"text": "Frontend route `/profile/customize-home` has no Link/navigate to it \u2014 web/src/App.tsx"}, "fullDescription": {"text": "The route is registered but no `<Link to=\u2026>` or `navigate(\u2026)` in the codebase navigates here. Either it's reachable only via direct URL (intentional), it's dead, or the link broke during a refactor."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/19637"}, "properties": {"repository": "Silo-Server/silo-server", "repoUrl": "https://github.com/Silo-Server/silo-server", "branch": "main"}, "results": [{"ruleId": "scanner-5a9777fb6ff32d51", "level": "note", "message": {"text": "Possibly dead Python function: fetch_case"}, "properties": {"repobilityId": "3883ef904dd120d6", "scanner": "scanner-primary", "fingerprint": "5a9777fb6ff32d51", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "scripts/benchmark_episode_catalog.py:151"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-f41667c957c40a59", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/ChaptersMenu.tsx:137"}, "properties": {"repobilityId": "ad9400f6da4a3855", "scanner": "scanner-primary", "fingerprint": "f41667c957c40a59", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7a2209a5bce53108", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/QualityMenu.tsx:146"}, "properties": {"repobilityId": "71390775a56cd944", "scanner": "scanner-primary", "fingerprint": "7a2209a5bce53108", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8be544909ee3769c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/AudioTrackMenu.tsx:167"}, "properties": {"repobilityId": "d18a53beafa54097", "scanner": "scanner-primary", "fingerprint": "8be544909ee3769c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-91712b20ebdc90ad", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/PlayingNextScreen.tsx:423"}, "properties": {"repobilityId": "b142e53a8a59fd91", "scanner": "scanner-primary", "fingerprint": "91712b20ebdc90ad", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-fa6be24d5f0d9605", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/PlaybackInfoOverlay.tsx:91"}, "properties": {"repobilityId": "e356dd7c82f4dbc5", "scanner": "scanner-primary", "fingerprint": "fa6be24d5f0d9605", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-59339bb99a6d8de8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/SubtitleSearchModal.tsx:345"}, "properties": {"repobilityId": "7a1969ad237ae38f", "scanner": "scanner-primary", "fingerprint": "59339bb99a6d8de8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-54b1d8d4ea10f0f9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/player/components/SeekBar.tsx:320"}, "properties": {"repobilityId": "5843ecc6a63497c1", "scanner": "scanner-primary", "fingerprint": "54b1d8d4ea10f0f9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-140629a15fd82e28", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/NowListeningHero.tsx:186"}, "properties": {"repobilityId": "39f1a9595544245d", "scanner": "scanner-primary", "fingerprint": "140629a15fd82e28", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4c2322e72af2ed0d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/RecommendationGrid.tsx:33"}, "properties": {"repobilityId": "b1321b7fb5be3e0a", "scanner": "scanner-primary", "fingerprint": "4c2322e72af2ed0d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f241376f8ea1b7b6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/SideNav.tsx:75"}, "properties": {"repobilityId": "0eb303ed62c1760d", "scanner": "scanner-primary", "fingerprint": "f241376f8ea1b7b6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-9b729fb7bf0f038d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/AppSidebar.tsx:460"}, "properties": {"repobilityId": "69684eb6ab9f8de2", "scanner": "scanner-primary", "fingerprint": "9b729fb7bf0f038d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-642d0fb320ad5154", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ContinueWatchingCard.tsx:288"}, "properties": {"repobilityId": "d3409f0f66f114ac", "scanner": "scanner-primary", "fingerprint": "642d0fb320ad5154", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b4c03bf9f823f794", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/SectionItemCard.tsx:101"}, "properties": {"repobilityId": "2d9b2358083a960b", "scanner": "scanner-primary", "fingerprint": "b4c03bf9f823f794", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bf2afb24b0a69935", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/GlobalSearch.tsx:93"}, "properties": {"repobilityId": "f5862dd8821a7211", "scanner": "scanner-primary", "fingerprint": "bf2afb24b0a69935", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f30010ed00481f64", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/WatchTonightCard.tsx:152"}, "properties": {"repobilityId": "39cedbfca1022ec2", "scanner": "scanner-primary", "fingerprint": "f30010ed00481f64", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-172474b82c949eac", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/LibraryMultiSelect.tsx:94"}, "properties": {"repobilityId": "2a0c031f0e32a8bc", "scanner": "scanner-primary", "fingerprint": "172474b82c949eac", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dd883a2012768f45", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/AddToCollectionDialog.tsx:160"}, "properties": {"repobilityId": "544990d84604c2e0", "scanner": "scanner-primary", "fingerprint": "dd883a2012768f45", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0074eaa85937da4c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ImpersonationBanner.tsx:45"}, "properties": {"repobilityId": "a662ddb878ba30e2", "scanner": "scanner-primary", "fingerprint": "0074eaa85937da4c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1d0b6d6e5fa54fce", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CrewList.tsx:47"}, "properties": {"repobilityId": "d4fbaea6dee9d401", "scanner": "scanner-primary", "fingerprint": "1d0b6d6e5fa54fce", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2e6b793b8fd616c3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CastCarousel.tsx:106"}, "properties": {"repobilityId": "e8aa4036d37158e0", "scanner": "scanner-primary", "fingerprint": "2e6b793b8fd616c3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cf33980f8167ab94", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ItemCard.tsx:245"}, "properties": {"repobilityId": "cf9b363beae00762", "scanner": "scanner-primary", "fingerprint": "cf33980f8167ab94", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c9ff5aa192bbb20c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/RequestToAddSection.tsx:129"}, "properties": {"repobilityId": "d445bb0b15869bd6", "scanner": "scanner-primary", "fingerprint": "c9ff5aa192bbb20c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-691eeca246667471", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionSearchableSelect.tsx:72"}, "properties": {"repobilityId": "1beb0f9742039648", "scanner": "scanner-primary", "fingerprint": "691eeca246667471", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3fbc8524c0c0f2dd", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/LibraryHeader.tsx:68"}, "properties": {"repobilityId": "c19295862718924e", "scanner": "scanner-primary", "fingerprint": "3fbc8524c0c0f2dd", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4a87cfd797151091", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ThemeSwitcher.tsx:43"}, "properties": {"repobilityId": "d38a55caf9010dc5", "scanner": "scanner-primary", "fingerprint": "4a87cfd797151091", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-442e54da720b13b3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/RequestPosterCard.tsx:207"}, "properties": {"repobilityId": "41c321d40a357380", "scanner": "scanner-primary", "fingerprint": "442e54da720b13b3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-06689a5dbb827033", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/EpisodeRow.tsx:71"}, "properties": {"repobilityId": "bead0cf1835b7361", "scanner": "scanner-primary", "fingerprint": "06689a5dbb827033", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-82292cda3e27daa7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/MatchItemDialog.tsx:217"}, "properties": {"repobilityId": "bc8b77d298a89c27", "scanner": "scanner-primary", "fingerprint": "82292cda3e27daa7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-dcf2f62481c3987b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/FolderBrowser.tsx:268"}, "properties": {"repobilityId": "62095d89081a997d", "scanner": "scanner-primary", "fingerprint": "dcf2f62481c3987b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b989d56f8883287b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ServerActivity.tsx:305"}, "properties": {"repobilityId": "9d98a19427ccc823", "scanner": "scanner-primary", "fingerprint": "b989d56f8883287b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-99fb352c0f43c701", "level": "note", "message": {"text": "\"active\" state uses light bg in a dark theme \u2014 web/src/components/settings/SubtitleAppearancePanelView.tsx:297"}, "properties": {"repobilityId": "da9bce0a7e175d67", "scanner": "scanner-primary", "fingerprint": "99fb352c0f43c701", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.active-light-bg"]}}, {"ruleId": "scanner-8fea595f84a2a07d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/audiobooks/AudiobookGroupsView.tsx:200"}, "properties": {"repobilityId": "35544a489d9c2abe", "scanner": "scanner-primary", "fingerprint": "8fea595f84a2a07d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b9bc90f51180a9f6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionTemplateGallery/MDBListBrowser.tsx:86"}, "properties": {"repobilityId": "92b94db3758e38b3", "scanner": "scanner-primary", "fingerprint": "b9bc90f51180a9f6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-aebaaec1b01091da", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionTemplateGallery/CollectionTemplateCard.tsx:45"}, "properties": {"repobilityId": "012cbfceccc3f7b7", "scanner": "scanner-primary", "fingerprint": "aebaaec1b01091da", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-19586d1d0ff4d028", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/CollectionTemplateGallery/TemplatePosterField.tsx:58"}, "properties": {"repobilityId": "3060b8489fb40717", "scanner": "scanner-primary", "fingerprint": "19586d1d0ff4d028", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-15b55aadd47a4b14", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ui/facet-search-select.tsx:124"}, "properties": {"repobilityId": "c2084d3eb3448553", "scanner": "scanner-primary", "fingerprint": "15b55aadd47a4b14", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-23d1bc050923e973", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ui/person-search-select.tsx:89"}, "properties": {"repobilityId": "85ddb8a3dea7b598", "scanner": "scanner-primary", "fingerprint": "23d1bc050923e973", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-fbf09f75a9885951", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/ui/searchable-select.tsx:85"}, "properties": {"repobilityId": "3f1b23edc92c9a31", "scanner": "scanner-primary", "fingerprint": "fbf09f75a9885951", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-411f0507f57595db", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/admin/deviceOverrides.tsx:612"}, "properties": {"repobilityId": "f8b13bb776f057a7", "scanner": "scanner-primary", "fingerprint": "411f0507f57595db", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-88a7f9b32733b052", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/admin/libraries/LibraryEditorDialog.tsx:132"}, "properties": {"repobilityId": "8fa2a52628adf1d0", "scanner": "scanner-primary", "fingerprint": "88a7f9b32733b052", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8594bfc658e6fdb3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/ManualCollectionItemsEditor.tsx:111"}, "properties": {"repobilityId": "80db8572a01e6f3c", "scanner": "scanner-primary", "fingerprint": "8594bfc658e6fdb3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b1e7bab1dc20868f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/CollectionPreviewPane.tsx:51"}, "properties": {"repobilityId": "6ad21db846b08129", "scanner": "scanner-primary", "fingerprint": "b1e7bab1dc20868f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-acd1f38712916430", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/CollectionPosterCard.tsx:61"}, "properties": {"repobilityId": "cc447a0f7729afdc", "scanner": "scanner-primary", "fingerprint": "acd1f38712916430", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a322d2657956fa2b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/collections/admin/CollectionRow.tsx:89"}, "properties": {"repobilityId": "06cb2c46ffc3921f", "scanner": "scanner-primary", "fingerprint": "a322d2657956fa2b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c07009f8f5dcbd4d", "level": "note", "message": {"text": "Icon-only button without accessible name \u2014 web/src/components/RecipeGallery/RecipeGalleryModal.tsx:83"}, "properties": {"repobilityId": "d5eb33c14c9d6647", "scanner": "scanner-primary", "fingerprint": "c07009f8f5dcbd4d", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.button.no-label"]}}, {"ruleId": "scanner-c689b8eb4f50a595", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/FilterEasyMode/PreviewBox.tsx:45"}, "properties": {"repobilityId": "ecbbe834eda5d32f", "scanner": "scanner-primary", "fingerprint": "c689b8eb4f50a595", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4625a2b1baf03122", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/profiles/HouseholdStreamsPanel.tsx:77"}, "properties": {"repobilityId": "419f5d2172979fe8", "scanner": "scanner-primary", "fingerprint": "4625a2b1baf03122", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f0087e2c8e3a89aa", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/calendar/CalendarEventCard.tsx:85"}, "properties": {"repobilityId": "185c566d328b4d7e", "scanner": "scanner-primary", "fingerprint": "f0087e2c8e3a89aa", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-796352672b7715a2", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/components/calendar/WeekNavigator.tsx:48"}, "properties": {"repobilityId": "bda6423591a354a1", "scanner": "scanner-primary", "fingerprint": "796352672b7715a2", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cc2bc75153b2cc9d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminHistoryImport.tsx:724"}, "properties": {"repobilityId": "db481b7666901bfc", "scanner": "scanner-primary", "fingerprint": "cc2bc75153b2cc9d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-e134fc2c05d6f20b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminMarkerHistory.tsx:115"}, "properties": {"repobilityId": "63cb9b71bfd77193", "scanner": "scanner-primary", "fingerprint": "e134fc2c05d6f20b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4d094459f4e9427a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/WatchTogetherRoomPage.tsx:127"}, "properties": {"repobilityId": "1f85881afa05f06c", "scanner": "scanner-primary", "fingerprint": "4d094459f4e9427a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f93f4757411bf50b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/RequestBrowse.tsx:103"}, "properties": {"repobilityId": "ee9422c0faa9579f", "scanner": "scanner-primary", "fingerprint": "f93f4757411bf50b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f315a572e5ad3012", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminDashboard.tsx:528"}, "properties": {"repobilityId": "e5d8b5ebbd772450", "scanner": "scanner-primary", "fingerprint": "f315a572e5ad3012", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-802fbe6a2c078a1f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminCollections.tsx:552"}, "properties": {"repobilityId": "12f52ef835e06c7d", "scanner": "scanner-primary", "fingerprint": "802fbe6a2c078a1f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6de89454cbf53819", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/EbookReader.tsx:538"}, "properties": {"repobilityId": "6f467a59e830c995", "scanner": "scanner-primary", "fingerprint": "6de89454cbf53819", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-044b71dedeb26ea5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/WatchTogetherSuggestionPanel.tsx:103"}, "properties": {"repobilityId": "9e727093b7f9e13b", "scanner": "scanner-primary", "fingerprint": "044b71dedeb26ea5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4926defc43a7e63a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminDevices.tsx:1004"}, "properties": {"repobilityId": "c0355bcd7382bd52", "scanner": "scanner-primary", "fingerprint": "4926defc43a7e63a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-85aaf0967125af46", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminTaskDetail.tsx:151"}, "properties": {"repobilityId": "61e98d9d4a0a1a3e", "scanner": "scanner-primary", "fingerprint": "85aaf0967125af46", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-bf130d4315a572b8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminPlugins.tsx:579"}, "properties": {"repobilityId": "858fb45c4ecfaf7d", "scanner": "scanner-primary", "fingerprint": "bf130d4315a572b8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-04635337d8f0c523", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminLibraries.tsx:816"}, "properties": {"repobilityId": "ca238a56339f9103", "scanner": "scanner-primary", "fingerprint": "04635337d8f0c523", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4700f8d997a0da73", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ImportedCollectionEditor.tsx:748"}, "properties": {"repobilityId": "c9b0aed621053007", "scanner": "scanner-primary", "fingerprint": "4700f8d997a0da73", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-529a29f0cf6adc8f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/AdminActivity.tsx:580"}, "properties": {"repobilityId": "d4d32a6f46d95d51", "scanner": "scanner-primary", "fingerprint": "529a29f0cf6adc8f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-66c8bb602533e152", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/Notifications.tsx:160"}, "properties": {"repobilityId": "0508868c4db8bc14", "scanner": "scanner-primary", "fingerprint": "66c8bb602533e152", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-30469f2a5de95ef9", "level": "none", "message": {"text": "TODO/FIXME marker in shipping code \u2014 web/src/pages/ProfileCustomizeHome.tsx:248"}, "properties": {"repobilityId": "004ebf13f6a0a33e", "scanner": "scanner-primary", "fingerprint": "30469f2a5de95ef9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.todo-marker"]}}, {"ruleId": "scanner-f6d8962b8c291b65", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/ProfilesSettings.tsx:145"}, "properties": {"repobilityId": "a28e8c72462ff079", "scanner": "scanner-primary", "fingerprint": "f6d8962b8c291b65", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5555e3943fe3da3d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/LibrarySettings.tsx:269"}, "properties": {"repobilityId": "195be4baa6b91423", "scanner": "scanner-primary", "fingerprint": "5555e3943fe3da3d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d6b68c45233bc28b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/WatchProvidersSettings.tsx:131"}, "properties": {"repobilityId": "3255f21285e1b4a1", "scanner": "scanner-primary", "fingerprint": "d6b68c45233bc28b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-61fc25599803519c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/WebhookSyncSettings.tsx:971"}, "properties": {"repobilityId": "90c7b77632f41ef7", "scanner": "scanner-primary", "fingerprint": "61fc25599803519c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4299219c7ee4dd66", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/settings/NotificationsSettings.tsx:647"}, "properties": {"repobilityId": "004c038a3779f229", "scanner": "scanner-primary", "fingerprint": "4299219c7ee4dd66", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5ee3f58cf4200c2d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/NarratorPicker.tsx:67"}, "properties": {"repobilityId": "d067fa1f3b233c86", "scanner": "scanner-primary", "fingerprint": "5ee3f58cf4200c2d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-da6bf42ae4443e2e", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/ChaptersSection.tsx:149"}, "properties": {"repobilityId": "672d80f885eb011d", "scanner": "scanner-primary", "fingerprint": "da6bf42ae4443e2e", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d9dfd65466ee2595", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/RelatedRail.tsx:53"}, "properties": {"repobilityId": "2e92252d2d5c1fc3", "scanner": "scanner-primary", "fingerprint": "d9dfd65466ee2595", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-fa832a3b96e9dc53", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/audiobooks/components/NarratorCard.tsx:23"}, "properties": {"repobilityId": "46f8596cc6953452", "scanner": "scanner-primary", "fingerprint": "fa832a3b96e9dc53", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-0bbf99008b779b8d", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/setup-wizard/steps/ServerStorageStep.tsx:469"}, "properties": {"repobilityId": "88281e3bb8933ec0", "scanner": "scanner-primary", "fingerprint": "0bbf99008b779b8d", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-37872131f8784053", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/admin/autoscan/ConnectionsPanel.tsx:302"}, "properties": {"repobilityId": "7438acaded553a43", "scanner": "scanner-primary", "fingerprint": "37872131f8784053", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b7861fbcb65329df", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/admin/autoscan/SourcesPanel.tsx:637"}, "properties": {"repobilityId": "55683278acb877ba", "scanner": "scanner-primary", "fingerprint": "b7861fbcb65329df", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-65d81c0d7b8ae9a6", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/SeasonCarousel.tsx:101"}, "properties": {"repobilityId": "ce7b53f2612092ca", "scanner": "scanner-primary", "fingerprint": "65d81c0d7b8ae9a6", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cb7b21ca8b3b57d0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/SubtitlesPopover.tsx:236"}, "properties": {"repobilityId": "f216e0cef4694d1d", "scanner": "scanner-primary", "fingerprint": "cb7b21ca8b3b57d0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-548c6daa9c3a80ce", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/AudioTracksPopover.tsx:100"}, "properties": {"repobilityId": "7f88a838960ee781", "scanner": "scanner-primary", "fingerprint": "548c6daa9c3a80ce", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cfb04d87c388ff42", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/SeasonEpisodeGrid.tsx:107"}, "properties": {"repobilityId": "a69f074c0e2acbc0", "scanner": "scanner-primary", "fingerprint": "cfb04d87c388ff42", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3dcb8ab62672757b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/VersionDropdown.tsx:70"}, "properties": {"repobilityId": "03c9e98d925fe991", "scanner": "scanner-primary", "fingerprint": "3dcb8ab62672757b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4472a929efd973a5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/SubtitleSearchDialog.tsx:233"}, "properties": {"repobilityId": "9b9da2e2341d4f12", "scanner": "scanner-primary", "fingerprint": "4472a929efd973a5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-c8dbeaf4a3e81247", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/VersionFlyout.tsx:79"}, "properties": {"repobilityId": "c320dbaf83898cd1", "scanner": "scanner-primary", "fingerprint": "c8dbeaf4a3e81247", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6273a059bf876054", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/pages/ItemDetail/components/EpisodeCarousel.tsx:162"}, "properties": {"repobilityId": "6f9466e8c5f9fbd7", "scanner": "scanner-primary", "fingerprint": "6273a059bf876054", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-63d5fb0cae91f8a5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 web/src/playback/WatchPlaybackChrome.tsx:927"}, "properties": {"repobilityId": "c0d7ebf1b0906586", "scanner": "scanner-primary", "fingerprint": "63d5fb0cae91f8a5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d63da3583b14afc0", "level": "warning", "message": {"text": "Dockerfile runs as root: Dockerfile"}, "properties": {"repobilityId": "a2ed1bd120e507db", "scanner": "scanner-primary", "fingerprint": "d63da3583b14afc0", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-93e02e0d67c8f3e8", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: node:22-slim"}, "properties": {"repobilityId": "d8214ede3c85bb3c", "scanner": "scanner-primary", "fingerprint": "93e02e0d67c8f3e8", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 2}}}]}, {"ruleId": "scanner-34d41f64da56cd8b", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: golang:1.26"}, "properties": {"repobilityId": "e9136243f6ef9801", "scanner": "scanner-primary", "fingerprint": "34d41f64da56cd8b", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 18}}}]}, {"ruleId": "scanner-84019dfd8d98a34d", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: debian:bookworm-slim"}, "properties": {"repobilityId": "73a7cdf59f2f2ffa", "scanner": "scanner-primary", "fingerprint": "84019dfd8d98a34d", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "Dockerfile"}, "region": {"startLine": 44}}}]}, {"ruleId": "scanner-aa5acaa49eb8315b", "level": "note", "message": {"text": "Containers defined but no K8s/orchestration manifest found"}, "properties": {"repobilityId": "b230ea9b68736081", "scanner": "scanner-primary", "fingerprint": "aa5acaa49eb8315b", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["coverage", "deployment"]}}, {"ruleId": "scanner-6993af2e694a7917", "level": "error", "message": {"text": "Possible secret in internal/mail/mail.go"}, "properties": {"repobilityId": "19b3374646f9e5fd", "scanner": "scanner-primary", "fingerprint": "6993af2e694a7917", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "internal/mail/mail.go"}, "region": {"startLine": 38}}}]}, {"ruleId": "scanner-779d5ec2e07a8e00", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in internal/api/handlers/stream.go:353"}, "properties": {"repobilityId": "f4daa21c301952b6", "scanner": "scanner-primary", "fingerprint": "779d5ec2e07a8e00", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "internal/api/handlers/stream.go"}, "region": {"startLine": 353}}}]}, {"ruleId": "scanner-942433c3a7c461e1", "level": "error", "message": {"text": "Possible secret in internal/subtitles/opensubtitles/opensubtitles.go"}, "properties": {"repobilityId": "5332fb5fecd937e3", "scanner": "scanner-primary", "fingerprint": "942433c3a7c461e1", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "internal/subtitles/opensubtitles/opensubtitles.go"}, "region": {"startLine": 23}}}]}, {"ruleId": "scanner-f38d02255ac06826", "level": "error", "message": {"text": "Possible secret in internal/metadata/tmdb/client.go"}, "properties": {"repobilityId": "633af690920dad6c", "scanner": "scanner-primary", "fingerprint": "f38d02255ac06826", "layer": "security", "severity": "critical", "confidence": 1.0, "tags": ["secrets"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "internal/metadata/tmdb/client.go"}, "region": {"startLine": 22}}}]}, {"ruleId": "scanner-7f0f9976570faa6d", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "e9e8e5955bd12433", "scanner": "scanner-primary", "fingerprint": "7f0f9976570faa6d", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/docker.yml"}, "region": {"startLine": 29}}}]}, {"ruleId": "scanner-7f0f9976570faa6d", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "6932bddd9d284155", "scanner": "scanner-primary", "fingerprint": "7f0f9976570faa6d", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/docker.yml"}, "region": {"startLine": 32}}}]}, {"ruleId": "scanner-7f0f9976570faa6d", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "35e82279a229c0c9", "scanner": "scanner-primary", "fingerprint": "7f0f9976570faa6d", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/docker.yml"}, "region": {"startLine": 37}}}]}, {"ruleId": "scanner-7f0f9976570faa6d", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "ec2f0f545b3517bb", "scanner": "scanner-primary", "fingerprint": "7f0f9976570faa6d", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/docker.yml"}, "region": {"startLine": 52}}}]}, {"ruleId": "scanner-7f0f9976570faa6d", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "49f477cbbe083433", "scanner": "scanner-primary", "fingerprint": "7f0f9976570faa6d", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/docker.yml"}, "region": {"startLine": 78}}}]}, {"ruleId": "scanner-7f0f9976570faa6d", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "19a3e05b43a287b5", "scanner": "scanner-primary", "fingerprint": "7f0f9976570faa6d", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/docker.yml"}, "region": {"startLine": 84}}}]}, {"ruleId": "scanner-7f0f9976570faa6d", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "d6aa7210cf6c969d", "scanner": "scanner-primary", "fingerprint": "7f0f9976570faa6d", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/docker.yml"}, "region": {"startLine": 92}}}]}, {"ruleId": "scanner-7f0f9976570faa6d", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "5f7d5d8fad9ae56d", "scanner": "scanner-primary", "fingerprint": "7f0f9976570faa6d", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/docker.yml"}, "region": {"startLine": 100}}}]}, {"ruleId": "scanner-68a2b8f5c8cd6b53", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "0036b33690fe05ae", "scanner": "scanner-primary", "fingerprint": "68a2b8f5c8cd6b53", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/docker.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-de53ac274e5b4ecf", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "02600186fc092bd4", "scanner": "scanner-primary", "fingerprint": "de53ac274e5b4ecf", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/claude.yml"}, "region": {"startLine": 37}}}]}, {"ruleId": "scanner-de53ac274e5b4ecf", "level": "warning", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "8ead6a2c2bfe167b", "scanner": "scanner-primary", "fingerprint": "de53ac274e5b4ecf", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/claude.yml"}, "region": {"startLine": 43}}}]}, {"ruleId": "scanner-37716d9c0a33ad5c", "level": "warning", "message": {"text": "GitHub Actions workflow grants broad write permissions"}, "properties": {"repobilityId": "abfb5752158cf655", "scanner": "scanner-primary", "fingerprint": "37716d9c0a33ad5c", "layer": "cicd", "severity": "medium", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "least-privilege"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/claude.yml"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-9ae56bc4b9d36417", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "0bb1124ddcec1ba9", "scanner": "scanner-primary", "fingerprint": "9ae56bc4b9d36417", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/discord-commits.yml"}, "region": {"startLine": 16}}}]}, {"ruleId": "scanner-9a9f882b748428d5", "level": "note", "message": {"text": "Very large file: internal/recommendations/repo.go (1946 lines)"}, "properties": {"repobilityId": "9be0039e951790b9", "scanner": "scanner-primary", "fingerprint": "9a9f882b748428d5", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-2bb504716120100a", "level": "note", "message": {"text": "Very large file: internal/requests/service_test.go (2697 lines)"}, "properties": {"repobilityId": "dd0f3c122b7dff28", "scanner": "scanner-primary", "fingerprint": "2bb504716120100a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-34bbc2d65a89fd1a", "level": "note", "message": {"text": "Very large file: internal/requests/service.go (1833 lines)"}, "properties": {"repobilityId": "d113963275f3f3c0", "scanner": "scanner-primary", "fingerprint": "34bbc2d65a89fd1a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-557e3aa6374233ec", "level": "note", "message": {"text": "Very large file: internal/api/router.go (2916 lines)"}, "properties": {"repobilityId": "f81797da97473af9", "scanner": "scanner-primary", "fingerprint": "557e3aa6374233ec", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-502171769c6181e1", "level": "note", "message": {"text": "Very large file: internal/api/handlers/admin.go (2164 lines)"}, "properties": {"repobilityId": "42614a5aaa4b641d", "scanner": "scanner-primary", "fingerprint": "502171769c6181e1", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-e95321e5e49a8a13", "level": "note", "message": {"text": "Very large file: internal/api/handlers/playback_test.go (1505 lines)"}, "properties": {"repobilityId": "db72a75773c80563", "scanner": "scanner-primary", "fingerprint": "e95321e5e49a8a13", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-46a3b96af2302b80", "level": "note", "message": {"text": "Very large file: internal/api/handlers/playback.go (2648 lines)"}, "properties": {"repobilityId": "7f205fec7262193c", "scanner": "scanner-primary", "fingerprint": "46a3b96af2302b80", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-172908bf49648220", "level": "note", "message": {"text": "Very large file: internal/api/handlers/items.go (1815 lines)"}, "properties": {"repobilityId": "36c2b6e0411c33fd", "scanner": "scanner-primary", "fingerprint": "172908bf49648220", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a64eb7145acf51a5", "level": "note", "message": {"text": "Very large file: internal/api/handlers/sections.go (1566 lines)"}, "properties": {"repobilityId": "0fb4c1a214313fe2", "scanner": "scanner-primary", "fingerprint": "a64eb7145acf51a5", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-740ade55288048bd", "level": "note", "message": {"text": "Very large file: internal/api/handlers/library_collections.go (3722 lines)"}, "properties": {"repobilityId": "8ea83348e2808863", "scanner": "scanner-primary", "fingerprint": "740ade55288048bd", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a3a93c19fc4180cf", "level": "note", "message": {"text": "Very large file: internal/api/handlers/libraries.go (2561 lines)"}, "properties": {"repobilityId": "2a442980ea60e08b", "scanner": "scanner-primary", "fingerprint": "a3a93c19fc4180cf", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-4516077f41094629", "level": "note", "message": {"text": "Very large file: internal/api/handlers/plugins.go (1619 lines)"}, "properties": {"repobilityId": "228fa62e254f97d2", "scanner": "scanner-primary", "fingerprint": "4516077f41094629", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-d3507221982647f9", "level": "note", "message": {"text": "Very large file: internal/jellycompat/handlers_items.go (2526 lines)"}, "properties": {"repobilityId": "d8c35e139a0c9910", "scanner": "scanner-primary", "fingerprint": "d3507221982647f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-89a14f5296ec6291", "level": "note", "message": {"text": "Very large file: internal/jellycompat/streams.go (1441 lines)"}, "properties": {"repobilityId": "5979eb2153e4d14e", "scanner": "scanner-primary", "fingerprint": "89a14f5296ec6291", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-9bfd21396f01b022", "level": "note", "message": {"text": "Very large file: internal/catalog/catalog_resolver.go (2338 lines)"}, "properties": {"repobilityId": "4de5245fd0ac79ef", "scanner": "scanner-primary", "fingerprint": "9bfd21396f01b022", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-b32cd2e7db5b2711", "level": "note", "message": {"text": "Very large file: internal/catalog/query_builder.go (1760 lines)"}, "properties": {"repobilityId": "d0a1d8fc84cc2fab", "scanner": "scanner-primary", "fingerprint": "b32cd2e7db5b2711", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-f165a60bbbede717", "level": "note", "message": {"text": "Very large file: internal/catalog/item_repo.go (1641 lines)"}, "properties": {"repobilityId": "8712ba28e4adf359", "scanner": "scanner-primary", "fingerprint": "f165a60bbbede717", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-46a05b5030effd6e", "level": "note", "message": {"text": "Very large file: internal/catalog/detail.go (2795 lines)"}, "properties": {"repobilityId": "6f993286a1a85724", "scanner": "scanner-primary", "fingerprint": "46a05b5030effd6e", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-086adbdb0c4eb5f6", "level": "note", "message": {"text": "Very large file: internal/collections/templates/builtin.go (1883 lines)"}, "properties": {"repobilityId": "30678b2a133d1c73", "scanner": "scanner-primary", "fingerprint": "086adbdb0c4eb5f6", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-d1938a3fd542c1ea", "level": "note", "message": {"text": "Very large file: internal/sections/fetcher.go (3112 lines)"}, "properties": {"repobilityId": "85524dd8f7f122cc", "scanner": "scanner-primary", "fingerprint": "d1938a3fd542c1ea", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a2345ce74174e98b", "level": "note", "message": {"text": "Very large file: internal/catalogseed/service.go (2604 lines)"}, "properties": {"repobilityId": "96f6bab55761c8cc", "scanner": "scanner-primary", "fingerprint": "a2345ce74174e98b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a9d1c02a816952ef", "level": "note", "message": {"text": "Very large file: internal/watchtogether/service.go (2012 lines)"}, "properties": {"repobilityId": "e7487b72038c469a", "scanner": "scanner-primary", "fingerprint": "a9d1c02a816952ef", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a6bffd770b7834db", "level": "note", "message": {"text": "Very large file: internal/scanner/scanner.go (2801 lines)"}, "properties": {"repobilityId": "041b6f7ea1c355b7", "scanner": "scanner-primary", "fingerprint": "a6bffd770b7834db", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-f3aaff9d4a6b0ce2", "level": "note", "message": {"text": "Very large file: internal/scanner/file_repo.go (3043 lines)"}, "properties": {"repobilityId": "e30818f267b29b99", "scanner": "scanner-primary", "fingerprint": "f3aaff9d4a6b0ce2", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-b617849cd5bab5d5", "level": "note", "message": {"text": "Very large file: internal/scanner/ebook_test.go (1896 lines)"}, "properties": {"repobilityId": "7d5770c596157295", "scanner": "scanner-primary", "fingerprint": "b617849cd5bab5d5", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-ccc47f9b2c743e2b", "level": "note", "message": {"text": "Very large file: internal/metadata/service_test.go (2209 lines)"}, "properties": {"repobilityId": "a5c66183c9bb7aa5", "scanner": "scanner-primary", "fingerprint": "ccc47f9b2c743e2b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-fb26aeda82035151", "level": "note", "message": {"text": "Very large file: internal/metadata/service.go (5543 lines)"}, "properties": {"repobilityId": "20af2bf21c681e81", "scanner": "scanner-primary", "fingerprint": "fb26aeda82035151", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-e9966c122fa16e86", "level": "note", "message": {"text": "Very large file: internal/playback/transcode.go (1856 lines)"}, "properties": {"repobilityId": "c3bea9acae47bcba", "scanner": "scanner-primary", "fingerprint": "e9966c122fa16e86", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-af7d71a50e5ce35a", "level": "note", "message": {"text": "Very large file: internal/userstore/storetest/suite.go (1690 lines)"}, "properties": {"repobilityId": "7887a58b9de394fc", "scanner": "scanner-primary", "fingerprint": "af7d71a50e5ce35a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a07c9a62b46675b8", "level": "note", "message": {"text": "Very large file: internal/watchsync/service_test.go (1944 lines)"}, "properties": {"repobilityId": "1d55cfe64a47998e", "scanner": "scanner-primary", "fingerprint": "a07c9a62b46675b8", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-ce535521d3dfd938", "level": "note", "message": {"text": "Very large file: internal/watchsync/service.go (2147 lines)"}, "properties": {"repobilityId": "a85bd2496e103184", "scanner": "scanner-primary", "fingerprint": "ce535521d3dfd938", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-cde9db784632eddf", "level": "note", "message": {"text": "Very large file: cmd/silo/main.go (2651 lines)"}, "properties": {"repobilityId": "700cb35020439859", "scanner": "scanner-primary", "fingerprint": "cde9db784632eddf", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-909c70caa07cbd73", "level": "note", "message": {"text": "Very large file: web/src/player/components/VideoPlayer.tsx (2417 lines)"}, "properties": {"repobilityId": "3568b8028e65e6ae", "scanner": "scanner-primary", "fingerprint": "909c70caa07cbd73", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-c0ae2aa1791a07da", "level": "note", "message": {"text": "Very large file: web/src/api/types.ts (4063 lines)"}, "properties": {"repobilityId": "eeea0791bd6beee6", "scanner": "scanner-primary", "fingerprint": "c0ae2aa1791a07da", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-472867be3f665a1d", "level": "note", "message": {"text": "Very large file: web/src/pages/AdminHistoryImport.tsx (1373 lines)"}, "properties": {"repobilityId": "d0261c2b224511a9", "scanner": "scanner-primary", "fingerprint": "472867be3f665a1d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-164f71a9d5b66c7a", "level": "note", "message": {"text": "Very large file: web/src/pages/AdminRequests.tsx (1458 lines)"}, "properties": {"repobilityId": "70dbb3408e61c665", "scanner": "scanner-primary", "fingerprint": "164f71a9d5b66c7a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-dc9599664d5b62aa", "level": "note", "message": {"text": "Very large file: web/src/pages/AdminDevices.tsx (1800 lines)"}, "properties": {"repobilityId": "c205a69ea2367d34", "scanner": "scanner-primary", "fingerprint": "dc9599664d5b62aa", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-b0e51402d80cea5f", "level": "note", "message": {"text": "Very large file: web/src/pages/adminCollectionsShared.tsx (1712 lines)"}, "properties": {"repobilityId": "ba25532a43ad54ed", "scanner": "scanner-primary", "fingerprint": "b0e51402d80cea5f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-35c7eb19361a8b74", "level": "note", "message": {"text": "Very large file: web/src/pages/AdminLibraries.tsx (2060 lines)"}, "properties": {"repobilityId": "87e61e448b7cfbed", "scanner": "scanner-primary", "fingerprint": "35c7eb19361a8b74", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-01733c7b5333a854", "level": "note", "message": {"text": "Very large file: web/src/pages/settings/WebhookSyncSettings.tsx (1401 lines)"}, "properties": {"repobilityId": "11b06f06ac800d04", "scanner": "scanner-primary", "fingerprint": "01733c7b5333a854", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "1ed900b0374b2d82", "scanner": "scanner-primary", "fingerprint": "3ab5d313dda8e5f9", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["debug", "cleanup", "repo-hardening", "generated-repo-pattern"]}}, {"ruleId": "scanner-72b2a6250083a784", "level": "warning", "message": {"text": "Placeholder or mock-heavy implementation detected"}, "properties": {"repobilityId": "9fc937f278dca97d", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-9d79c4077342a7d0", "level": "warning", "message": {"text": "Runtime service client appears to use placeholder configuration"}, "properties": {"repobilityId": "d14a349ff2c15114", "scanner": "scanner-primary", "fingerprint": "9d79c4077342a7d0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "runtime-config", "service-client", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "46c910c50e4d66f4", "scanner": "scanner-primary", "fingerprint": "2d0c7b7ab8f8aacf", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "critical-flow", "generated-repo-pattern"]}}, {"ruleId": "scanner-ea8f3013f588db25", "level": "note", "message": {"text": "Shallow git history limits provenance confidence"}, "properties": {"repobilityId": "a8f4f1d38d1e83cc", "scanner": "scanner-primary", "fingerprint": "ea8f3013f588db25", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-8424db9c75e04ba4", "level": "none", "message": {"text": "Very short observed git history"}, "properties": {"repobilityId": "3e298d3b26cad124", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-8de13436c4db26a8", "level": "none", "message": {"text": "Commented-code block (5 lines) in scripts/dedup_audiobooks.py:51"}, "properties": {"repobilityId": "874e1bae9fa004da", "scanner": "scanner-primary", "fingerprint": "8de13436c4db26a8", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-830ab2cf3d2332d3", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/player/utils/subtitleFonts.ts:126"}, "properties": {"repobilityId": "10991d69a2f26a02", "scanner": "scanner-primary", "fingerprint": "830ab2cf3d2332d3", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-62a7a861d70d1f58", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/player/components/VideoPlayer.tsx:562"}, "properties": {"repobilityId": "7904c06371c17527", "scanner": "scanner-primary", "fingerprint": "62a7a861d70d1f58", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-80f51e5b43cff916", "level": "none", "message": {"text": "Commented-code block (6 lines) in web/src/player/hooks/usePGSSubtitles.ts:30"}, "properties": {"repobilityId": "0994cd160a6731fb", "scanner": "scanner-primary", "fingerprint": "80f51e5b43cff916", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-fd092db9dfd3783d", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/player/hooks/useASSSubtitles.test.tsx:186"}, "properties": {"repobilityId": "9628b9adcf5c5535", "scanner": "scanner-primary", "fingerprint": "fd092db9dfd3783d", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-73e39666288bbf87", "level": "none", "message": {"text": "Commented-code block (7 lines) in web/src/player/hooks/useTranscodeQuality.ts:223"}, "properties": {"repobilityId": "cbd9cd4b3f389423", "scanner": "scanner-primary", "fingerprint": "73e39666288bbf87", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-7233add4e4d2a21f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/player/hooks/useWatchProgress.ts:61"}, "properties": {"repobilityId": "5aa45fbd511c25c3", "scanner": "scanner-primary", "fingerprint": "7233add4e4d2a21f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-ff3f2b4493213a60", "level": "none", "message": {"text": "Commented-code block (6 lines) in web/src/player/hooks/useSubtitleTracks.ts:263"}, "properties": {"repobilityId": "216131b187ce1e8d", "scanner": "scanner-primary", "fingerprint": "ff3f2b4493213a60", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c4e37ee7eb12bc66", "level": "none", "message": {"text": "Commented-code block (6 lines) in web/src/player/hooks/useASSSubtitles.ts:34"}, "properties": {"repobilityId": "dd0778019b45c67d", "scanner": "scanner-primary", "fingerprint": "c4e37ee7eb12bc66", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-9d8accde7ea31109", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/api/client.ts:346"}, "properties": {"repobilityId": "45b400aa004159c4", "scanner": "scanner-primary", "fingerprint": "9d8accde7ea31109", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d2ec6fa43750b839", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/components/RealtimeEventsProvider.tsx:804"}, "properties": {"repobilityId": "49881686d91b6189", "scanner": "scanner-primary", "fingerprint": "d2ec6fa43750b839", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5d109a8fe8dcf806", "level": "none", "message": {"text": "Commented-code block (6 lines) in web/src/components/HeroBanner.tsx:84"}, "properties": {"repobilityId": "8fd2ac21ccb4a5c2", "scanner": "scanner-primary", "fingerprint": "5d109a8fe8dcf806", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-664cf387a15d72d4", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/components/ContinueWatchingCard.tsx:189"}, "properties": {"repobilityId": "429e710f9ec9fa7b", "scanner": "scanner-primary", "fingerprint": "664cf387a15d72d4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-0a5ab906b0187746", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/components/SectionRow.tsx:87"}, "properties": {"repobilityId": "3a87d786a32732a5", "scanner": "scanner-primary", "fingerprint": "0a5ab906b0187746", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5f359627131b92a3", "level": "none", "message": {"text": "Commented-code block (6 lines) in web/src/components/CollectionTemplateGallery/CollectionTemplateConfigForm.tsx:347"}, "properties": {"repobilityId": "c632eeb96682d0d4", "scanner": "scanner-primary", "fingerprint": "5f359627131b92a3", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e470ef4417a8bfec", "level": "note", "message": {"text": "Legacy-named symbol `lc_old` in web/src/components/CollectionTemplateGallery/CollectionTemplateGallery.test.tsx:314"}, "properties": {"repobilityId": "a17d9d4e21d5eb00", "scanner": "scanner-primary", "fingerprint": "e470ef4417a8bfec", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-39c8c25d9c018a69", "level": "none", "message": {"text": "Commented-code block (9 lines) in web/src/components/admin/deviceOverrides.tsx:161"}, "properties": {"repobilityId": "9723b99337f48b48", "scanner": "scanner-primary", "fingerprint": "39c8c25d9c018a69", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2c04a62593c49cc0", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/lib/permissions.ts:31"}, "properties": {"repobilityId": "4b1692ce6a58d5e0", "scanner": "scanner-primary", "fingerprint": "2c04a62593c49cc0", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a7e690404bc889a7", "level": "none", "message": {"text": "Commented-code block (6 lines) in web/src/lib/querySortOptions.ts:59"}, "properties": {"repobilityId": "10f1d32716606141", "scanner": "scanner-primary", "fingerprint": "a7e690404bc889a7", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-7958d80e6b19c536", "level": "none", "message": {"text": "Commented-code block (31 lines) in web/src/lib/design-system.ts:179"}, "properties": {"repobilityId": "33cb3d0c6022517e", "scanner": "scanner-primary", "fingerprint": "7958d80e6b19c536", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2c63546f7ef74795", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/lib/plexAuth.ts:99"}, "properties": {"repobilityId": "af509af6959811a5", "scanner": "scanner-primary", "fingerprint": "2c63546f7ef74795", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-9350df376e729864", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/lib/overlays/presets.ts:3"}, "properties": {"repobilityId": "db7559f38f78f11d", "scanner": "scanner-primary", "fingerprint": "9350df376e729864", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1bc92d3edfcf6be6", "level": "none", "message": {"text": "Commented-code block (6 lines) in web/src/lib/overlays/registry/ribbons.ts:3"}, "properties": {"repobilityId": "c5e7ec9448b0488a", "scanner": "scanner-primary", "fingerprint": "1bc92d3edfcf6be6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e7a62177b96181fa", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/pages/Collections.tsx:251"}, "properties": {"repobilityId": "c6ac6e5ebce2a540", "scanner": "scanner-primary", "fingerprint": "e7a62177b96181fa", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-48bd02bdcfd3894a", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/pages/OAuthComplete.tsx:14"}, "properties": {"repobilityId": "94bb10dc1a8022bb", "scanner": "scanner-primary", "fingerprint": "48bd02bdcfd3894a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-9e97e05b51689d8f", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/pages/LibraryPage.tsx:65"}, "properties": {"repobilityId": "93b298f4104cbba8", "scanner": "scanner-primary", "fingerprint": "9e97e05b51689d8f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1d4a508af668befa", "level": "none", "message": {"text": "Commented-code block (8 lines) in web/src/pages/AdminRequests.tsx:679"}, "properties": {"repobilityId": "583cf4542dec4228", "scanner": "scanner-primary", "fingerprint": "1d4a508af668befa", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1bff06ebce665e0a", "level": "none", "message": {"text": "Commented-code block (7 lines) in web/src/pages/AdminDevices.tsx:1164"}, "properties": {"repobilityId": "cf94e5e9c6fce6d3", "scanner": "scanner-primary", "fingerprint": "1bff06ebce665e0a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-d5035c9226ee6f76", "level": "none", "message": {"text": "Commented-code block (7 lines) in web/src/pages/ProfileCustomizeHome.tsx:31"}, "properties": {"repobilityId": "1d2573ee936e91d6", "scanner": "scanner-primary", "fingerprint": "d5035c9226ee6f76", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e73e9c4e7a39b932", "level": "none", "message": {"text": "Commented-code block (7 lines) in web/src/pages/admin-settings/BrandingSettings.tsx:28"}, "properties": {"repobilityId": "0db135cd8d0849ec", "scanner": "scanner-primary", "fingerprint": "e73e9c4e7a39b932", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-2ca5c20f19c69c9f", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/reader/readest/libs/document.ts:228"}, "properties": {"repobilityId": "655c6a640b7fc976", "scanner": "scanner-primary", "fingerprint": "2ca5c20f19c69c9f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-bca3f02041621e94", "level": "none", "message": {"text": "Commented-code block (5 lines) in web/src/hooks/queries/collections.ts:134"}, "properties": {"repobilityId": "cb3fa31d88309072", "scanner": "scanner-primary", "fingerprint": "bca3f02041621e94", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e8bf0c1f53a233c9", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 web/src/hooks/queries/admin/libraries.ts:85"}, "properties": {"repobilityId": "1733dfd26a916a98", "scanner": "scanner-primary", "fingerprint": "e8bf0c1f53a233c9", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-d0b17c8c07a7421d", "level": "note", "message": {"text": "8 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "17fe720e8247f9df", "scanner": "scanner-primary", "fingerprint": "d0b17c8c07a7421d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "config-drift"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "c297b0cd48e74482", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-1293c5d6ff4a28cd", "level": "warning", "message": {"text": "Frontend route `/login/oauth-complete` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "8e0e4d4c4a8d02f6", "scanner": "scanner-primary", "fingerprint": "1293c5d6ff4a28cd", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-c36df52adcc29f38", "level": "warning", "message": {"text": "Frontend route `/activate` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "ed3bb15fc0797f6a", "scanner": "scanner-primary", "fingerprint": "c36df52adcc29f38", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-140acc5da60aebac", "level": "warning", "message": {"text": "Frontend route `/signup` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "72ec37d60cf6a9fe", "scanner": "scanner-primary", "fingerprint": "140acc5da60aebac", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-d368f7604311fb8e", "level": "warning", "message": {"text": "Frontend route `/*` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "dcddbbc659aa63ad", "scanner": "scanner-primary", "fingerprint": "d368f7604311fb8e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-d861f7aed9b787fe", "level": "warning", "message": {"text": "Frontend route `/watch/:id` has no Link/navigate to it \u2014 web/src/pages/WatchRoute.component.test.tsx"}, "properties": {"repobilityId": "b0c65913bd91e8d4", "scanner": "scanner-primary", "fingerprint": "d861f7aed9b787fe", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-93bdeddaa820924b", "level": "warning", "message": {"text": "Frontend route `/reader/ebook/:contentId` has no Link/navigate to it \u2014 web/src/pages/EbookReader.test.tsx"}, "properties": {"repobilityId": "3a0bd2906bd567fe", "scanner": "scanner-primary", "fingerprint": "93bdeddaa820924b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-1c8e4d522b79f330", "level": "warning", "message": {"text": "Frontend route `/admin/*` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "a618a36b4ce7bbd4", "scanner": "scanner-primary", "fingerprint": "1c8e4d522b79f330", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-20edd36017ec926d", "level": "warning", "message": {"text": "Frontend route `activity` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "c0caca0aff04993f", "scanner": "scanner-primary", "fingerprint": "20edd36017ec926d", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-e344e9dcf1228e55", "level": "warning", "message": {"text": "Frontend route `logs` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "962d59ba63c75a34", "scanner": "scanner-primary", "fingerprint": "e344e9dcf1228e55", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-aa20352120955009", "level": "warning", "message": {"text": "Frontend route `maintenance` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "5972a9a2f7da1213", "scanner": "scanner-primary", "fingerprint": "aa20352120955009", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-bc766704dff857a5", "level": "warning", "message": {"text": "Frontend route `collections` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "820877483ec3ff6b", "scanner": "scanner-primary", "fingerprint": "bc766704dff857a5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-d6f29d073e392c3f", "level": "warning", "message": {"text": "Frontend route `collections/new` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "dcc95c116f2d1613", "scanner": "scanner-primary", "fingerprint": "d6f29d073e392c3f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-ebade5b710227dca", "level": "warning", "message": {"text": "Frontend route `collections/:id/edit` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "becc25461aa3f3e5", "scanner": "scanner-primary", "fingerprint": "ebade5b710227dca", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-1231de0e658a8f9f", "level": "warning", "message": {"text": "Frontend route `requests` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "25e676680d958ecf", "scanner": "scanner-primary", "fingerprint": "1231de0e658a8f9f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-aba86cf0afa08228", "level": "warning", "message": {"text": "Frontend route `autoscan` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "47656f9a1ff53648", "scanner": "scanner-primary", "fingerprint": "aba86cf0afa08228", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-f39b9f6a9d13c086", "level": "warning", "message": {"text": "Frontend route `history` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "7cbbc55aa4b0de04", "scanner": "scanner-primary", "fingerprint": "f39b9f6a9d13c086", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-e1ad599d38ef05f8", "level": "warning", "message": {"text": "Frontend route `marker-history` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "5e8de4774829cfaf", "scanner": "scanner-primary", "fingerprint": "e1ad599d38ef05f8", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-11b2684a442d3153", "level": "warning", "message": {"text": "Frontend route `users` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "119c3a17cedd2fcf", "scanner": "scanner-primary", "fingerprint": "11b2684a442d3153", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-f4a131417b2c7a04", "level": "warning", "message": {"text": "Frontend route `users/:id` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "44386bb9a1a8e8a3", "scanner": "scanner-primary", "fingerprint": "f4a131417b2c7a04", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-231a99f177a79e97", "level": "warning", "message": {"text": "Frontend route `devices` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "e85665eca519ab6c", "scanner": "scanner-primary", "fingerprint": "231a99f177a79e97", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-762432e309fc26a1", "level": "warning", "message": {"text": "Frontend route `devices/:userId/:deviceId` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "d284e6a731a9c883", "scanner": "scanner-primary", "fingerprint": "762432e309fc26a1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-a666ef09c03ea030", "level": "warning", "message": {"text": "Frontend route `nodes` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "e265a2d268d58da0", "scanner": "scanner-primary", "fingerprint": "a666ef09c03ea030", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-c182b49fbebd8f09", "level": "warning", "message": {"text": "Frontend route `sections` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "ed3904dcecb778d6", "scanner": "scanner-primary", "fingerprint": "c182b49fbebd8f09", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-6ae280707dbadf3f", "level": "warning", "message": {"text": "Frontend route `plugins` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "2472455842d4c29e", "scanner": "scanner-primary", "fingerprint": "6ae280707dbadf3f", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-88cf01eced5e2d03", "level": "warning", "message": {"text": "Frontend route `settings` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "0b7abb0a2f12db9d", "scanner": "scanner-primary", "fingerprint": "88cf01eced5e2d03", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-be24191a6de828fe", "level": "warning", "message": {"text": "Frontend route `recommendations` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "9384c90541460ffb", "scanner": "scanner-primary", "fingerprint": "be24191a6de828fe", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-446754b3ab8c8944", "level": "warning", "message": {"text": "Frontend route `api-keys` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "905f864fcded7082", "scanner": "scanner-primary", "fingerprint": "446754b3ab8c8944", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-1b09ff635eebea0a", "level": "warning", "message": {"text": "Frontend route `subtitles` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "1ce842b23452a396", "scanner": "scanner-primary", "fingerprint": "1b09ff635eebea0a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-c409e623e39e9533", "level": "warning", "message": {"text": "Frontend route `tasks` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "b79e0537fe65d22c", "scanner": "scanner-primary", "fingerprint": "c409e623e39e9533", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-0ea43e2388ebfdab", "level": "warning", "message": {"text": "Frontend route `tasks/:key` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "7ce525e201a67df2", "scanner": "scanner-primary", "fingerprint": "0ea43e2388ebfdab", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-cadd0e76955b661a", "level": "warning", "message": {"text": "Frontend route `stats` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "db8ca7dd5d9b6e35", "scanner": "scanner-primary", "fingerprint": "cadd0e76955b661a", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-2d60b9b56cbd5729", "level": "warning", "message": {"text": "Frontend route `/settings/*` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "642410b90e2425b7", "scanner": "scanner-primary", "fingerprint": "2d60b9b56cbd5729", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-03592e083bd3814b", "level": "warning", "message": {"text": "Frontend route `plex-webhooks` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "60bad5e62ee12c97", "scanner": "scanner-primary", "fingerprint": "03592e083bd3814b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-6fcf4a27b8598a9e", "level": "warning", "message": {"text": "Frontend route `/catalog` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "f8c6eeabd07d62f2", "scanner": "scanner-primary", "fingerprint": "6fcf4a27b8598a9e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-7f69614adf386202", "level": "warning", "message": {"text": "Frontend route `/library/:libraryId` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "e23a6d448bff222f", "scanner": "scanner-primary", "fingerprint": "7f69614adf386202", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-02520f191bf5157e", "level": "warning", "message": {"text": "Frontend route `/search` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "3db78d7b2def04f2", "scanner": "scanner-primary", "fingerprint": "02520f191bf5157e", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-96a949112c653352", "level": "warning", "message": {"text": "Frontend route `/browse` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "984eed2740adcde5", "scanner": "scanner-primary", "fingerprint": "96a949112c653352", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-ced46130dbfa6dee", "level": "warning", "message": {"text": "Frontend route `/item/:id` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "fe5847b7492a6aa1", "scanner": "scanner-primary", "fingerprint": "ced46130dbfa6dee", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-079d76fb1be1afe5", "level": "warning", "message": {"text": "Frontend route `/person/:id` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "b736662efc1f53e9", "scanner": "scanner-primary", "fingerprint": "079d76fb1be1afe5", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-7930eb3548edc83c", "level": "warning", "message": {"text": "Frontend route `/rooms/:roomId` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "7a55ed73b516822c", "scanner": "scanner-primary", "fingerprint": "7930eb3548edc83c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-0aadbf98f0f45ba0", "level": "warning", "message": {"text": "Frontend route `/favorites` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "a14b592ebff2ab2c", "scanner": "scanner-primary", "fingerprint": "0aadbf98f0f45ba0", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-12fb0dad41526043", "level": "warning", "message": {"text": "Frontend route `/watchlist` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "33b98302e212617b", "scanner": "scanner-primary", "fingerprint": "12fb0dad41526043", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-0afa231a717c83ab", "level": "warning", "message": {"text": "Frontend route `/history` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "426d8dfe0af0253c", "scanner": "scanner-primary", "fingerprint": "0afa231a717c83ab", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-bfd1f189cffaa936", "level": "warning", "message": {"text": "Frontend route `/collections/new` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "50e4b44ee114b89f", "scanner": "scanner-primary", "fingerprint": "bfd1f189cffaa936", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-342c6f4671568980", "level": "warning", "message": {"text": "Frontend route `/collections/:id/edit` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "5bdb53a371a24e22", "scanner": "scanner-primary", "fingerprint": "342c6f4671568980", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-667f9eed74ead38c", "level": "warning", "message": {"text": "Frontend route `/collections/:id` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "00d826e897d9c86b", "scanner": "scanner-primary", "fingerprint": "667f9eed74ead38c", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-7d013c4311929a51", "level": "warning", "message": {"text": "Frontend route `/requests/:mediaType/:tmdbId` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "72c9fb56452bef32", "scanner": "scanner-primary", "fingerprint": "7d013c4311929a51", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-24962dca4a3e01c4", "level": "warning", "message": {"text": "Frontend route `/requests/browse/studio/:slug` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "d7be6f601555fbe8", "scanner": "scanner-primary", "fingerprint": "24962dca4a3e01c4", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-ff1c78ab8e967677", "level": "warning", "message": {"text": "Frontend route `/requests/browse/network/:slug` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "96fbe81b591b0bcc", "scanner": "scanner-primary", "fingerprint": "ff1c78ab8e967677", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-7a584f199677ac53", "level": "warning", "message": {"text": "Frontend route `/requests/browse/genre/:slug` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "5baa9959c93feb19", "scanner": "scanner-primary", "fingerprint": "7a584f199677ac53", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-44d30f78fa22c203", "level": "warning", "message": {"text": "Frontend route `/recommendations/section/:kind` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "ba177db5b7f5fa2d", "scanner": "scanner-primary", "fingerprint": "44d30f78fa22c203", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-39cc2347c30e896b", "level": "warning", "message": {"text": "Frontend route `/recommendations/section/:kind/:key` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "bac0f3edc417ee47", "scanner": "scanner-primary", "fingerprint": "39cc2347c30e896b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-bdd4a80a38b42ebd", "level": "warning", "message": {"text": "Frontend route `/profile/customize-home` has no Link/navigate to it \u2014 web/src/App.tsx"}, "properties": {"repobilityId": "a4821a819134f99c", "scanner": "scanner-primary", "fingerprint": "bdd4a80a38b42ebd", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}]}]}