{"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-c21eae8a3d3aae40", "name": "Possibly dead Python function: position_from_preflop_actions", "shortDescription": {"text": "Possibly dead Python function: position_from_preflop_actions"}, "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-871c48d9eb894b30", "name": "Possibly dead Python function: build_app_url", "shortDescription": {"text": "Possibly dead Python function: build_app_url"}, "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-6e7222468b41e6ad", "name": "Possibly dead Python function: load_cookies", "shortDescription": {"text": "Possibly dead Python function: load_cookies"}, "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-b5b75bd62be929e7", "name": "Possibly dead Python function: do_login", "shortDescription": {"text": "Possibly dead Python function: do_login"}, "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-a7ea3bf9d7541f3a", "name": "Possibly dead Python function: build_preflop_actions_simple", "shortDescription": {"text": "Possibly dead Python function: build_preflop_actions_simple"}, "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-2ea49e4ac5554d11", "name": "Possibly dead Python function: matcher", "shortDescription": {"text": "Possibly dead Python function: matcher"}, "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-3e2ddab13fd3387d", "name": "Possibly dead Python function: log_message", "shortDescription": {"text": "Possibly dead Python function: log_message"}, "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-6786ea3de5bfb14c", "name": "Possibly dead Python function: do_GET", "shortDescription": {"text": "Possibly dead Python function: do_GET"}, "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-933e8ce97737c20f", "name": "Possibly dead Python function: do_POST", "shortDescription": {"text": "Possibly dead Python function: do_POST"}, "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-6d2278e70323cdf4", "name": "Possibly dead Python function: ph", "shortDescription": {"text": "Possibly dead Python function: ph"}, "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-0dc3e2c58d87f439", "name": "Possibly dead Python function: placeholders", "shortDescription": {"text": "Possibly dead Python function: placeholders"}, "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-b99f41eb1e64ce35", "name": "Possibly dead Python function: resync_gto_labels_for_node", "shortDescription": {"text": "Possibly dead Python function: resync_gto_labels_for_node"}, "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-8395fdb6a1721efa", "name": "Possibly dead Python function: is_divergent", "shortDescription": {"text": "Possibly dead Python function: is_divergent"}, "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-800831fa7b3cd278", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/ui/chart.tsx:70", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/ui/chart.tsx:70"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-89d574f1e2dc78b3", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/CognitiveFailureCard.tsx:41", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/CognitiveFailureCard.tsx:41"}, "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-abba8f6fdd33f618", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/CareerGraphCard.tsx:425", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/CareerGraphCard.tsx:425"}, "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-509b966463a17e1c", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/DecisionQualityCard.tsx:71", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/DecisionQualityCard.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-84fbd12631b6c3da", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/V2CognitiveCard.tsx:46", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/V2CognitiveCard.tsx:46"}, "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-8e76e9f6bf8163d3", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/PokerTable.tsx:150", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/PokerTable.tsx:150"}, "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-4c7c9c945e4443e9", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/HudHeader.tsx:303", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/HudHeader.tsx:303"}, "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-b8a07c2b381c37e9", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/StrategicTwinCard.tsx:34", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/StrategicTwinCard.tsx:34"}, "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-365c49a8ce360d5f", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/RecentTournamentsTable.tsx:98", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/RecentTournamentsTable.tsx:98"}, "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-a1fdb3d7764dcf74", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/DailyFocusCard.tsx:61", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/DailyFocusCard.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-958bc4deb19b53b5", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/LeakFinderCard.tsx:63", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/LeakFinderCard.tsx:63"}, "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-cedc9d850885ea5a", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/V2TwinCard.tsx:33", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/V2TwinCard.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-8634774e9a08d7e3", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/GtoQualityCard.tsx:88", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/GtoQualityCard.tsx:88"}, "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-6c976e23e710232b", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/GtoAlignmentCard.tsx:125", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/GtoAlignmentCard.tsx:125"}, "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-ff32713133085842", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/V2QualityCard.tsx:79", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/V2QualityCard.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-48ab4f7ad8d7ebf9", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/UploadQueue.tsx:93", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/UploadQueue.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-03e3d82cec32e113", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/GtoPositionCard.tsx:107", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/GtoPositionCard.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-8fdd8ca33c27a3db", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/LevelCard.tsx:124", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/LevelCard.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-f806c34d4ae52892", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Tournaments.tsx:311", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Tournaments.tsx:311"}, "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-1137aadea2be1d5c", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/TournamentCompare.tsx:124", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/TournamentCompare.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-1db2bf66dc6068c5", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/StudentProfile.tsx:147", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/StudentProfile.tsx:147"}, "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-55ef47fe75fde900", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Replayer.tsx:1289", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Replayer.tsx:1289"}, "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-2f812ebdb1f7a54b", "name": "Stray `console.log` in TS/JS \u2014 frontend/src/pages/Replayer.tsx:1650", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 frontend/src/pages/Replayer.tsx:1650"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-7c69a69e5b543807", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/CoachesDirectory.tsx:66", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/CoachesDirectory.tsx:66"}, "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-85544ab96dbf1324", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/pages/DocsRating.tsx:10", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/pages/DocsRating.tsx:10"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-23762336110cdb6f", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Sparring.tsx:706", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Sparring.tsx:706"}, "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-6fca59c42a6f46f0", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/PublicCoachProfile.tsx:335", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/PublicCoachProfile.tsx:335"}, "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-24c4313e6ead0dd7", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/GhostTable.tsx:399", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/GhostTable.tsx:399"}, "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-6afdce1054e29da8", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Docs.tsx:77", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Docs.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-3b5ddc88f3439f0a", "name": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/pages/Docs.tsx:194", "shortDescription": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/pages/Docs.tsx:194"}, "fullDescription": {"text": "Open XSS surface unless the input is provably trusted. Replace with explicit JSX or sanitize via a vetted library.\n\nWhy: OWASP basics. Already partially flagged by the security analyzer.\nRule id: fq.dangerous-html"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-b01759e3ffb98f1f", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Leaderboard.tsx:44", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Leaderboard.tsx:44"}, "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-d3cfe70d0ea56c16", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/StudyPlan.tsx:85", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/StudyPlan.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-7030e48761039002", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/AICoach.tsx:287", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/AICoach.tsx:287"}, "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-8d83619ed743eb15", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/admin/AdminDashboard.tsx:119", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/admin/AdminDashboard.tsx:119"}, "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-5dc8817c74b5c4df", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/coach/StudentDetail.tsx:200", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/coach/StudentDetail.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-29891483997f1b6a", "name": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/coach/CoachDashboard.tsx:125", "shortDescription": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/coach/CoachDashboard.tsx:125"}, "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-83d9e633e5ead2f1", "name": "Stray `console.log` in TS/JS \u2014 backend/scripts/gto_validation/console_script.js:523", "shortDescription": {"text": "Stray `console.log` in TS/JS \u2014 backend/scripts/gto_validation/console_script.js:523"}, "fullDescription": {"text": "Replace with the toast helper, an error boundary, or remove. `console.warn` / `console.error` are acceptable.\n\nWhy: Hygiene \u2014 easy to leak debug output.\nRule id: fq.console-leak"}, "properties": {"scanner": "scanner-primary", "layer": "frontend", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f6cd08fa8d1eb4b0", "name": "Analyzer timeout: security.gitleaks", "shortDescription": {"text": "Analyzer timeout: security.gitleaks"}, "fullDescription": {"text": "analyzer exceeded 60.0s wall-clock (thread mode \u2014 daemon abandoned). Bump REPOBILITY_ANALYZER_TIMEOUT_S if expected."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-503686fa1d081418", "name": "Privileged port 42 in use", "shortDescription": {"text": "Privileged port 42 in use"}, "fullDescription": {"text": "Port 42 is privileged (<1024). Make sure the service runs with the right caps or front it with a non-privileged port via a load balancer."}, "properties": {"scanner": "scanner-primary", "layer": "network", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-1f66ad88286ca30a", "name": "Dockerfile runs as root: backend/Dockerfile", "shortDescription": {"text": "Dockerfile runs as root: backend/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-8cd20d539467d2c5", "name": "Docker base image is tag-pinned but not digest-pinned: python:3.11-slim", "shortDescription": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.11-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-8d282e31e9bc7a78", "name": "Runtime dotenv file present in repo: frontend/.env", "shortDescription": {"text": "Runtime dotenv file present in repo: frontend/.env"}, "fullDescription": {"text": "`frontend/.env` looks like a runtime dotenv file. No high-confidence secret value was matched, but runtime dotenv files often drift into live credentials. Move real values to a secret manager and keep only `.env.example` style templates in source control."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "high", "confidence": 1.0}}, {"id": "scanner-2a26d405619326a1", "name": "Insecure pattern 'direct_innerhtml_assignment' in frontend/leaklab-replayer-v3.html:710", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/leaklab-replayer-v3.html:710"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-045798e982aa56ad", "name": "Insecure pattern 'direct_innerhtml_assignment' in frontend/index.legacy.html:899", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/index.legacy.html:899"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-5a5a632de13abfd7", "name": "Insecure pattern 'local_storage_auth_token' in frontend/index.legacy.html:2069", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/index.legacy.html:2069"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-2c8914bada65590c", "name": "Insecure pattern 'direct_innerhtml_assignment' in frontend/leaklab-replayer-v4.html:692", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/leaklab-replayer-v4.html:692"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-571b8a04eaecbfb3", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/faces_squeeze_card_shots.mjs:21", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/faces_squeeze_card_shots.mjs:21"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4be17ef28dc35f3a", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/pf_uncov_shots.mjs:15", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/pf_uncov_shots.mjs:15"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-93bfd61fd8d8629d", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs_shove_card_shots.mjs:17", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs_shove_card_shots.mjs:17"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-dd192790506b29cb", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs3bet_card_shots.mjs:21", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs3bet_card_shots.mjs:21"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-dae277e50e4ea7df", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vsrfi_fresh_shots.mjs:15", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vsrfi_fresh_shots.mjs:15"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ae093bfdbbeb8e13", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/pushfold_card_shots.mjs:17", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/pushfold_card_shots.mjs:17"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a04696b5dfd34720", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/postflop_card_shots.mjs:16", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/postflop_card_shots.mjs:16"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-9bc9fa7f5090cf38", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs4bet_card_shots.mjs:17", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs4bet_card_shots.mjs:17"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-51f15e9571a54257", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/replayer_shots.mjs:33", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/replayer_shots.mjs:33"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-4f4d58df3af64f71", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/limp_card_shots.mjs:17", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/limp_card_shots.mjs:17"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f5a0317af4c1b55b", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/turn_card_shots.mjs:17", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/turn_card_shots.mjs:17"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-11d4ae4708ee6fb2", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/mobile_shots.mjs:13", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/mobile_shots.mjs:13"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ed78303535497af9", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/rangepanel_shots.mjs:15", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/rangepanel_shots.mjs:15"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ff017c7b1f1ad72a", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/rfi_card_shots.mjs:17", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/rfi_card_shots.mjs:17"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-354fedde557ef376", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/squeeze_card_shots.mjs:16", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/squeeze_card_shots.mjs:16"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-ef77cea862647792", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs_rfi_card_shots.mjs:16", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs_rfi_card_shots.mjs:16"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-c0e36abd00968855", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/multiway_card_shots.mjs:17", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/multiway_card_shots.mjs:17"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-81788c5a051db4a5", "name": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/river_card_shots.mjs:17", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/river_card_shots.mjs:17"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-a306d70c7e47b967", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/ui/chart.tsx:70", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/ui/chart.tsx:70"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-72afaf67ffaf524e", "name": "Insecure pattern 'direct_innerhtml_assignment' in frontend/src/components/hud/PokerTableV3.tsx:521", "shortDescription": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/src/components/hud/PokerTableV3.tsx:521"}, "fullDescription": {"text": "Found a known-risky pattern (direct_innerhtml_assignment). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-26e3d57bf56c8c13", "name": "Insecure pattern 'local_storage_auth_token' in frontend/src/lib/auth.tsx:34", "shortDescription": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/src/lib/auth.tsx:34"}, "fullDescription": {"text": "Found a known-risky pattern (local_storage_auth_token). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-e87db8c3f412c580", "name": "Insecure pattern 'dangerous_innerhtml' in frontend/src/pages/Docs.tsx:194", "shortDescription": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/pages/Docs.tsx:194"}, "fullDescription": {"text": "Found a known-risky pattern (dangerous_innerhtml). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-f87a3288747a6c1d", "name": "Insecure pattern 'debug_true' in backend/api/app.py:7436", "shortDescription": {"text": "Insecure pattern 'debug_true' in backend/api/app.py:7436"}, "fullDescription": {"text": "Found a known-risky pattern (debug_true). Review and replace if possible."}, "properties": {"scanner": "scanner-primary", "layer": "security", "severity": "low", "confidence": 1.0}}, {"id": "scanner-665b48455dd120b7", "name": "Insecure pattern 'cors_wildcard' in backend/api/app.py:209", "shortDescription": {"text": "Insecure pattern 'cors_wildcard' in backend/api/app.py:209"}, "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-e6670f32b5bd9075", "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-c11cf013845a07f0", "name": "Very large file: frontend/src/lib/api.ts (2308 lines)", "shortDescription": {"text": "Very large file: frontend/src/lib/api.ts (2308 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-d9193bfbb7a79114", "name": "Very large file: frontend/src/pages/HandBuilder.tsx (1246 lines)", "shortDescription": {"text": "Very large file: frontend/src/pages/HandBuilder.tsx (1246 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-68c4fa18d1396d7b", "name": "Very large file: frontend/src/pages/Replayer.tsx (2024 lines)", "shortDescription": {"text": "Very large file: frontend/src/pages/Replayer.tsx (2024 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-30a071f30d83b515", "name": "Very large file: frontend/src/pages/GhostTable.tsx (1131 lines)", "shortDescription": {"text": "Very large file: frontend/src/pages/GhostTable.tsx (1131 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-b7335146c3601bda", "name": "Very large file: frontend/src/pages/admin/AdminDashboard.tsx (1241 lines)", "shortDescription": {"text": "Very large file: frontend/src/pages/admin/AdminDashboard.tsx (1241 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-55f4946de37a4227", "name": "Very large file: frontend/src/pages/coach/StudentDetail.tsx (1695 lines)", "shortDescription": {"text": "Very large file: frontend/src/pages/coach/StudentDetail.tsx (1695 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-03aa1d7857da438d", "name": "Very large file: frontend/src/pages/coach/CoachDashboard.tsx (1364 lines)", "shortDescription": {"text": "Very large file: frontend/src/pages/coach/CoachDashboard.tsx (1364 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-a58a699a3f0a00e5", "name": "Very large file: backend/api/app.py (7436 lines)", "shortDescription": {"text": "Very large file: backend/api/app.py (7436 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-b63f6e84f63b3130", "name": "Very large file: backend/gto_bot/solver_api/server.py (1358 lines)", "shortDescription": {"text": "Very large file: backend/gto_bot/solver_api/server.py (1358 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-bae22e76346288ce", "name": "Very large file: backend/database/schema.py (1637 lines)", "shortDescription": {"text": "Very large file: backend/database/schema.py (1637 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-5b677d4683a9f13a", "name": "Very large file: backend/database/repositories.py (6948 lines)", "shortDescription": {"text": "Very large file: backend/database/repositories.py (6948 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-32e0bf00bc420f5e", "name": "Very large file: backend/leaklab/preflop_gto_ranges.py (1327 lines)", "shortDescription": {"text": "Very large file: backend/leaklab/preflop_gto_ranges.py (1327 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-0063b7b8c10d8b36", "name": "Very large file: backend/leaklab/llm_explainer.py (2886 lines)", "shortDescription": {"text": "Very large file: backend/leaklab/llm_explainer.py (2886 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-fd49a97369cdcab5", "name": "Very large file: backend/leaklab/academy.py (1307 lines)", "shortDescription": {"text": "Very large file: backend/leaklab/academy.py (1307 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-c3baf052fbdb6df1", "name": "Very large file: backend/leaklab/decision_engine_v11.py (1181 lines)", "shortDescription": {"text": "Very large file: backend/leaklab/decision_engine_v11.py (1181 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-ea3b5e389d8c9c0f", "name": "Low test-to-source ratio", "shortDescription": {"text": "Low test-to-source ratio"}, "fullDescription": {"text": "75 tests / 425 src (ratio 0.18)."}, "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 1754 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 131 placeholder/mock markers across 38 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-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-51a2afab6ca294e1", "name": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/replayer/RangePanel.tsx:17", "shortDescription": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/replayer/RangePanel.tsx:17"}, "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-e81dc82d57550202", "name": "Commented-code block (8 lines) in frontend/src/components/hud/PokerTableV3.tsx:208", "shortDescription": {"text": "Commented-code block (8 lines) in frontend/src/components/hud/PokerTableV3.tsx:208"}, "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-87d19055c6947e65", "name": "Commented-code block (5 lines) in frontend/src/components/hud/DashboardV2.tsx:47", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/components/hud/DashboardV2.tsx:47"}, "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-1cce3ad201f35456", "name": "Commented-code block (5 lines) in frontend/src/lib/hhImport.ts:1", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/lib/hhImport.ts:1"}, "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-d884838dd33b1c3b", "name": "Commented-code block (5 lines) in frontend/src/pages/Replayer.tsx:152", "shortDescription": {"text": "Commented-code block (5 lines) in frontend/src/pages/Replayer.tsx:152"}, "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-e6d68189c53f500f", "name": "Commented-code block (6 lines) in frontend/src/hooks/useDashboardLayout.ts:21", "shortDescription": {"text": "Commented-code block (6 lines) in frontend/src/hooks/useDashboardLayout.ts:21"}, "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-3ada643d8d9681c7", "name": "Commented-code block (6 lines) in backend/tests/test_postflop_evaluator.py:257", "shortDescription": {"text": "Commented-code block (6 lines) in backend/tests/test_postflop_evaluator.py:257"}, "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-55da378cc9381831", "name": "Legacy-named symbol `test_study_plan_cache_key_v2` in backend/tests/test_study_plan.py:114", "shortDescription": {"text": "Legacy-named symbol `test_study_plan_cache_key_v2` in backend/tests/test_study_plan.py:114"}, "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-1ba6be38a4c2e362", "name": "Commented-code block (5 lines) in backend/tests/test_recent_regressions.py:93", "shortDescription": {"text": "Commented-code block (5 lines) in backend/tests/test_recent_regressions.py:93"}, "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-b11e42bbdeea6a7e", "name": "Legacy-named symbol `coach_students_v2` in backend/api/app.py:2061", "shortDescription": {"text": "Legacy-named symbol `coach_students_v2` in backend/api/app.py:2061"}, "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-674b674c9444a8d3", "name": "Commented-code block (6 lines) in backend/api/app.py:1419", "shortDescription": {"text": "Commented-code block (6 lines) in backend/api/app.py:1419"}, "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-7462d2c23f3d9e4a", "name": "Commented-code block (5 lines) in backend/docs/external_ranges/greenline_ranges.ts:338", "shortDescription": {"text": "Commented-code block (5 lines) in backend/docs/external_ranges/greenline_ranges.ts:338"}, "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-532866daef32db19", "name": "Legacy-named symbol `purged_solver_cli_nodes_backup` in backend/scripts/postflop_correctness_audit.py:115", "shortDescription": {"text": "Legacy-named symbol `purged_solver_cli_nodes_backup` in backend/scripts/postflop_correctness_audit.py:115"}, "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-d9c6397ae4c6a78a", "name": "Commented-code block (6 lines) in backend/scripts/build_coach_review_t27.py:19", "shortDescription": {"text": "Commented-code block (6 lines) in backend/scripts/build_coach_review_t27.py:19"}, "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-1f39d34415815252", "name": "Legacy-named symbol `parse_spot_v2` in backend/scripts/parse_gw_har.py:46", "shortDescription": {"text": "Legacy-named symbol `parse_spot_v2` in backend/scripts/parse_gw_har.py:46"}, "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-4b0244a4a7787f5b", "name": "Commented-code block (10 lines) in backend/scripts/parse_gw_har.py:242", "shortDescription": {"text": "Commented-code block (10 lines) in backend/scripts/parse_gw_har.py:242"}, "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-ba02bd092bf9c50b", "name": "Commented-code block (5 lines) in backend/scripts/seed_preflop_gw.py:155", "shortDescription": {"text": "Commented-code block (5 lines) in backend/scripts/seed_preflop_gw.py:155"}, "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-1b8d144d3fcadfba", "name": "Commented-code block (6 lines) in backend/scripts/scan_card_invariants.py:270", "shortDescription": {"text": "Commented-code block (6 lines) in backend/scripts/scan_card_invariants.py:270"}, "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-7863e28e09f4e9d1", "name": "Network/subprocess call without timeout or try/except \u2014 backend/scripts/gto_validation/playwright_compare.py:583", "shortDescription": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/scripts/gto_validation/playwright_compare.py:583"}, "fullDescription": {"text": "`subprocess.Popen(...)` here lacks both a `timeout=` arg and an enclosing try/except. This is exactly the class of bug that took down our git-clone earlier (HTTP/2 stream cancel surfaced as a fatal). Add a `timeout=` and wrap in try/except, or use a wrapper that retries."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "medium", "confidence": 1.0}}, {"id": "scanner-262ff8dd20cd1903", "name": "Commented-code block (7 lines) in backend/scripts/gto_validation/console_script.js:5", "shortDescription": {"text": "Commented-code block (7 lines) in backend/scripts/gto_validation/console_script.js:5"}, "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-c0ca2523246e3ae0", "name": "Commented-code block (7 lines) in backend/gto_bot/solver_api/_gw_subprocess.py:36", "shortDescription": {"text": "Commented-code block (7 lines) in backend/gto_bot/solver_api/_gw_subprocess.py:36"}, "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-c34bf086c954c97f", "name": "Commented-code block (6 lines) in backend/gto_bot/solver_api/server.py:728", "shortDescription": {"text": "Commented-code block (6 lines) in backend/gto_bot/solver_api/server.py:728"}, "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-50edb7ec16691027", "name": "Stub function `log_message` (body is just `pass`/`return`) \u2014 backend/gto_bot/solver_api/server.py:1232", "shortDescription": {"text": "Stub function `log_message` (body is just `pass`/`return`) \u2014 backend/gto_bot/solver_api/server.py:1232"}, "fullDescription": {"text": "Likely an AI scaffold that was never filled in. Remove or implement."}, "properties": {"scanner": "scanner-primary", "layer": "quality", "severity": "low", "confidence": 1.0}}, {"id": "scanner-68c745da7bc7206a", "name": "Legacy-named symbol `is_legacy` in backend/database/repositories.py:106", "shortDescription": {"text": "Legacy-named symbol `is_legacy` in backend/database/repositories.py:106"}, "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-0a546f25a3155600", "name": "Commented-code block (5 lines) in backend/leaklab/gto_utils.py:18", "shortDescription": {"text": "Commented-code block (5 lines) in backend/leaklab/gto_utils.py:18"}, "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-9a067178fce79c97", "name": "Commented-code block (5 lines) in backend/leaklab/parser.py:15", "shortDescription": {"text": "Commented-code block (5 lines) in backend/leaklab/parser.py:15"}, "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-a330e0a24cba2805", "name": "Commented-code block (6 lines) in backend/leaklab/preflop_gto_ranges.py:192", "shortDescription": {"text": "Commented-code block (6 lines) in backend/leaklab/preflop_gto_ranges.py:192"}, "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-024eaaf6e09c9e51", "name": "Commented-code block (7 lines) in backend/leaklab/hand_state_builder.py:6", "shortDescription": {"text": "Commented-code block (7 lines) in backend/leaklab/hand_state_builder.py:6"}, "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-98b766411268112b", "name": "Legacy-named symbol `study_plan_agentic_v1` in backend/leaklab/llm_explainer.py:1401", "shortDescription": {"text": "Legacy-named symbol `study_plan_agentic_v1` in backend/leaklab/llm_explainer.py:1401"}, "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-3483674361f53abc", "name": "Commented-code block (8 lines) in backend/leaklab/llm_explainer.py:1229", "shortDescription": {"text": "Commented-code block (8 lines) in backend/leaklab/llm_explainer.py:1229"}, "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-dad2190bb1e2d1a3", "name": "Commented-code block (5 lines) in backend/leaklab/icm.py:110", "shortDescription": {"text": "Commented-code block (5 lines) in backend/leaklab/icm.py:110"}, "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-78d85e8a57f6c0c4", "name": "Commented-code block (8 lines) in backend/leaklab/gto_solver.py:329", "shortDescription": {"text": "Commented-code block (8 lines) in backend/leaklab/gto_solver.py:329"}, "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-5f3b240bd6a66cb6", "name": "Commented-code block (6 lines) in backend/leaklab/elo_engine.py:44", "shortDescription": {"text": "Commented-code block (6 lines) in backend/leaklab/elo_engine.py:44"}, "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-c1f9c699b4fb1850", "name": "Commented-code block (5 lines) in backend/leaklab/street_math_engine.py:4", "shortDescription": {"text": "Commented-code block (5 lines) in backend/leaklab/street_math_engine.py:4"}, "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-8092cecfc721b285", "name": "Legacy-named symbol `digest_unsub_v1` in backend/leaklab/email_digest.py:31", "shortDescription": {"text": "Legacy-named symbol `digest_unsub_v1` in backend/leaklab/email_digest.py:31"}, "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-0ba4c663a25fd04c", "name": "Commented-code block (5 lines) in backend/leaklab/decision_engine_v11.py:93", "shortDescription": {"text": "Commented-code block (5 lines) in backend/leaklab/decision_engine_v11.py:93"}, "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-0cebe82322e3eb91", "name": "Commented-code block (6 lines) in backend/leaklab/revalidation/differ.py:231", "shortDescription": {"text": "Commented-code block (6 lines) in backend/leaklab/revalidation/differ.py:231"}, "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-eab8b6346c2579e8", "name": "57 env vars used in code but missing from .env.example", "shortDescription": {"text": "57 env vars used in code but missing from .env.example"}, "fullDescription": {"text": "Drift between code and config docs. The first few: `ALLOWED_ORIGINS`, `ANTHROPIC_API_KEY`, `APP_BASE_URL`, `CDP_PORT`, `COACH_CHAT_AGENTIC`, `DATABASE_URL`, `DEEP_DIVE_AGENTIC`, `DIGEST_FROM` + 49 more. 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:\nbackend/api/app.py:history_tournaments, backend/api/app.py:history_tournament\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-be46ea126aa5d8dc", "name": "Near-duplicate function bodies in 3 places", "shortDescription": {"text": "Near-duplicate function bodies in 3 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/scripts/sync_gto_labels_from_ranges.py:parse_cards, backend/scripts/sync_gto_labels_from_solver.py:parse_cards, backend/scripts/list_uncovered_vsrfi.py:parse_cards\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-49c98f7cedd9c977", "name": "Near-duplicate function bodies in 4 places", "shortDescription": {"text": "Near-duplicate function bodies in 4 places"}, "fullDescription": {"text": "Functions with the same first-5-line body hash:\nbackend/scripts/gto_validation/playwright_compare.py:on_req, backend/scripts/gto_validation/playwright_compare.py:on_req, backend/scripts/gto_validation/_probe_gametypes.py:on_req, backend/scripts/gto_validation/smoke_test_multiway.py:on_req\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-c0ab9a5671bb3326", "name": "Frontend route `/tournaments/compare` has no Link/navigate to it \u2014 frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/tournaments/compare` has no Link/navigate to it \u2014 frontend/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-9341a9e16d6eee60", "name": "Frontend route `/tournaments/:id` has no Link/navigate to it \u2014 frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/tournaments/:id` has no Link/navigate to it \u2014 frontend/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-d2ffd2fe4f714d43", "name": "Frontend route `/replayer` has no Link/navigate to it \u2014 frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/replayer` has no Link/navigate to it \u2014 frontend/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-0329a9f3cf9d456b", "name": "Frontend route `/coach-dashboard/student/:id` has no Link/navigate to it \u2014 frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/coach-dashboard/student/:id` has no Link/navigate to it \u2014 frontend/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-12d327c7dc9ff393", "name": "Frontend route `/coaches/:id` has no Link/navigate to it \u2014 frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/coaches/:id` has no Link/navigate to it \u2014 frontend/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-d73e1d073c651498", "name": "Frontend route `/academy/gto-preflop` has no Link/navigate to it \u2014 frontend/src/App.tsx", "shortDescription": {"text": "Frontend route `/academy/gto-preflop` has no Link/navigate to it \u2014 frontend/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-59ebce5eb3747afe", "name": "Dangling fetch: GET /replay/${tournamentId}/${handId} (frontend/src/lib/api.ts:444)", "shortDescription": {"text": "Dangling fetch: GET /replay/${tournamentId}/${handId} (frontend/src/lib/api.ts:444)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:444` calls `GET /replay/${tournamentId}/${handId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/replay/<p>/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-3ffda38b37343ef7", "name": "Dangling fetch: POST /player/hands/${handId}/request-gto (frontend/src/lib/api.ts:447)", "shortDescription": {"text": "Dangling fetch: POST /player/hands/${handId}/request-gto (frontend/src/lib/api.ts:447)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:447` calls `POST /player/hands/${handId}/request-gto` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/player/hands/<p>/request-gto`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-f5e590d0c4368258", "name": "Dangling fetch: DELETE /history/tournament/${tournamentId} (frontend/src/lib/api.ts:464)", "shortDescription": {"text": "Dangling fetch: DELETE /history/tournament/${tournamentId} (frontend/src/lib/api.ts:464)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:464` calls `DELETE /history/tournament/${tournamentId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/history/tournament/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-cc1aa2008c0b2d31", "name": "Dangling fetch: GET /player/spots/drill/${decision_id}/analysis (frontend/src/lib/api.ts:830)", "shortDescription": {"text": "Dangling fetch: GET /player/spots/drill/${decision_id}/analysis (frontend/src/lib/api.ts:830)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:830` calls `GET /player/spots/drill/${decision_id}/analysis` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/player/spots/drill/<p>/analysis`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-6f5f7732a314bfd0", "name": "Dangling fetch: POST /player/notifications/${id}/read (frontend/src/lib/api.ts:1013)", "shortDescription": {"text": "Dangling fetch: POST /player/notifications/${id}/read (frontend/src/lib/api.ts:1013)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1013` calls `POST /player/notifications/${id}/read` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/player/notifications/<p>/read`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-63608fdc45baa573", "name": "Dangling fetch: GET /player/session-review/${tournamentId} (frontend/src/lib/api.ts:1142)", "shortDescription": {"text": "Dangling fetch: GET /player/session-review/${tournamentId} (frontend/src/lib/api.ts:1142)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1142` calls `GET /player/session-review/${tournamentId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/player/session-review/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-f7dc8b6705434388", "name": "Dangling fetch: GET /coach/student/${studentId}/level (frontend/src/lib/api.ts:1617)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/level (frontend/src/lib/api.ts:1617)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1617` calls `GET /coach/student/${studentId}/level` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/level`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-29ddfbcb0688b938", "name": "Dangling fetch: GET /coach/student/${studentId}/history?days=${days} (frontend/src/lib/api.ts:1620)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/history?days=${days} (frontend/src/lib/api.ts:1620)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1620` calls `GET /coach/student/${studentId}/history?days=${days}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/history`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-3bfaacd1bbe8a77f", "name": "Dangling fetch: GET /coach/student/${studentId}/stats?days=${days} (frontend/src/lib/api.ts:1623)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/stats?days=${days} (frontend/src/lib/api.ts:1623)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1623` calls `GET /coach/student/${studentId}/stats?days=${days}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/stats`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-01dc2ce568434ef8", "name": "Dangling fetch: GET /coach/student/${studentId}/breakdown?days=${days} (frontend/src/lib/api.ts:1626)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/breakdown?days=${days} (frontend/src/lib/api.ts:1626)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1626` calls `GET /coach/student/${studentId}/breakdown?days=${days}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/breakdown`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-68a822267f1e42e5", "name": "Dangling fetch: GET /coach/student/${studentId}/replay/${tournamentId}/${handId} (frontend/src/lib/api.ts:1642)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/replay/${tournamentId}/${handId} (frontend/src/lib/api.ts:1642)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1642` calls `GET /coach/student/${studentId}/replay/${tournamentId}/${handId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/replay/<p>/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-1964484050ade697", "name": "Dangling fetch: GET /coach/student/${studentId}/study-overrides (frontend/src/lib/api.ts:1645)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/study-overrides (frontend/src/lib/api.ts:1645)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1645` calls `GET /coach/student/${studentId}/study-overrides` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/study-overrides`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-e4cde218c1f8c167", "name": "Dangling fetch: POST /coach/student/${studentId}/study-overrides (frontend/src/lib/api.ts:1653)", "shortDescription": {"text": "Dangling fetch: POST /coach/student/${studentId}/study-overrides (frontend/src/lib/api.ts:1653)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1653` calls `POST /coach/student/${studentId}/study-overrides` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/study-overrides`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c8313fb8075c8326", "name": "Dangling fetch: DELETE /coach/student/${studentId}/study-overrides/${encodeURIComponent(cardSpot)} (frontend/src/lib/api", "shortDescription": {"text": "Dangling fetch: DELETE /coach/student/${studentId}/study-overrides/${encodeURIComponent(cardSpot)} (frontend/src/lib/api.ts:1659)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1659` calls `DELETE /coach/student/${studentId}/study-overrides/${encodeURIComponent(cardSpot)}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/study-overrides/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-8e54cfe0191a4647", "name": "Dangling fetch: GET /coach/student/${studentId}/hand-annotations (frontend/src/lib/api.ts:1664)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/hand-annotations (frontend/src/lib/api.ts:1664)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1664` calls `GET /coach/student/${studentId}/hand-annotations` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/hand-annotations`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-2b6b126543f94e23", "name": "Dangling fetch: POST /coach/student/${studentId}/hand-annotations (frontend/src/lib/api.ts:1673)", "shortDescription": {"text": "Dangling fetch: POST /coach/student/${studentId}/hand-annotations (frontend/src/lib/api.ts:1673)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1673` calls `POST /coach/student/${studentId}/hand-annotations` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/hand-annotations`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-c99eedcebac0a54b", "name": "Dangling fetch: DELETE /coach/student/${studentId}/hand-annotations/${decisionId} (frontend/src/lib/api.ts:1679)", "shortDescription": {"text": "Dangling fetch: DELETE /coach/student/${studentId}/hand-annotations/${decisionId} (frontend/src/lib/api.ts:1679)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1679` calls `DELETE /coach/student/${studentId}/hand-annotations/${decisionId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/hand-annotations/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-d78e23d2bae12b76", "name": "Dangling fetch: POST /coach/student/${studentId}/baseline (frontend/src/lib/api.ts:1703)", "shortDescription": {"text": "Dangling fetch: POST /coach/student/${studentId}/baseline (frontend/src/lib/api.ts:1703)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1703` calls `POST /coach/student/${studentId}/baseline` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/baseline`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-9ae854ae01b47fe3", "name": "Dangling fetch: DELETE /coach/student/${studentId}/baseline (frontend/src/lib/api.ts:1709)", "shortDescription": {"text": "Dangling fetch: DELETE /coach/student/${studentId}/baseline (frontend/src/lib/api.ts:1709)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1709` calls `DELETE /coach/student/${studentId}/baseline` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/baseline`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-8eb6ce75557fdc2c", "name": "Dangling fetch: GET /coach/student/${studentId}/activity-feed?limit=${limit} (frontend/src/lib/api.ts:1714)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/activity-feed?limit=${limit} (frontend/src/lib/api.ts:1714)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1714` calls `GET /coach/student/${studentId}/activity-feed?limit=${limit}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/activity-feed`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-80cf33adc57f3dc8", "name": "Dangling fetch: GET /coach/student/${studentId}/progress-report (frontend/src/lib/api.ts:1717)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/progress-report (frontend/src/lib/api.ts:1717)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1717` calls `GET /coach/student/${studentId}/progress-report` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/progress-report`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-e1d1560713ba7daf", "name": "Dangling fetch: DELETE /coach/templates/${templateId} (frontend/src/lib/api.ts:1748)", "shortDescription": {"text": "Dangling fetch: DELETE /coach/templates/${templateId} (frontend/src/lib/api.ts:1748)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1748` calls `DELETE /coach/templates/${templateId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/templates/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-67954cbf249c0be1", "name": "Dangling fetch: GET /coach/student/${studentId}/messages (frontend/src/lib/api.ts:1752)", "shortDescription": {"text": "Dangling fetch: GET /coach/student/${studentId}/messages (frontend/src/lib/api.ts:1752)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1752` calls `GET /coach/student/${studentId}/messages` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/messages`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-d07b2f63599a3675", "name": "Dangling fetch: POST /coach/student/${studentId}/messages (frontend/src/lib/api.ts:1755)", "shortDescription": {"text": "Dangling fetch: POST /coach/student/${studentId}/messages (frontend/src/lib/api.ts:1755)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1755` calls `POST /coach/student/${studentId}/messages` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/student/<p>/messages`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-342cb7a143818b6c", "name": "Dangling fetch: GET /coaches/${coachUserId} (frontend/src/lib/api.ts:1823)", "shortDescription": {"text": "Dangling fetch: GET /coaches/${coachUserId} (frontend/src/lib/api.ts:1823)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:1823` calls `GET /coaches/${coachUserId}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coaches/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-a3a7c519431006ba", "name": "Dangling fetch: PATCH /admin/users/${id} (frontend/src/lib/api.ts:2002)", "shortDescription": {"text": "Dangling fetch: PATCH /admin/users/${id} (frontend/src/lib/api.ts:2002)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:2002` calls `PATCH /admin/users/${id}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/admin/users/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-e3dbb509c1bef800", "name": "Dangling fetch: DELETE /admin/users/${id} (frontend/src/lib/api.ts:2008)", "shortDescription": {"text": "Dangling fetch: DELETE /admin/users/${id} (frontend/src/lib/api.ts:2008)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:2008` calls `DELETE /admin/users/${id}` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/admin/users/<p>`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-7226dd44dd24c199", "name": "Dangling fetch: PATCH /admin/finance/coaches/${paymentId}/pay (frontend/src/lib/api.ts:2019)", "shortDescription": {"text": "Dangling fetch: PATCH /admin/finance/coaches/${paymentId}/pay (frontend/src/lib/api.ts:2019)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:2019` calls `PATCH /admin/finance/coaches/${paymentId}/pay` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/admin/finance/coaches/<p>/pay`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-25ff4e9d00f08767", "name": "Dangling fetch: POST /admin/coach-applications/${id}/approve (frontend/src/lib/api.ts:2027)", "shortDescription": {"text": "Dangling fetch: POST /admin/coach-applications/${id}/approve (frontend/src/lib/api.ts:2027)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:2027` calls `POST /admin/coach-applications/${id}/approve` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/admin/coach-applications/<p>/approve`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-8738d86bea5bae80", "name": "Dangling fetch: POST /admin/coach-applications/${id}/reject (frontend/src/lib/api.ts:2033)", "shortDescription": {"text": "Dangling fetch: POST /admin/coach-applications/${id}/reject (frontend/src/lib/api.ts:2033)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:2033` calls `POST /admin/coach-applications/${id}/reject` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/admin/coach-applications/<p>/reject`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-9e8be0676dd8f3fb", "name": "Dangling fetch: POST /coach/${coachId}/contact (frontend/src/lib/api.ts:2172)", "shortDescription": {"text": "Dangling fetch: POST /coach/${coachId}/contact (frontend/src/lib/api.ts:2172)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:2172` calls `POST /coach/${coachId}/contact` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/<p>/contact`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-e870e4cecea349df", "name": "Dangling fetch: GET /coach/${coachId}/contact-thread (frontend/src/lib/api.ts:2178)", "shortDescription": {"text": "Dangling fetch: GET /coach/${coachId}/contact-thread (frontend/src/lib/api.ts:2178)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:2178` calls `GET /coach/${coachId}/contact-thread` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/coach/<p>/contact-thread`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-cd617b64452f888a", "name": "Dangling fetch: GET /replay/${decisionId}/gto (frontend/src/lib/api.ts:2278)", "shortDescription": {"text": "Dangling fetch: GET /replay/${decisionId}/gto (frontend/src/lib/api.ts:2278)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:2278` calls `GET /replay/${decisionId}/gto` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/replay/<p>/gto`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-4740bf309d69296b", "name": "Dangling fetch: POST /admin/support-tickets/${ticketId}/reply (frontend/src/lib/api.ts:2304)", "shortDescription": {"text": "Dangling fetch: POST /admin/support-tickets/${ticketId}/reply (frontend/src/lib/api.ts:2304)"}, "fullDescription": {"text": "`frontend/src/lib/api.ts:2304` calls `POST /admin/support-tickets/${ticketId}/reply` but no backend route matches that path. This is a runtime 404 waiting to happen.\n\nTool: helper:request\nNormalized path used for matching: `/admin/support-tickets/<p>/reply`\nIf this points at an external API, prefix it with `https://` so the matcher skips it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "high", "confidence": 1.0}}, {"id": "scanner-71534283a20e67bd", "name": "Unused endpoint: ANY /analyze", "shortDescription": {"text": "Unused endpoint: ANY /analyze"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /analyze` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ecc9df8fded662dc", "name": "Unused endpoint: ANY /history/tournament/<tournament_id>", "shortDescription": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /history/tournament/<tournament_id>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1662fb6b0e728954", "name": "Unused endpoint: ANY /history/tournament/<tournament_id>/phase_analysis", "shortDescription": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>/phase_analysis"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /history/tournament/<tournament_id>/phase_analysis` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8f16d64535200fa0", "name": "Unused endpoint: ANY /history/tournament/<tournament_id>/texture_analysis", "shortDescription": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>/texture_analysis"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /history/tournament/<tournament_id>/texture_analysis` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a06fef680a455a2e", "name": "Unused endpoint: ANY /history/tournament/<tournament_id>/narrative", "shortDescription": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>/narrative"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /history/tournament/<tournament_id>/narrative` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9325a38a30093218", "name": "Unused endpoint: ANY /history/tournaments/compare", "shortDescription": {"text": "Unused endpoint: ANY /history/tournaments/compare"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /history/tournaments/compare` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6037b0738ebd14c4", "name": "Unused endpoint: ANY /history/tournament/<tournament_id>/report.pdf", "shortDescription": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>/report.pdf"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /history/tournament/<tournament_id>/report.pdf` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-38f537f58466000e", "name": "Unused endpoint: ANY /history/evolution", "shortDescription": {"text": "Unused endpoint: ANY /history/evolution"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /history/evolution` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-53b8eff612b2ea41", "name": "Unused endpoint: ANY /player/leak-roi", "shortDescription": {"text": "Unused endpoint: ANY /player/leak-roi"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/leak-roi` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-747b20e72c8276cf", "name": "Unused endpoint: ANY /player/ev-leaks", "shortDescription": {"text": "Unused endpoint: ANY /player/ev-leaks"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/ev-leaks` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-52940c1027ad1d7d", "name": "Unused endpoint: ANY /player/leak-finder", "shortDescription": {"text": "Unused endpoint: ANY /player/leak-finder"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/leak-finder` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-aa962ab4908b829a", "name": "Unused endpoint: ANY /player/gto-quality", "shortDescription": {"text": "Unused endpoint: ANY /player/gto-quality"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/gto-quality` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3e20e9e4612965fc", "name": "Unused endpoint: ANY /player/gto-alignment", "shortDescription": {"text": "Unused endpoint: ANY /player/gto-alignment"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/gto-alignment` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-34e6e49fbba2003b", "name": "Unused endpoint: ANY /player/gto-position", "shortDescription": {"text": "Unused endpoint: ANY /player/gto-position"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/gto-position` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-bdf36d6d16ed82ed", "name": "Unused endpoint: ANY /player/gto-alignment-matrix", "shortDescription": {"text": "Unused endpoint: ANY /player/gto-alignment-matrix"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/gto-alignment-matrix` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-64bce77733cee5f8", "name": "Unused endpoint: ANY /player/results-vs-gto", "shortDescription": {"text": "Unused endpoint: ANY /player/results-vs-gto"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/results-vs-gto` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-65ad0fa20fb785a9", "name": "Unused endpoint: ANY /player/spots/drill", "shortDescription": {"text": "Unused endpoint: ANY /player/spots/drill"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/spots/drill` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-881c2b423179ee5f", "name": "Unused endpoint: ANY /player/notifications/<int:notif_id>/read", "shortDescription": {"text": "Unused endpoint: ANY /player/notifications/<int:notif_id>/read"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/notifications/<int:notif_id>/read` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-31540c0cf431a7ce", "name": "Unused endpoint: ANY /player/sparring/hand", "shortDescription": {"text": "Unused endpoint: ANY /player/sparring/hand"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/sparring/hand` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-6995e9bc5033ccd5", "name": "Unused endpoint: ANY /player/session-review/<int:tournament_id>", "shortDescription": {"text": "Unused endpoint: ANY /player/session-review/<int:tournament_id>"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/session-review/<int:tournament_id>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-ded8f6bb52898936", "name": "Unused endpoint: ANY /player/spots/drill/<int:decision_id>/analysis", "shortDescription": {"text": "Unused endpoint: ANY /player/spots/drill/<int:decision_id>/analysis"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /player/spots/drill/<int:decision_id>/analysis` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-c108632ee68eb50b", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/level", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/level"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/level` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8f4790563ea02356", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/history", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/history"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/history` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-fcf55248fca0b445", "name": "Unused endpoint: ANY /gto/status", "shortDescription": {"text": "Unused endpoint: ANY /gto/status"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /gto/status` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-14854d084b16ac21", "name": "Unused endpoint: ANY /analyze/guest", "shortDescription": {"text": "Unused endpoint: ANY /analyze/guest"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /analyze/guest` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-3b50f7f56170792f", "name": "Unused endpoint: ANY /coach/templates/<int:template_id>", "shortDescription": {"text": "Unused endpoint: ANY /coach/templates/<int:template_id>"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/templates/<int:template_id>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-1623b8481916e644", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/messages", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/messages"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/messages` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0ffdaccff2abb126", "name": "Unused endpoint: ANY /coach/<int:coach_id>/contact", "shortDescription": {"text": "Unused endpoint: ANY /coach/<int:coach_id>/contact"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/<int:coach_id>/contact` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-88c4d999ea928aa8", "name": "Unused endpoint: ANY /coach/<int:coach_id>/contact-thread", "shortDescription": {"text": "Unused endpoint: ANY /coach/<int:coach_id>/contact-thread"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/<int:coach_id>/contact-thread` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-b46f0a1933b973ee", "name": "Unused endpoint: ANY /coaches", "shortDescription": {"text": "Unused endpoint: ANY /coaches"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coaches` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d6417adc32d4a2e0", "name": "Unused endpoint: ANY /coaches/<int:coach_user_id>", "shortDescription": {"text": "Unused endpoint: ANY /coaches/<int:coach_user_id>"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coaches/<int:coach_user_id>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-2d4aa15b5fc0638b", "name": "Unused endpoint: ANY /coaches/<int:coach_user_id>/reviews", "shortDescription": {"text": "Unused endpoint: ANY /coaches/<int:coach_user_id>/reviews"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coaches/<int:coach_user_id>/reviews` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9c229dcb199c0527", "name": "Unused endpoint: ANY /coach/students-legacy", "shortDescription": {"text": "Unused endpoint: ANY /coach/students-legacy"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/students-legacy` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e18bcc5a87572c9d", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/stats", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/stats"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/stats` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0485e104510a28be", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/breakdown", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/breakdown"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/breakdown` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-a0c6940ee5348e54", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/tournament/<tournament_id>", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/tournament/<tournament_id>"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/tournament/<tournament_id>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e4a694e91a8bc74e", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/worst-decisions", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/worst-decisions"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/worst-decisions` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-135e8fc09e1f6f97", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/study-plan", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/study-plan"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/study-plan` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-8fea7367b5a559bd", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/replay/<tournament_id>/<hand_id>", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/replay/<tournament_id>/<hand_id>"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/replay/<tournament_id>/<hand_id>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d74931ca0465ad56", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/study-overrides", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/study-overrides"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/study-overrides` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-0677839bc0aa4063", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/study-overrides/<path:card_spot>", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/study-overrides/<path:card_spot>"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/study-overrides/<path:card_spot>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d5d3ea592b147cd6", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/hand-annotations", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/hand-annotations"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/hand-annotations` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-52a26e7f034b53a1", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/hand-annotations/<int:decision_id>", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/hand-annotations/<int:decision_id>"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/hand-annotations/<int:decision_id>` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-f43d5eef81769133", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/baseline", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/baseline"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/baseline` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-37c1078e7494b80b", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/activity-feed", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/activity-feed"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/activity-feed` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-e2587c543e24eca8", "name": "Unused endpoint: ANY /coach/student/<int:student_id>/progress-report", "shortDescription": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/progress-report"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/student/<int:student_id>/progress-report` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-cabc7930354e2d54", "name": "Unused endpoint: ANY /coach/my-review", "shortDescription": {"text": "Unused endpoint: ANY /coach/my-review"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /coach/my-review` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-9bfb5ccc8c007354", "name": "Unused endpoint: ANY /analyze/hand-coach", "shortDescription": {"text": "Unused endpoint: ANY /analyze/hand-coach"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /analyze/hand-coach` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d6ef036b134356e3", "name": "Unused endpoint: ANY /study/plan", "shortDescription": {"text": "Unused endpoint: ANY /study/plan"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /study/plan` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}, {"id": "scanner-d714fdf0b62943ca", "name": "Unused endpoint: ANY /analyze/replay-coach", "shortDescription": {"text": "Unused endpoint: ANY /analyze/replay-coach"}, "fullDescription": {"text": "`backend/api/app.py` declares `ANY /analyze/replay-coach` but no frontend code we scanned calls it. This is fine if the endpoint serves external clients (mobile app, third-party, server-side webhooks). Otherwise it's dead code \u2014 consider removing or documenting who consumes it."}, "properties": {"scanner": "scanner-primary", "layer": "api", "severity": "low", "confidence": 1.0}}]}}, "automationDetails": {"id": "repobility/22891"}, "properties": {"repository": "wrodrigobr/Leaklab", "repoUrl": "https://github.com/wrodrigobr/Leaklab", "branch": "main"}, "results": [{"ruleId": "scanner-c21eae8a3d3aae40", "level": "note", "message": {"text": "Possibly dead Python function: position_from_preflop_actions"}, "properties": {"repobilityId": "cd0fe1630d164a91", "scanner": "scanner-primary", "fingerprint": "c21eae8a3d3aae40", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/scripts/parse_gw_har.py:223"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-871c48d9eb894b30", "level": "note", "message": {"text": "Possibly dead Python function: build_app_url"}, "properties": {"repobilityId": "bdce45f145352888", "scanner": "scanner-primary", "fingerprint": "871c48d9eb894b30", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/scripts/gto_validation/playwright_compare.py:120"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6e7222468b41e6ad", "level": "note", "message": {"text": "Possibly dead Python function: load_cookies"}, "properties": {"repobilityId": "68358996a7564b80", "scanner": "scanner-primary", "fingerprint": "6e7222468b41e6ad", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/scripts/gto_validation/playwright_compare.py:144"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b5b75bd62be929e7", "level": "note", "message": {"text": "Possibly dead Python function: do_login"}, "properties": {"repobilityId": "90e07ee0d2ed6be2", "scanner": "scanner-primary", "fingerprint": "b5b75bd62be929e7", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/scripts/gto_validation/playwright_compare.py:159"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-a7ea3bf9d7541f3a", "level": "note", "message": {"text": "Possibly dead Python function: build_preflop_actions_simple"}, "properties": {"repobilityId": "a947876b69172747", "scanner": "scanner-primary", "fingerprint": "a7ea3bf9d7541f3a", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/scripts/gto_validation/preflop_action_builder.py:36"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2ea49e4ac5554d11", "level": "note", "message": {"text": "Possibly dead Python function: matcher"}, "properties": {"repobilityId": "274ff3c059fa01ec", "scanner": "scanner-primary", "fingerprint": "2ea49e4ac5554d11", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/gto_bot/solver_api/_gw_subprocess.py:93"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-3e2ddab13fd3387d", "level": "note", "message": {"text": "Possibly dead Python function: log_message"}, "properties": {"repobilityId": "965f3150b4af5b2e", "scanner": "scanner-primary", "fingerprint": "3e2ddab13fd3387d", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/gto_bot/solver_api/server.py:1232"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6786ea3de5bfb14c", "level": "note", "message": {"text": "Possibly dead Python function: do_GET"}, "properties": {"repobilityId": "2d943bb45e4f13bd", "scanner": "scanner-primary", "fingerprint": "6786ea3de5bfb14c", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/gto_bot/solver_api/server.py:1258"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-933e8ce97737c20f", "level": "note", "message": {"text": "Possibly dead Python function: do_POST"}, "properties": {"repobilityId": "53357410ca9379a9", "scanner": "scanner-primary", "fingerprint": "933e8ce97737c20f", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/gto_bot/solver_api/server.py:1279"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-6d2278e70323cdf4", "level": "note", "message": {"text": "Possibly dead Python function: ph"}, "properties": {"repobilityId": "7914908bdf5f5485", "scanner": "scanner-primary", "fingerprint": "6d2278e70323cdf4", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/database/schema.py:44"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-0dc3e2c58d87f439", "level": "note", "message": {"text": "Possibly dead Python function: placeholders"}, "properties": {"repobilityId": "7f25701f37b15175", "scanner": "scanner-primary", "fingerprint": "0dc3e2c58d87f439", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/database/schema.py:49"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-b99f41eb1e64ce35", "level": "note", "message": {"text": "Possibly dead Python function: resync_gto_labels_for_node"}, "properties": {"repobilityId": "0fea50d175e5e3d0", "scanner": "scanner-primary", "fingerprint": "b99f41eb1e64ce35", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/database/repositories.py:6718"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-8395fdb6a1721efa", "level": "note", "message": {"text": "Possibly dead Python function: is_divergent"}, "properties": {"repobilityId": "0248516f8a7d7bb8", "scanner": "scanner-primary", "fingerprint": "8395fdb6a1721efa", "layer": "software", "severity": "low", "confidence": 1.0, "tags": ["dead-code"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/leaklab/coach_adherence.py:135"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-800831fa7b3cd278", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/components/ui/chart.tsx:70"}, "properties": {"repobilityId": "87d65db05fa624b0", "scanner": "scanner-primary", "fingerprint": "800831fa7b3cd278", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-89d574f1e2dc78b3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/CognitiveFailureCard.tsx:41"}, "properties": {"repobilityId": "2e0b024baf348dea", "scanner": "scanner-primary", "fingerprint": "89d574f1e2dc78b3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-abba8f6fdd33f618", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/CareerGraphCard.tsx:425"}, "properties": {"repobilityId": "cb3d80060f9c2516", "scanner": "scanner-primary", "fingerprint": "abba8f6fdd33f618", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-509b966463a17e1c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/DecisionQualityCard.tsx:71"}, "properties": {"repobilityId": "21326da5e62a87cc", "scanner": "scanner-primary", "fingerprint": "509b966463a17e1c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-84fbd12631b6c3da", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/V2CognitiveCard.tsx:46"}, "properties": {"repobilityId": "eb10873d272f1a03", "scanner": "scanner-primary", "fingerprint": "84fbd12631b6c3da", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8e76e9f6bf8163d3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/PokerTable.tsx:150"}, "properties": {"repobilityId": "084694e49c88c575", "scanner": "scanner-primary", "fingerprint": "8e76e9f6bf8163d3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-4c7c9c945e4443e9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/HudHeader.tsx:303"}, "properties": {"repobilityId": "e3456ec87d1087a1", "scanner": "scanner-primary", "fingerprint": "4c7c9c945e4443e9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-b8a07c2b381c37e9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/StrategicTwinCard.tsx:34"}, "properties": {"repobilityId": "966810c41677e0de", "scanner": "scanner-primary", "fingerprint": "b8a07c2b381c37e9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-365c49a8ce360d5f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/RecentTournamentsTable.tsx:98"}, "properties": {"repobilityId": "fe199db6c0d0e7a2", "scanner": "scanner-primary", "fingerprint": "365c49a8ce360d5f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-a1fdb3d7764dcf74", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/DailyFocusCard.tsx:61"}, "properties": {"repobilityId": "381d464104fe17e7", "scanner": "scanner-primary", "fingerprint": "a1fdb3d7764dcf74", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-958bc4deb19b53b5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/LeakFinderCard.tsx:63"}, "properties": {"repobilityId": "1ae951b251b2fd3e", "scanner": "scanner-primary", "fingerprint": "958bc4deb19b53b5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-cedc9d850885ea5a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/V2TwinCard.tsx:33"}, "properties": {"repobilityId": "0049a314b0daab9f", "scanner": "scanner-primary", "fingerprint": "cedc9d850885ea5a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8634774e9a08d7e3", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/GtoQualityCard.tsx:88"}, "properties": {"repobilityId": "c74c56aa0b061729", "scanner": "scanner-primary", "fingerprint": "8634774e9a08d7e3", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6c976e23e710232b", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/GtoAlignmentCard.tsx:125"}, "properties": {"repobilityId": "1139e313ed41fb97", "scanner": "scanner-primary", "fingerprint": "6c976e23e710232b", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-ff32713133085842", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/V2QualityCard.tsx:79"}, "properties": {"repobilityId": "8967e87348b5e6b4", "scanner": "scanner-primary", "fingerprint": "ff32713133085842", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-48ab4f7ad8d7ebf9", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/UploadQueue.tsx:93"}, "properties": {"repobilityId": "d5b2cceed53acc7f", "scanner": "scanner-primary", "fingerprint": "48ab4f7ad8d7ebf9", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-03e3d82cec32e113", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/GtoPositionCard.tsx:107"}, "properties": {"repobilityId": "63d4c993ea20e2ed", "scanner": "scanner-primary", "fingerprint": "03e3d82cec32e113", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8fdd8ca33c27a3db", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/components/hud/LevelCard.tsx:124"}, "properties": {"repobilityId": "a9bc3bb964151947", "scanner": "scanner-primary", "fingerprint": "8fdd8ca33c27a3db", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-f806c34d4ae52892", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Tournaments.tsx:311"}, "properties": {"repobilityId": "cd89bc4aa71c81ca", "scanner": "scanner-primary", "fingerprint": "f806c34d4ae52892", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1137aadea2be1d5c", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/TournamentCompare.tsx:124"}, "properties": {"repobilityId": "f2f804a48fdccd5d", "scanner": "scanner-primary", "fingerprint": "1137aadea2be1d5c", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-1db2bf66dc6068c5", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/StudentProfile.tsx:147"}, "properties": {"repobilityId": "58e86263c0cbede7", "scanner": "scanner-primary", "fingerprint": "1db2bf66dc6068c5", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-55ef47fe75fde900", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Replayer.tsx:1289"}, "properties": {"repobilityId": "4da7a86a876d8bff", "scanner": "scanner-primary", "fingerprint": "55ef47fe75fde900", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-2f812ebdb1f7a54b", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 frontend/src/pages/Replayer.tsx:1650"}, "properties": {"repobilityId": "d75983a4e7bb338b", "scanner": "scanner-primary", "fingerprint": "2f812ebdb1f7a54b", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-7c69a69e5b543807", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/CoachesDirectory.tsx:66"}, "properties": {"repobilityId": "17e3069ac045b141", "scanner": "scanner-primary", "fingerprint": "7c69a69e5b543807", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-85544ab96dbf1324", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/pages/DocsRating.tsx:10"}, "properties": {"repobilityId": "8466ee349d96d0f3", "scanner": "scanner-primary", "fingerprint": "85544ab96dbf1324", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-23762336110cdb6f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Sparring.tsx:706"}, "properties": {"repobilityId": "a4bacc079ea17abd", "scanner": "scanner-primary", "fingerprint": "23762336110cdb6f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6fca59c42a6f46f0", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/PublicCoachProfile.tsx:335"}, "properties": {"repobilityId": "5f50b4c0abd42750", "scanner": "scanner-primary", "fingerprint": "6fca59c42a6f46f0", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-24c4313e6ead0dd7", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/GhostTable.tsx:399"}, "properties": {"repobilityId": "e2c56ef2bba1cb67", "scanner": "scanner-primary", "fingerprint": "24c4313e6ead0dd7", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-6afdce1054e29da8", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Docs.tsx:77"}, "properties": {"repobilityId": "bff623456fdc37d6", "scanner": "scanner-primary", "fingerprint": "6afdce1054e29da8", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-3b5ddc88f3439f0a", "level": "warning", "message": {"text": "`dangerouslySetInnerHTML` used in a React component \u2014 frontend/src/pages/Docs.tsx:194"}, "properties": {"repobilityId": "3739b71215b0e6e9", "scanner": "scanner-primary", "fingerprint": "3b5ddc88f3439f0a", "layer": "frontend", "severity": "medium", "confidence": 1.0, "tags": ["frontend-quality", "fq.dangerous-html"]}}, {"ruleId": "scanner-b01759e3ffb98f1f", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/Leaderboard.tsx:44"}, "properties": {"repobilityId": "c7e63d091d2a4c44", "scanner": "scanner-primary", "fingerprint": "b01759e3ffb98f1f", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-d3cfe70d0ea56c16", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/StudyPlan.tsx:85"}, "properties": {"repobilityId": "c735c13e401af874", "scanner": "scanner-primary", "fingerprint": "d3cfe70d0ea56c16", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-7030e48761039002", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/AICoach.tsx:287"}, "properties": {"repobilityId": "246d8f348079b315", "scanner": "scanner-primary", "fingerprint": "7030e48761039002", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-8d83619ed743eb15", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/admin/AdminDashboard.tsx:119"}, "properties": {"repobilityId": "6cbb0be1920021b7", "scanner": "scanner-primary", "fingerprint": "8d83619ed743eb15", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-5dc8817c74b5c4df", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/coach/StudentDetail.tsx:200"}, "properties": {"repobilityId": "ee5f4da2a8bd1434", "scanner": "scanner-primary", "fingerprint": "5dc8817c74b5c4df", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-29891483997f1b6a", "level": "none", "message": {"text": "`truncate` class without `title=` for hover reveal \u2014 frontend/src/pages/coach/CoachDashboard.tsx:125"}, "properties": {"repobilityId": "9ea53b720773f755", "scanner": "scanner-primary", "fingerprint": "29891483997f1b6a", "layer": "frontend", "severity": "info", "confidence": 1.0, "tags": ["frontend-quality", "fq.truncate.no-title"]}}, {"ruleId": "scanner-83d9e633e5ead2f1", "level": "note", "message": {"text": "Stray `console.log` in TS/JS \u2014 backend/scripts/gto_validation/console_script.js:523"}, "properties": {"repobilityId": "4ee4089dc23039f3", "scanner": "scanner-primary", "fingerprint": "83d9e633e5ead2f1", "layer": "frontend", "severity": "low", "confidence": 1.0, "tags": ["frontend-quality", "fq.console-leak"]}}, {"ruleId": "scanner-f6cd08fa8d1eb4b0", "level": "warning", "message": {"text": "Analyzer timeout: security.gitleaks"}, "properties": {"repobilityId": "err::timeout::security.gitleaks", "scanner": "scanner-primary", "fingerprint": "f6cd08fa8d1eb4b0", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["analyzer-error", "timeout"]}}, {"ruleId": "scanner-503686fa1d081418", "level": "warning", "message": {"text": "Privileged port 42 in use"}, "properties": {"repobilityId": "16d9608735f9e01a", "scanner": "scanner-primary", "fingerprint": "503686fa1d081418", "layer": "network", "severity": "medium", "confidence": 1.0, "tags": ["security", "ports"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/gto_bot/solver_api/setup_vm.sh"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-1f66ad88286ca30a", "level": "warning", "message": {"text": "Dockerfile runs as root: backend/Dockerfile"}, "properties": {"repobilityId": "7afd2b0e8a8c9eeb", "scanner": "scanner-primary", "fingerprint": "1f66ad88286ca30a", "layer": "hardware", "severity": "medium", "confidence": 1.0, "tags": ["security", "container"]}}, {"ruleId": "scanner-8cd20d539467d2c5", "level": "note", "message": {"text": "Docker base image is tag-pinned but not digest-pinned: python:3.11-slim"}, "properties": {"repobilityId": "06b87ac9439092d6", "scanner": "scanner-primary", "fingerprint": "8cd20d539467d2c5", "layer": "hardware", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "docker", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/Dockerfile"}, "region": {"startLine": 1}}}]}, {"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-8d282e31e9bc7a78", "level": "error", "message": {"text": "Runtime dotenv file present in repo: frontend/.env"}, "properties": {"repobilityId": "20512f217a866b0e", "scanner": "scanner-primary", "fingerprint": "8d282e31e9bc7a78", "layer": "security", "severity": "high", "confidence": 1.0, "tags": ["secrets", "config", "env-file", "runtime-env"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/.env"}, "region": {"startLine": 1}}}]}, {"ruleId": "scanner-2a26d405619326a1", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/leaklab-replayer-v3.html:710"}, "properties": {"repobilityId": "f4c2b90c0791e9d9", "scanner": "scanner-primary", "fingerprint": "2a26d405619326a1", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/leaklab-replayer-v3.html"}, "region": {"startLine": 710}}}]}, {"ruleId": "scanner-045798e982aa56ad", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/index.legacy.html:899"}, "properties": {"repobilityId": "e1ef784389a3fe20", "scanner": "scanner-primary", "fingerprint": "045798e982aa56ad", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/index.legacy.html"}, "region": {"startLine": 899}}}]}, {"ruleId": "scanner-5a5a632de13abfd7", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/index.legacy.html:2069"}, "properties": {"repobilityId": "fa15fef203e3616b", "scanner": "scanner-primary", "fingerprint": "5a5a632de13abfd7", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/index.legacy.html"}, "region": {"startLine": 2069}}}]}, {"ruleId": "scanner-2c8914bada65590c", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/leaklab-replayer-v4.html:692"}, "properties": {"repobilityId": "410868538930dfcb", "scanner": "scanner-primary", "fingerprint": "2c8914bada65590c", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/leaklab-replayer-v4.html"}, "region": {"startLine": 692}}}]}, {"ruleId": "scanner-571b8a04eaecbfb3", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/faces_squeeze_card_shots.mjs:21"}, "properties": {"repobilityId": "d703e3029f5b7cad", "scanner": "scanner-primary", "fingerprint": "571b8a04eaecbfb3", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/faces_squeeze_card_shots.mjs"}, "region": {"startLine": 21}}}]}, {"ruleId": "scanner-4be17ef28dc35f3a", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/pf_uncov_shots.mjs:15"}, "properties": {"repobilityId": "4cb65bcdddadebbb", "scanner": "scanner-primary", "fingerprint": "4be17ef28dc35f3a", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/pf_uncov_shots.mjs"}, "region": {"startLine": 15}}}]}, {"ruleId": "scanner-93bfd61fd8d8629d", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs_shove_card_shots.mjs:17"}, "properties": {"repobilityId": "e764053d9733fe6e", "scanner": "scanner-primary", "fingerprint": "93bfd61fd8d8629d", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/vs_shove_card_shots.mjs"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-dd192790506b29cb", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs3bet_card_shots.mjs:21"}, "properties": {"repobilityId": "efdda1dfddaa2072", "scanner": "scanner-primary", "fingerprint": "dd192790506b29cb", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/vs3bet_card_shots.mjs"}, "region": {"startLine": 21}}}]}, {"ruleId": "scanner-dae277e50e4ea7df", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vsrfi_fresh_shots.mjs:15"}, "properties": {"repobilityId": "a010ae0cd72ff629", "scanner": "scanner-primary", "fingerprint": "dae277e50e4ea7df", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/vsrfi_fresh_shots.mjs"}, "region": {"startLine": 15}}}]}, {"ruleId": "scanner-ae093bfdbbeb8e13", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/pushfold_card_shots.mjs:17"}, "properties": {"repobilityId": "f8c9ef84ca897735", "scanner": "scanner-primary", "fingerprint": "ae093bfdbbeb8e13", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/pushfold_card_shots.mjs"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-a04696b5dfd34720", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/postflop_card_shots.mjs:16"}, "properties": {"repobilityId": "5ff1661efc94d6d6", "scanner": "scanner-primary", "fingerprint": "a04696b5dfd34720", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/postflop_card_shots.mjs"}, "region": {"startLine": 16}}}]}, {"ruleId": "scanner-9bc9fa7f5090cf38", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs4bet_card_shots.mjs:17"}, "properties": {"repobilityId": "ada285aa65f790d3", "scanner": "scanner-primary", "fingerprint": "9bc9fa7f5090cf38", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/vs4bet_card_shots.mjs"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-51f15e9571a54257", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/replayer_shots.mjs:33"}, "properties": {"repobilityId": "fa6460fb01be794d", "scanner": "scanner-primary", "fingerprint": "51f15e9571a54257", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/replayer_shots.mjs"}, "region": {"startLine": 33}}}]}, {"ruleId": "scanner-4f4d58df3af64f71", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/limp_card_shots.mjs:17"}, "properties": {"repobilityId": "142c34baa3749b25", "scanner": "scanner-primary", "fingerprint": "4f4d58df3af64f71", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/limp_card_shots.mjs"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-f5a0317af4c1b55b", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/turn_card_shots.mjs:17"}, "properties": {"repobilityId": "22ad7ec041e3a6e9", "scanner": "scanner-primary", "fingerprint": "f5a0317af4c1b55b", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/turn_card_shots.mjs"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-11d4ae4708ee6fb2", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/mobile_shots.mjs:13"}, "properties": {"repobilityId": "966741e3290627cf", "scanner": "scanner-primary", "fingerprint": "11d4ae4708ee6fb2", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/mobile_shots.mjs"}, "region": {"startLine": 13}}}]}, {"ruleId": "scanner-ed78303535497af9", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/rangepanel_shots.mjs:15"}, "properties": {"repobilityId": "f6e559b78f592bfe", "scanner": "scanner-primary", "fingerprint": "ed78303535497af9", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/rangepanel_shots.mjs"}, "region": {"startLine": 15}}}]}, {"ruleId": "scanner-ff017c7b1f1ad72a", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/rfi_card_shots.mjs:17"}, "properties": {"repobilityId": "355ddeceda88defd", "scanner": "scanner-primary", "fingerprint": "ff017c7b1f1ad72a", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/rfi_card_shots.mjs"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-354fedde557ef376", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/squeeze_card_shots.mjs:16"}, "properties": {"repobilityId": "196d6722b7e0ad62", "scanner": "scanner-primary", "fingerprint": "354fedde557ef376", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/squeeze_card_shots.mjs"}, "region": {"startLine": 16}}}]}, {"ruleId": "scanner-ef77cea862647792", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/vs_rfi_card_shots.mjs:16"}, "properties": {"repobilityId": "44bd7c6e05dc468c", "scanner": "scanner-primary", "fingerprint": "ef77cea862647792", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/vs_rfi_card_shots.mjs"}, "region": {"startLine": 16}}}]}, {"ruleId": "scanner-c0e36abd00968855", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/multiway_card_shots.mjs:17"}, "properties": {"repobilityId": "1b9196f63003c3a0", "scanner": "scanner-primary", "fingerprint": "c0e36abd00968855", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/multiway_card_shots.mjs"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-81788c5a051db4a5", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/scripts/river_card_shots.mjs:17"}, "properties": {"repobilityId": "4067d34357b1ecc5", "scanner": "scanner-primary", "fingerprint": "81788c5a051db4a5", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/scripts/river_card_shots.mjs"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-a306d70c7e47b967", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/components/ui/chart.tsx:70"}, "properties": {"repobilityId": "68d1eb3e4f8f564d", "scanner": "scanner-primary", "fingerprint": "a306d70c7e47b967", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/ui/chart.tsx"}, "region": {"startLine": 70}}}]}, {"ruleId": "scanner-72afaf67ffaf524e", "level": "warning", "message": {"text": "Insecure pattern 'direct_innerhtml_assignment' in frontend/src/components/hud/PokerTableV3.tsx:521"}, "properties": {"repobilityId": "368cf0f69107667e", "scanner": "scanner-primary", "fingerprint": "72afaf67ffaf524e", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "direct_innerhtml_assignment"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/components/hud/PokerTableV3.tsx"}, "region": {"startLine": 521}}}]}, {"ruleId": "scanner-26e3d57bf56c8c13", "level": "warning", "message": {"text": "Insecure pattern 'local_storage_auth_token' in frontend/src/lib/auth.tsx:34"}, "properties": {"repobilityId": "bff16aa225923147", "scanner": "scanner-primary", "fingerprint": "26e3d57bf56c8c13", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "local_storage_auth_token"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/lib/auth.tsx"}, "region": {"startLine": 34}}}]}, {"ruleId": "scanner-e87db8c3f412c580", "level": "warning", "message": {"text": "Insecure pattern 'dangerous_innerhtml' in frontend/src/pages/Docs.tsx:194"}, "properties": {"repobilityId": "1dc0830b69bab012", "scanner": "scanner-primary", "fingerprint": "e87db8c3f412c580", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "dangerous_innerhtml"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "frontend/src/pages/Docs.tsx"}, "region": {"startLine": 194}}}]}, {"ruleId": "scanner-f87a3288747a6c1d", "level": "note", "message": {"text": "Insecure pattern 'debug_true' in backend/api/app.py:7436"}, "properties": {"repobilityId": "2c2f2ce373a3b919", "scanner": "scanner-primary", "fingerprint": "f87a3288747a6c1d", "layer": "security", "severity": "low", "confidence": 1.0, "tags": ["owasp", "debug_true"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/api/app.py"}, "region": {"startLine": 7436}}}]}, {"ruleId": "scanner-665b48455dd120b7", "level": "warning", "message": {"text": "Insecure pattern 'cors_wildcard' in backend/api/app.py:209"}, "properties": {"repobilityId": "ea5eba4c15bf5090", "scanner": "scanner-primary", "fingerprint": "665b48455dd120b7", "layer": "security", "severity": "medium", "confidence": 1.0, "tags": ["owasp", "cors_wildcard"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": "backend/api/app.py"}, "region": {"startLine": 209}}}]}, {"ruleId": "scanner-e6670f32b5bd9075", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "1f37420fcbc4160e", "scanner": "scanner-primary", "fingerprint": "e6670f32b5bd9075", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci-cd.yml"}, "region": {"startLine": 17}}}]}, {"ruleId": "scanner-e6670f32b5bd9075", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "2f5b6a561cfd8801", "scanner": "scanner-primary", "fingerprint": "e6670f32b5bd9075", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci-cd.yml"}, "region": {"startLine": 20}}}]}, {"ruleId": "scanner-e6670f32b5bd9075", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "2da2b5dc0d69cebc", "scanner": "scanner-primary", "fingerprint": "e6670f32b5bd9075", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci-cd.yml"}, "region": {"startLine": 37}}}]}, {"ruleId": "scanner-e6670f32b5bd9075", "level": "note", "message": {"text": "GitHub Action is tag-pinned rather than SHA-pinned"}, "properties": {"repobilityId": "1f37420fcbc4160e", "scanner": "scanner-primary", "fingerprint": "e6670f32b5bd9075", "layer": "cicd", "severity": "low", "confidence": 1.0, "tags": ["supply-chain", "github-actions", "pinned-dependencies"]}, "locations": [{"physicalLocation": {"artifactLocation": {"uri": ".github/workflows/ci-cd.yml"}, "region": {"startLine": 86}}}]}, {"ruleId": "scanner-c11cf013845a07f0", "level": "note", "message": {"text": "Very large file: frontend/src/lib/api.ts (2308 lines)"}, "properties": {"repobilityId": "be9b0901f516ad7b", "scanner": "scanner-primary", "fingerprint": "c11cf013845a07f0", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-d9193bfbb7a79114", "level": "note", "message": {"text": "Very large file: frontend/src/pages/HandBuilder.tsx (1246 lines)"}, "properties": {"repobilityId": "75c77584884b40d8", "scanner": "scanner-primary", "fingerprint": "d9193bfbb7a79114", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-68c4fa18d1396d7b", "level": "note", "message": {"text": "Very large file: frontend/src/pages/Replayer.tsx (2024 lines)"}, "properties": {"repobilityId": "a388e57b645be21c", "scanner": "scanner-primary", "fingerprint": "68c4fa18d1396d7b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-30a071f30d83b515", "level": "note", "message": {"text": "Very large file: frontend/src/pages/GhostTable.tsx (1131 lines)"}, "properties": {"repobilityId": "3e87a41e5689bc97", "scanner": "scanner-primary", "fingerprint": "30a071f30d83b515", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-b7335146c3601bda", "level": "note", "message": {"text": "Very large file: frontend/src/pages/admin/AdminDashboard.tsx (1241 lines)"}, "properties": {"repobilityId": "c4dd13be38b9950d", "scanner": "scanner-primary", "fingerprint": "b7335146c3601bda", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-55f4946de37a4227", "level": "note", "message": {"text": "Very large file: frontend/src/pages/coach/StudentDetail.tsx (1695 lines)"}, "properties": {"repobilityId": "27136d63f8cf15fa", "scanner": "scanner-primary", "fingerprint": "55f4946de37a4227", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-03aa1d7857da438d", "level": "note", "message": {"text": "Very large file: frontend/src/pages/coach/CoachDashboard.tsx (1364 lines)"}, "properties": {"repobilityId": "7818398c20964bf6", "scanner": "scanner-primary", "fingerprint": "03aa1d7857da438d", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-a58a699a3f0a00e5", "level": "note", "message": {"text": "Very large file: backend/api/app.py (7436 lines)"}, "properties": {"repobilityId": "ba1fb8899a58a68b", "scanner": "scanner-primary", "fingerprint": "a58a699a3f0a00e5", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-b63f6e84f63b3130", "level": "note", "message": {"text": "Very large file: backend/gto_bot/solver_api/server.py (1358 lines)"}, "properties": {"repobilityId": "7d2ced4c4bba0102", "scanner": "scanner-primary", "fingerprint": "b63f6e84f63b3130", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-bae22e76346288ce", "level": "note", "message": {"text": "Very large file: backend/database/schema.py (1637 lines)"}, "properties": {"repobilityId": "e11208102d120fdd", "scanner": "scanner-primary", "fingerprint": "bae22e76346288ce", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-5b677d4683a9f13a", "level": "note", "message": {"text": "Very large file: backend/database/repositories.py (6948 lines)"}, "properties": {"repobilityId": "e7e86c04bee38135", "scanner": "scanner-primary", "fingerprint": "5b677d4683a9f13a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-32e0bf00bc420f5e", "level": "note", "message": {"text": "Very large file: backend/leaklab/preflop_gto_ranges.py (1327 lines)"}, "properties": {"repobilityId": "9aa419bfee9b6e12", "scanner": "scanner-primary", "fingerprint": "32e0bf00bc420f5e", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-0063b7b8c10d8b36", "level": "note", "message": {"text": "Very large file: backend/leaklab/llm_explainer.py (2886 lines)"}, "properties": {"repobilityId": "612a52f30224a3a9", "scanner": "scanner-primary", "fingerprint": "0063b7b8c10d8b36", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-fd49a97369cdcab5", "level": "note", "message": {"text": "Very large file: backend/leaklab/academy.py (1307 lines)"}, "properties": {"repobilityId": "93768c1df853eca3", "scanner": "scanner-primary", "fingerprint": "fd49a97369cdcab5", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-c3baf052fbdb6df1", "level": "note", "message": {"text": "Very large file: backend/leaklab/decision_engine_v11.py (1181 lines)"}, "properties": {"repobilityId": "d31ac8e08b7303c4", "scanner": "scanner-primary", "fingerprint": "c3baf052fbdb6df1", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["complexity"]}}, {"ruleId": "scanner-ea3b5e389d8c9c0f", "level": "note", "message": {"text": "Low test-to-source ratio"}, "properties": {"repobilityId": "ef7b2552cc00a375", "scanner": "scanner-primary", "fingerprint": "ea3b5e389d8c9c0f", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["tests"]}}, {"ruleId": "scanner-3ab5d313dda8e5f9", "level": "note", "message": {"text": "Debug logging residue appears in source files"}, "properties": {"repobilityId": "cd2e49f311a73f26", "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": "f151ba3c1297a57c", "scanner": "scanner-primary", "fingerprint": "72b2a6250083a784", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["placeholder", "mock-data", "incomplete", "generated-repo-pattern"]}}, {"ruleId": "scanner-2d0c7b7ab8f8aacf", "level": "warning", "message": {"text": "Critical user flow still appears backed by mock or placeholder data"}, "properties": {"repobilityId": "efcf9697904143a7", "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": "7ea680e09f6c0913", "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": "f251afee58378a75", "scanner": "scanner-primary", "fingerprint": "8424db9c75e04ba4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["provenance", "git-history", "generated-repo-pattern"]}}, {"ruleId": "scanner-51a2afab6ca294e1", "level": "warning", "message": {"text": "`fetch()` without try/.catch or AbortSignal \u2014 frontend/src/components/replayer/RangePanel.tsx:17"}, "properties": {"repobilityId": "420135b72baa92b6", "scanner": "scanner-primary", "fingerprint": "51a2afab6ca294e1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-e81dc82d57550202", "level": "none", "message": {"text": "Commented-code block (8 lines) in frontend/src/components/hud/PokerTableV3.tsx:208"}, "properties": {"repobilityId": "1ab69fb33f7f2adf", "scanner": "scanner-primary", "fingerprint": "e81dc82d57550202", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-87d19055c6947e65", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/components/hud/DashboardV2.tsx:47"}, "properties": {"repobilityId": "3011943732d81304", "scanner": "scanner-primary", "fingerprint": "87d19055c6947e65", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1cce3ad201f35456", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/lib/hhImport.ts:1"}, "properties": {"repobilityId": "c7a730695fc18d9d", "scanner": "scanner-primary", "fingerprint": "1cce3ad201f35456", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-d884838dd33b1c3b", "level": "none", "message": {"text": "Commented-code block (5 lines) in frontend/src/pages/Replayer.tsx:152"}, "properties": {"repobilityId": "8ef317c8e1e0bf81", "scanner": "scanner-primary", "fingerprint": "d884838dd33b1c3b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-e6d68189c53f500f", "level": "none", "message": {"text": "Commented-code block (6 lines) in frontend/src/hooks/useDashboardLayout.ts:21"}, "properties": {"repobilityId": "5268664b7fd68313", "scanner": "scanner-primary", "fingerprint": "e6d68189c53f500f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-3ada643d8d9681c7", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/tests/test_postflop_evaluator.py:257"}, "properties": {"repobilityId": "9da935ef6f6f059c", "scanner": "scanner-primary", "fingerprint": "3ada643d8d9681c7", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-55da378cc9381831", "level": "note", "message": {"text": "Legacy-named symbol `test_study_plan_cache_key_v2` in backend/tests/test_study_plan.py:114"}, "properties": {"repobilityId": "3917d8a18053095e", "scanner": "scanner-primary", "fingerprint": "55da378cc9381831", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-1ba6be38a4c2e362", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/tests/test_recent_regressions.py:93"}, "properties": {"repobilityId": "8cb22731122cebb6", "scanner": "scanner-primary", "fingerprint": "1ba6be38a4c2e362", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-b11e42bbdeea6a7e", "level": "note", "message": {"text": "Legacy-named symbol `coach_students_v2` in backend/api/app.py:2061"}, "properties": {"repobilityId": "e2632fc6f63bfe2e", "scanner": "scanner-primary", "fingerprint": "b11e42bbdeea6a7e", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-674b674c9444a8d3", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/api/app.py:1419"}, "properties": {"repobilityId": "14759da7b5d64c80", "scanner": "scanner-primary", "fingerprint": "674b674c9444a8d3", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-7462d2c23f3d9e4a", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/docs/external_ranges/greenline_ranges.ts:338"}, "properties": {"repobilityId": "2da15bf16c577923", "scanner": "scanner-primary", "fingerprint": "7462d2c23f3d9e4a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-532866daef32db19", "level": "note", "message": {"text": "Legacy-named symbol `purged_solver_cli_nodes_backup` in backend/scripts/postflop_correctness_audit.py:115"}, "properties": {"repobilityId": "6295c48d3abe5f22", "scanner": "scanner-primary", "fingerprint": "532866daef32db19", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-d9c6397ae4c6a78a", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/scripts/build_coach_review_t27.py:19"}, "properties": {"repobilityId": "62929675777c86fa", "scanner": "scanner-primary", "fingerprint": "d9c6397ae4c6a78a", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1f39d34415815252", "level": "note", "message": {"text": "Legacy-named symbol `parse_spot_v2` in backend/scripts/parse_gw_har.py:46"}, "properties": {"repobilityId": "3bed573a47211f30", "scanner": "scanner-primary", "fingerprint": "1f39d34415815252", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-4b0244a4a7787f5b", "level": "none", "message": {"text": "Commented-code block (10 lines) in backend/scripts/parse_gw_har.py:242"}, "properties": {"repobilityId": "35d165fe3ad8ea2c", "scanner": "scanner-primary", "fingerprint": "4b0244a4a7787f5b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-ba02bd092bf9c50b", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/scripts/seed_preflop_gw.py:155"}, "properties": {"repobilityId": "f655f5c838584b99", "scanner": "scanner-primary", "fingerprint": "ba02bd092bf9c50b", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-1b8d144d3fcadfba", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/scripts/scan_card_invariants.py:270"}, "properties": {"repobilityId": "4a04c46d6954e8e6", "scanner": "scanner-primary", "fingerprint": "1b8d144d3fcadfba", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-7863e28e09f4e9d1", "level": "warning", "message": {"text": "Network/subprocess call without timeout or try/except \u2014 backend/scripts/gto_validation/playwright_compare.py:583"}, "properties": {"repobilityId": "564ea46ccf184de7", "scanner": "scanner-primary", "fingerprint": "7863e28e09f4e9d1", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "fragile-runtime", "robustness"]}}, {"ruleId": "scanner-262ff8dd20cd1903", "level": "none", "message": {"text": "Commented-code block (7 lines) in backend/scripts/gto_validation/console_script.js:5"}, "properties": {"repobilityId": "c09cda565390b783", "scanner": "scanner-primary", "fingerprint": "262ff8dd20cd1903", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c0ca2523246e3ae0", "level": "none", "message": {"text": "Commented-code block (7 lines) in backend/gto_bot/solver_api/_gw_subprocess.py:36"}, "properties": {"repobilityId": "c025281f7f1b4805", "scanner": "scanner-primary", "fingerprint": "c0ca2523246e3ae0", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c34bf086c954c97f", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/gto_bot/solver_api/server.py:728"}, "properties": {"repobilityId": "5049d9aa141ef4e6", "scanner": "scanner-primary", "fingerprint": "c34bf086c954c97f", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-50edb7ec16691027", "level": "note", "message": {"text": "Stub function `log_message` (body is just `pass`/`return`) \u2014 backend/gto_bot/solver_api/server.py:1232"}, "properties": {"repobilityId": "99e9204f4af84dbf", "scanner": "scanner-primary", "fingerprint": "50edb7ec16691027", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "empty-handler", "dead-code"]}}, {"ruleId": "scanner-68c745da7bc7206a", "level": "note", "message": {"text": "Legacy-named symbol `is_legacy` in backend/database/repositories.py:106"}, "properties": {"repobilityId": "f05df0c2a152dfd4", "scanner": "scanner-primary", "fingerprint": "68c745da7bc7206a", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-0a546f25a3155600", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/leaklab/gto_utils.py:18"}, "properties": {"repobilityId": "c8584cda44e08672", "scanner": "scanner-primary", "fingerprint": "0a546f25a3155600", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-9a067178fce79c97", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/leaklab/parser.py:15"}, "properties": {"repobilityId": "add7fa31e0e23a94", "scanner": "scanner-primary", "fingerprint": "9a067178fce79c97", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-a330e0a24cba2805", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/leaklab/preflop_gto_ranges.py:192"}, "properties": {"repobilityId": "b20f970db98de30d", "scanner": "scanner-primary", "fingerprint": "a330e0a24cba2805", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-024eaaf6e09c9e51", "level": "none", "message": {"text": "Commented-code block (7 lines) in backend/leaklab/hand_state_builder.py:6"}, "properties": {"repobilityId": "37914b15b6270504", "scanner": "scanner-primary", "fingerprint": "024eaaf6e09c9e51", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-98b766411268112b", "level": "note", "message": {"text": "Legacy-named symbol `study_plan_agentic_v1` in backend/leaklab/llm_explainer.py:1401"}, "properties": {"repobilityId": "3820ba332d817977", "scanner": "scanner-primary", "fingerprint": "98b766411268112b", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-3483674361f53abc", "level": "none", "message": {"text": "Commented-code block (8 lines) in backend/leaklab/llm_explainer.py:1229"}, "properties": {"repobilityId": "98606a2438adcabf", "scanner": "scanner-primary", "fingerprint": "3483674361f53abc", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-dad2190bb1e2d1a3", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/leaklab/icm.py:110"}, "properties": {"repobilityId": "2fd188d26ab0c25c", "scanner": "scanner-primary", "fingerprint": "dad2190bb1e2d1a3", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-78d85e8a57f6c0c4", "level": "none", "message": {"text": "Commented-code block (8 lines) in backend/leaklab/gto_solver.py:329"}, "properties": {"repobilityId": "c6a7220ff9db6ee7", "scanner": "scanner-primary", "fingerprint": "78d85e8a57f6c0c4", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-5f3b240bd6a66cb6", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/leaklab/elo_engine.py:44"}, "properties": {"repobilityId": "96098dce86820418", "scanner": "scanner-primary", "fingerprint": "5f3b240bd6a66cb6", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-c1f9c699b4fb1850", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/leaklab/street_math_engine.py:4"}, "properties": {"repobilityId": "75c223e0a6d9c93e", "scanner": "scanner-primary", "fingerprint": "c1f9c699b4fb1850", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-8092cecfc721b285", "level": "note", "message": {"text": "Legacy-named symbol `digest_unsub_v1` in backend/leaklab/email_digest.py:31"}, "properties": {"repobilityId": "11ac7dea0f58116a", "scanner": "scanner-primary", "fingerprint": "8092cecfc721b285", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "legacy-marker", "dead-code"]}}, {"ruleId": "scanner-0ba4c663a25fd04c", "level": "none", "message": {"text": "Commented-code block (5 lines) in backend/leaklab/decision_engine_v11.py:93"}, "properties": {"repobilityId": "2434c244e242f475", "scanner": "scanner-primary", "fingerprint": "0ba4c663a25fd04c", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-0cebe82322e3eb91", "level": "none", "message": {"text": "Commented-code block (6 lines) in backend/leaklab/revalidation/differ.py:231"}, "properties": {"repobilityId": "9f5085e537ae8859", "scanner": "scanner-primary", "fingerprint": "0cebe82322e3eb91", "layer": "quality", "severity": "info", "confidence": 1.0, "tags": ["integrity", "commented-code", "dead-code"]}}, {"ruleId": "scanner-eab8b6346c2579e8", "level": "note", "message": {"text": "57 env vars used in code but missing from .env.example"}, "properties": {"repobilityId": "87503ae5fa8c7c7d", "scanner": "scanner-primary", "fingerprint": "eab8b6346c2579e8", "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": "441c97a8cb421da5", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "5bd33f72f5f10475", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "a5ec37e174695351", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "64733648ffc1c5d3", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "4c4d814cf89e276a", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "f1ac3ed792783830", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "082ac8374630b70b", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "7b9b4d16f67b22ab", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "bc2431cc2781d69c", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "1fcb3bac77e0d4a9", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "b3be9db2d4df032c", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "88537592edfb5174", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "7aa7dbd87d8048e0", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "7afc0502a2154fe8", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "ad58dae59f17e5cd", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "ab4858808a4c23f1", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-49c98f7cedd9c977", "level": "note", "message": {"text": "Near-duplicate function bodies in 4 places"}, "properties": {"repobilityId": "7d1c8782940e4786", "scanner": "scanner-primary", "fingerprint": "49c98f7cedd9c977", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "6f0d67b90d2127a5", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-be46ea126aa5d8dc", "level": "note", "message": {"text": "Near-duplicate function bodies in 3 places"}, "properties": {"repobilityId": "2d9fe9e548f009da", "scanner": "scanner-primary", "fingerprint": "be46ea126aa5d8dc", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-2c04133e54348533", "level": "note", "message": {"text": "Near-duplicate function bodies in 2 places"}, "properties": {"repobilityId": "247bbaff6fa8c708", "scanner": "scanner-primary", "fingerprint": "2c04133e54348533", "layer": "quality", "severity": "low", "confidence": 1.0, "tags": ["integrity", "duplicate", "dry"]}}, {"ruleId": "scanner-c0ab9a5671bb3326", "level": "warning", "message": {"text": "Frontend route `/tournaments/compare` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "properties": {"repobilityId": "820b9a8208206782", "scanner": "scanner-primary", "fingerprint": "c0ab9a5671bb3326", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-9341a9e16d6eee60", "level": "warning", "message": {"text": "Frontend route `/tournaments/:id` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "properties": {"repobilityId": "13842dcb2c2c59f7", "scanner": "scanner-primary", "fingerprint": "9341a9e16d6eee60", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-d2ffd2fe4f714d43", "level": "warning", "message": {"text": "Frontend route `/replayer` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "properties": {"repobilityId": "8fdeaa75323aef06", "scanner": "scanner-primary", "fingerprint": "d2ffd2fe4f714d43", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-0329a9f3cf9d456b", "level": "warning", "message": {"text": "Frontend route `/coach-dashboard/student/:id` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "properties": {"repobilityId": "cc52572358a6c7b3", "scanner": "scanner-primary", "fingerprint": "0329a9f3cf9d456b", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-12d327c7dc9ff393", "level": "warning", "message": {"text": "Frontend route `/coaches/:id` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "properties": {"repobilityId": "1e230882c1b03266", "scanner": "scanner-primary", "fingerprint": "12d327c7dc9ff393", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-d73e1d073c651498", "level": "warning", "message": {"text": "Frontend route `/academy/gto-preflop` has no Link/navigate to it \u2014 frontend/src/App.tsx"}, "properties": {"repobilityId": "29fc34ce4086cb5d", "scanner": "scanner-primary", "fingerprint": "d73e1d073c651498", "layer": "quality", "severity": "medium", "confidence": 1.0, "tags": ["integrity", "orphan-page", "wiring"]}}, {"ruleId": "scanner-59ebce5eb3747afe", "level": "error", "message": {"text": "Dangling fetch: GET /replay/${tournamentId}/${handId} (frontend/src/lib/api.ts:444)"}, "properties": {"repobilityId": "a0b9f0ef5f585f63", "scanner": "scanner-primary", "fingerprint": "59ebce5eb3747afe", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-3ffda38b37343ef7", "level": "error", "message": {"text": "Dangling fetch: POST /player/hands/${handId}/request-gto (frontend/src/lib/api.ts:447)"}, "properties": {"repobilityId": "9b2b6f29dd8b6f01", "scanner": "scanner-primary", "fingerprint": "3ffda38b37343ef7", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-f5e590d0c4368258", "level": "error", "message": {"text": "Dangling fetch: DELETE /history/tournament/${tournamentId} (frontend/src/lib/api.ts:464)"}, "properties": {"repobilityId": "445aabefe06fc748", "scanner": "scanner-primary", "fingerprint": "f5e590d0c4368258", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-cc1aa2008c0b2d31", "level": "error", "message": {"text": "Dangling fetch: GET /player/spots/drill/${decision_id}/analysis (frontend/src/lib/api.ts:830)"}, "properties": {"repobilityId": "1a0f725458f5d20f", "scanner": "scanner-primary", "fingerprint": "cc1aa2008c0b2d31", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-6f5f7732a314bfd0", "level": "error", "message": {"text": "Dangling fetch: POST /player/notifications/${id}/read (frontend/src/lib/api.ts:1013)"}, "properties": {"repobilityId": "9b0618755f8b7f5e", "scanner": "scanner-primary", "fingerprint": "6f5f7732a314bfd0", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-63608fdc45baa573", "level": "error", "message": {"text": "Dangling fetch: GET /player/session-review/${tournamentId} (frontend/src/lib/api.ts:1142)"}, "properties": {"repobilityId": "bd89d3060d601ef9", "scanner": "scanner-primary", "fingerprint": "63608fdc45baa573", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-f7dc8b6705434388", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/level (frontend/src/lib/api.ts:1617)"}, "properties": {"repobilityId": "b12caa80c5a40957", "scanner": "scanner-primary", "fingerprint": "f7dc8b6705434388", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-29ddfbcb0688b938", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/history?days=${days} (frontend/src/lib/api.ts:1620)"}, "properties": {"repobilityId": "6f50a6b5e9d90a29", "scanner": "scanner-primary", "fingerprint": "29ddfbcb0688b938", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-3bfaacd1bbe8a77f", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/stats?days=${days} (frontend/src/lib/api.ts:1623)"}, "properties": {"repobilityId": "8e3e9da7d84e9bb6", "scanner": "scanner-primary", "fingerprint": "3bfaacd1bbe8a77f", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-01dc2ce568434ef8", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/breakdown?days=${days} (frontend/src/lib/api.ts:1626)"}, "properties": {"repobilityId": "417355e8b5123181", "scanner": "scanner-primary", "fingerprint": "01dc2ce568434ef8", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-68a822267f1e42e5", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/replay/${tournamentId}/${handId} (frontend/src/lib/api.ts:1642)"}, "properties": {"repobilityId": "1e29fa5847665eaf", "scanner": "scanner-primary", "fingerprint": "68a822267f1e42e5", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-1964484050ade697", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/study-overrides (frontend/src/lib/api.ts:1645)"}, "properties": {"repobilityId": "5531bac2e83daf57", "scanner": "scanner-primary", "fingerprint": "1964484050ade697", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-e4cde218c1f8c167", "level": "error", "message": {"text": "Dangling fetch: POST /coach/student/${studentId}/study-overrides (frontend/src/lib/api.ts:1653)"}, "properties": {"repobilityId": "38dd2c874d9f3e20", "scanner": "scanner-primary", "fingerprint": "e4cde218c1f8c167", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-c8313fb8075c8326", "level": "error", "message": {"text": "Dangling fetch: DELETE /coach/student/${studentId}/study-overrides/${encodeURIComponent(cardSpot)} (frontend/src/lib/api.ts:1659)"}, "properties": {"repobilityId": "6762a284a14214d5", "scanner": "scanner-primary", "fingerprint": "c8313fb8075c8326", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-8e54cfe0191a4647", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/hand-annotations (frontend/src/lib/api.ts:1664)"}, "properties": {"repobilityId": "296b76e6c9fb4b90", "scanner": "scanner-primary", "fingerprint": "8e54cfe0191a4647", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-2b6b126543f94e23", "level": "error", "message": {"text": "Dangling fetch: POST /coach/student/${studentId}/hand-annotations (frontend/src/lib/api.ts:1673)"}, "properties": {"repobilityId": "da5264674f6c5552", "scanner": "scanner-primary", "fingerprint": "2b6b126543f94e23", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-c99eedcebac0a54b", "level": "error", "message": {"text": "Dangling fetch: DELETE /coach/student/${studentId}/hand-annotations/${decisionId} (frontend/src/lib/api.ts:1679)"}, "properties": {"repobilityId": "f85cc17bd08bdb29", "scanner": "scanner-primary", "fingerprint": "c99eedcebac0a54b", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-d78e23d2bae12b76", "level": "error", "message": {"text": "Dangling fetch: POST /coach/student/${studentId}/baseline (frontend/src/lib/api.ts:1703)"}, "properties": {"repobilityId": "6c5d2cede61c90a5", "scanner": "scanner-primary", "fingerprint": "d78e23d2bae12b76", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-9ae854ae01b47fe3", "level": "error", "message": {"text": "Dangling fetch: DELETE /coach/student/${studentId}/baseline (frontend/src/lib/api.ts:1709)"}, "properties": {"repobilityId": "e4d1744c3cf52f43", "scanner": "scanner-primary", "fingerprint": "9ae854ae01b47fe3", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-8eb6ce75557fdc2c", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/activity-feed?limit=${limit} (frontend/src/lib/api.ts:1714)"}, "properties": {"repobilityId": "164c7c6d5431b7d4", "scanner": "scanner-primary", "fingerprint": "8eb6ce75557fdc2c", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-80cf33adc57f3dc8", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/progress-report (frontend/src/lib/api.ts:1717)"}, "properties": {"repobilityId": "f812d3775008a016", "scanner": "scanner-primary", "fingerprint": "80cf33adc57f3dc8", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-e1d1560713ba7daf", "level": "error", "message": {"text": "Dangling fetch: DELETE /coach/templates/${templateId} (frontend/src/lib/api.ts:1748)"}, "properties": {"repobilityId": "69a0ee658ec525d6", "scanner": "scanner-primary", "fingerprint": "e1d1560713ba7daf", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-67954cbf249c0be1", "level": "error", "message": {"text": "Dangling fetch: GET /coach/student/${studentId}/messages (frontend/src/lib/api.ts:1752)"}, "properties": {"repobilityId": "234f884931677891", "scanner": "scanner-primary", "fingerprint": "67954cbf249c0be1", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-d07b2f63599a3675", "level": "error", "message": {"text": "Dangling fetch: POST /coach/student/${studentId}/messages (frontend/src/lib/api.ts:1755)"}, "properties": {"repobilityId": "235906a609462162", "scanner": "scanner-primary", "fingerprint": "d07b2f63599a3675", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-342cb7a143818b6c", "level": "error", "message": {"text": "Dangling fetch: GET /coaches/${coachUserId} (frontend/src/lib/api.ts:1823)"}, "properties": {"repobilityId": "6c2d754591e2b333", "scanner": "scanner-primary", "fingerprint": "342cb7a143818b6c", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-a3a7c519431006ba", "level": "error", "message": {"text": "Dangling fetch: PATCH /admin/users/${id} (frontend/src/lib/api.ts:2002)"}, "properties": {"repobilityId": "ce6a19d04dd6c6b4", "scanner": "scanner-primary", "fingerprint": "a3a7c519431006ba", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-e3dbb509c1bef800", "level": "error", "message": {"text": "Dangling fetch: DELETE /admin/users/${id} (frontend/src/lib/api.ts:2008)"}, "properties": {"repobilityId": "38eb5701fde53553", "scanner": "scanner-primary", "fingerprint": "e3dbb509c1bef800", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-7226dd44dd24c199", "level": "error", "message": {"text": "Dangling fetch: PATCH /admin/finance/coaches/${paymentId}/pay (frontend/src/lib/api.ts:2019)"}, "properties": {"repobilityId": "97690d7a1609cd25", "scanner": "scanner-primary", "fingerprint": "7226dd44dd24c199", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-25ff4e9d00f08767", "level": "error", "message": {"text": "Dangling fetch: POST /admin/coach-applications/${id}/approve (frontend/src/lib/api.ts:2027)"}, "properties": {"repobilityId": "a10eaabd71de0d90", "scanner": "scanner-primary", "fingerprint": "25ff4e9d00f08767", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-8738d86bea5bae80", "level": "error", "message": {"text": "Dangling fetch: POST /admin/coach-applications/${id}/reject (frontend/src/lib/api.ts:2033)"}, "properties": {"repobilityId": "0f1e1a205c8ab6b7", "scanner": "scanner-primary", "fingerprint": "8738d86bea5bae80", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-9e8be0676dd8f3fb", "level": "error", "message": {"text": "Dangling fetch: POST /coach/${coachId}/contact (frontend/src/lib/api.ts:2172)"}, "properties": {"repobilityId": "5785f2255ffc54ab", "scanner": "scanner-primary", "fingerprint": "9e8be0676dd8f3fb", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-e870e4cecea349df", "level": "error", "message": {"text": "Dangling fetch: GET /coach/${coachId}/contact-thread (frontend/src/lib/api.ts:2178)"}, "properties": {"repobilityId": "9994947e4bb92b10", "scanner": "scanner-primary", "fingerprint": "e870e4cecea349df", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-cd617b64452f888a", "level": "error", "message": {"text": "Dangling fetch: GET /replay/${decisionId}/gto (frontend/src/lib/api.ts:2278)"}, "properties": {"repobilityId": "a387fab6f0e66af9", "scanner": "scanner-primary", "fingerprint": "cd617b64452f888a", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-4740bf309d69296b", "level": "error", "message": {"text": "Dangling fetch: POST /admin/support-tickets/${ticketId}/reply (frontend/src/lib/api.ts:2304)"}, "properties": {"repobilityId": "a49902d251c065d8", "scanner": "scanner-primary", "fingerprint": "4740bf309d69296b", "layer": "api", "severity": "high", "confidence": 1.0, "tags": ["wiring", "dangling-fetch", "helper:request"]}}, {"ruleId": "scanner-71534283a20e67bd", "level": "note", "message": {"text": "Unused endpoint: ANY /analyze"}, "properties": {"repobilityId": "416f8fb6192f2474", "scanner": "scanner-primary", "fingerprint": "71534283a20e67bd", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ecc9df8fded662dc", "level": "note", "message": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>"}, "properties": {"repobilityId": "41527517fc26b002", "scanner": "scanner-primary", "fingerprint": "ecc9df8fded662dc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1662fb6b0e728954", "level": "note", "message": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>/phase_analysis"}, "properties": {"repobilityId": "d1e280a9c0c67816", "scanner": "scanner-primary", "fingerprint": "1662fb6b0e728954", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8f16d64535200fa0", "level": "note", "message": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>/texture_analysis"}, "properties": {"repobilityId": "728976ddf0ec8a56", "scanner": "scanner-primary", "fingerprint": "8f16d64535200fa0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a06fef680a455a2e", "level": "note", "message": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>/narrative"}, "properties": {"repobilityId": "b74bcee8b4a3225b", "scanner": "scanner-primary", "fingerprint": "a06fef680a455a2e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9325a38a30093218", "level": "note", "message": {"text": "Unused endpoint: ANY /history/tournaments/compare"}, "properties": {"repobilityId": "cacc975676082805", "scanner": "scanner-primary", "fingerprint": "9325a38a30093218", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6037b0738ebd14c4", "level": "note", "message": {"text": "Unused endpoint: ANY /history/tournament/<tournament_id>/report.pdf"}, "properties": {"repobilityId": "9635526357f414f8", "scanner": "scanner-primary", "fingerprint": "6037b0738ebd14c4", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-38f537f58466000e", "level": "note", "message": {"text": "Unused endpoint: ANY /history/evolution"}, "properties": {"repobilityId": "5b87ec4f68051fb6", "scanner": "scanner-primary", "fingerprint": "38f537f58466000e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-53b8eff612b2ea41", "level": "note", "message": {"text": "Unused endpoint: ANY /player/leak-roi"}, "properties": {"repobilityId": "9c79f93d806ce8a8", "scanner": "scanner-primary", "fingerprint": "53b8eff612b2ea41", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-747b20e72c8276cf", "level": "note", "message": {"text": "Unused endpoint: ANY /player/ev-leaks"}, "properties": {"repobilityId": "69d47328f308dc81", "scanner": "scanner-primary", "fingerprint": "747b20e72c8276cf", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-52940c1027ad1d7d", "level": "note", "message": {"text": "Unused endpoint: ANY /player/leak-finder"}, "properties": {"repobilityId": "18c7cd9465e572d9", "scanner": "scanner-primary", "fingerprint": "52940c1027ad1d7d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-aa962ab4908b829a", "level": "note", "message": {"text": "Unused endpoint: ANY /player/gto-quality"}, "properties": {"repobilityId": "118a624dfeac2795", "scanner": "scanner-primary", "fingerprint": "aa962ab4908b829a", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3e20e9e4612965fc", "level": "note", "message": {"text": "Unused endpoint: ANY /player/gto-alignment"}, "properties": {"repobilityId": "279edd1c3a7a9e84", "scanner": "scanner-primary", "fingerprint": "3e20e9e4612965fc", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-34e6e49fbba2003b", "level": "note", "message": {"text": "Unused endpoint: ANY /player/gto-position"}, "properties": {"repobilityId": "8118bdedeb7cba9b", "scanner": "scanner-primary", "fingerprint": "34e6e49fbba2003b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-bdf36d6d16ed82ed", "level": "note", "message": {"text": "Unused endpoint: ANY /player/gto-alignment-matrix"}, "properties": {"repobilityId": "214dda48797f232f", "scanner": "scanner-primary", "fingerprint": "bdf36d6d16ed82ed", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-64bce77733cee5f8", "level": "note", "message": {"text": "Unused endpoint: ANY /player/results-vs-gto"}, "properties": {"repobilityId": "9d01498ebf16c8d0", "scanner": "scanner-primary", "fingerprint": "64bce77733cee5f8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-65ad0fa20fb785a9", "level": "note", "message": {"text": "Unused endpoint: ANY /player/spots/drill"}, "properties": {"repobilityId": "0cf08b5b4e8c065e", "scanner": "scanner-primary", "fingerprint": "65ad0fa20fb785a9", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-881c2b423179ee5f", "level": "note", "message": {"text": "Unused endpoint: ANY /player/notifications/<int:notif_id>/read"}, "properties": {"repobilityId": "b1c5d2799aa8ac72", "scanner": "scanner-primary", "fingerprint": "881c2b423179ee5f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-31540c0cf431a7ce", "level": "note", "message": {"text": "Unused endpoint: ANY /player/sparring/hand"}, "properties": {"repobilityId": "85d6895bde0998b0", "scanner": "scanner-primary", "fingerprint": "31540c0cf431a7ce", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-6995e9bc5033ccd5", "level": "note", "message": {"text": "Unused endpoint: ANY /player/session-review/<int:tournament_id>"}, "properties": {"repobilityId": "ab64cd764159eaf9", "scanner": "scanner-primary", "fingerprint": "6995e9bc5033ccd5", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-ded8f6bb52898936", "level": "note", "message": {"text": "Unused endpoint: ANY /player/spots/drill/<int:decision_id>/analysis"}, "properties": {"repobilityId": "b027b9c1d2ee0cea", "scanner": "scanner-primary", "fingerprint": "ded8f6bb52898936", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-c108632ee68eb50b", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/level"}, "properties": {"repobilityId": "b0e0c01db079437a", "scanner": "scanner-primary", "fingerprint": "c108632ee68eb50b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8f4790563ea02356", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/history"}, "properties": {"repobilityId": "22024a19cf1c65b5", "scanner": "scanner-primary", "fingerprint": "8f4790563ea02356", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-fcf55248fca0b445", "level": "note", "message": {"text": "Unused endpoint: ANY /gto/status"}, "properties": {"repobilityId": "d77bf6ec48771da8", "scanner": "scanner-primary", "fingerprint": "fcf55248fca0b445", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-14854d084b16ac21", "level": "note", "message": {"text": "Unused endpoint: ANY /analyze/guest"}, "properties": {"repobilityId": "2a00f23d8257e583", "scanner": "scanner-primary", "fingerprint": "14854d084b16ac21", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-3b50f7f56170792f", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/templates/<int:template_id>"}, "properties": {"repobilityId": "443195194babeeb1", "scanner": "scanner-primary", "fingerprint": "3b50f7f56170792f", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-1623b8481916e644", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/messages"}, "properties": {"repobilityId": "a2209f03230fd54b", "scanner": "scanner-primary", "fingerprint": "1623b8481916e644", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0ffdaccff2abb126", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/<int:coach_id>/contact"}, "properties": {"repobilityId": "277cf9fb5b0d2aed", "scanner": "scanner-primary", "fingerprint": "0ffdaccff2abb126", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-88c4d999ea928aa8", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/<int:coach_id>/contact-thread"}, "properties": {"repobilityId": "92a30550896523f8", "scanner": "scanner-primary", "fingerprint": "88c4d999ea928aa8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-b46f0a1933b973ee", "level": "note", "message": {"text": "Unused endpoint: ANY /coaches"}, "properties": {"repobilityId": "466bc23dd290e98c", "scanner": "scanner-primary", "fingerprint": "b46f0a1933b973ee", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d6417adc32d4a2e0", "level": "note", "message": {"text": "Unused endpoint: ANY /coaches/<int:coach_user_id>"}, "properties": {"repobilityId": "e127592c1e023e85", "scanner": "scanner-primary", "fingerprint": "d6417adc32d4a2e0", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-2d4aa15b5fc0638b", "level": "note", "message": {"text": "Unused endpoint: ANY /coaches/<int:coach_user_id>/reviews"}, "properties": {"repobilityId": "8f17478233acd368", "scanner": "scanner-primary", "fingerprint": "2d4aa15b5fc0638b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9c229dcb199c0527", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/students-legacy"}, "properties": {"repobilityId": "de0013ac6e8ea4f3", "scanner": "scanner-primary", "fingerprint": "9c229dcb199c0527", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e18bcc5a87572c9d", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/stats"}, "properties": {"repobilityId": "106387adfab78d8a", "scanner": "scanner-primary", "fingerprint": "e18bcc5a87572c9d", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0485e104510a28be", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/breakdown"}, "properties": {"repobilityId": "41642e39aaab8a37", "scanner": "scanner-primary", "fingerprint": "0485e104510a28be", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-a0c6940ee5348e54", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/tournament/<tournament_id>"}, "properties": {"repobilityId": "28d3eca619947a29", "scanner": "scanner-primary", "fingerprint": "a0c6940ee5348e54", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e4a694e91a8bc74e", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/worst-decisions"}, "properties": {"repobilityId": "7523a7f6eab62806", "scanner": "scanner-primary", "fingerprint": "e4a694e91a8bc74e", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-135e8fc09e1f6f97", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/study-plan"}, "properties": {"repobilityId": "61494e5d5491972c", "scanner": "scanner-primary", "fingerprint": "135e8fc09e1f6f97", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-8fea7367b5a559bd", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/replay/<tournament_id>/<hand_id>"}, "properties": {"repobilityId": "94bb6b142691c72f", "scanner": "scanner-primary", "fingerprint": "8fea7367b5a559bd", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d74931ca0465ad56", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/study-overrides"}, "properties": {"repobilityId": "b29d13f3d0195dda", "scanner": "scanner-primary", "fingerprint": "d74931ca0465ad56", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-0677839bc0aa4063", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/study-overrides/<path:card_spot>"}, "properties": {"repobilityId": "469825f5a85fdb6b", "scanner": "scanner-primary", "fingerprint": "0677839bc0aa4063", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d5d3ea592b147cd6", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/hand-annotations"}, "properties": {"repobilityId": "c9f2280ba1a1df75", "scanner": "scanner-primary", "fingerprint": "d5d3ea592b147cd6", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-52a26e7f034b53a1", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/hand-annotations/<int:decision_id>"}, "properties": {"repobilityId": "c7ff7bf42118c008", "scanner": "scanner-primary", "fingerprint": "52a26e7f034b53a1", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-f43d5eef81769133", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/baseline"}, "properties": {"repobilityId": "1491d20d8a076b81", "scanner": "scanner-primary", "fingerprint": "f43d5eef81769133", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-37c1078e7494b80b", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/activity-feed"}, "properties": {"repobilityId": "e0068c3edfd84ef4", "scanner": "scanner-primary", "fingerprint": "37c1078e7494b80b", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-e2587c543e24eca8", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/student/<int:student_id>/progress-report"}, "properties": {"repobilityId": "a693a66b70d565bc", "scanner": "scanner-primary", "fingerprint": "e2587c543e24eca8", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-cabc7930354e2d54", "level": "note", "message": {"text": "Unused endpoint: ANY /coach/my-review"}, "properties": {"repobilityId": "2c9b087ab4e53f33", "scanner": "scanner-primary", "fingerprint": "cabc7930354e2d54", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-9bfb5ccc8c007354", "level": "note", "message": {"text": "Unused endpoint: ANY /analyze/hand-coach"}, "properties": {"repobilityId": "71e90d3a998b4b21", "scanner": "scanner-primary", "fingerprint": "9bfb5ccc8c007354", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d6ef036b134356e3", "level": "note", "message": {"text": "Unused endpoint: ANY /study/plan"}, "properties": {"repobilityId": "9242fb6c7bed7fea", "scanner": "scanner-primary", "fingerprint": "d6ef036b134356e3", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}, {"ruleId": "scanner-d714fdf0b62943ca", "level": "note", "message": {"text": "Unused endpoint: ANY /analyze/replay-coach"}, "properties": {"repobilityId": "51f6af6956ac2444", "scanner": "scanner-primary", "fingerprint": "d714fdf0b62943ca", "layer": "api", "severity": "low", "confidence": 1.0, "tags": ["wiring", "unused-endpoint"]}}]}]}