{"schema_version":"2","scorer_version":"0.1.0","scoring_version":"prov-5+qual-2+sec-2","generated_at":"2026-11-14T14:52:06.053879Z","repo":{"ref":{"host":"github.com","owner":"lihaohong6","name":"Blue-Archive-bot"},"default_branch":"master","clone_url":"https://github.com/lihaohong6/Blue-Archive-bot.git","html_url":"https://github.com/lihaohong6/Blue-Archive-bot","description":null,"stars":0,"forks":2,"is_fork":false,"is_archived":false,"is_private":false,"size_kb":405,"primary_language":"Python","license_spdx":"AGPL-3.0","created_at":"2023-12-16T05:19:43Z","pushed_at":"2026-11-12T09:08:33Z","security_policy_url":null,"distribution":{"owner_created_at":"2015-05-21T13:08:12Z","owner_type":"User","release_assets":[]}},"commit_sha":"e17d00e98b2475067edbdbb938f2a697c02fabf7","profile":{"lines_by_language":{"Python":5998,"JavaScript":47,"Shell":3},"files_by_category":{"source":46,"config":5,"docs":4,"other":1,"generated":1},"source_lines":6048,"test_lines":0},"pillars":{"ai_provenance":{"score":0.6,"confidence":0.65,"coverage":1.0,"label":"possible","breakdown":{"attributed_share":0.006,"suspected_share":0.2295,"estimated_share":0.006,"ai_artifacts":0.0,"flagged_work_units":1.0,"flagged_releases":null,"style_index":0.0},"summary":"Weak signals consistent with AI-assisted development. 1 commit(s) carry explicit AI attribution, too few to characterize the codebase."},"quality":{"score":37.7,"confidence":0.9,"coverage":1.0,"label":"poor","breakdown":{"complexity":50.8,"duplication":98.3,"lint":16.9,"testing":0.0,"docs":45.0,"type_safety":40.0,"process":null},"summary":"Code quality is poor: test-to-source ratio 0.00, no CI test run detected; 23% of function code in complex or long functions; 0% duplicated lines. Weakest area: testing."},"security":{"score":66.3,"confidence":0.85,"coverage":1.0,"label":"weak","breakdown":{"secrets":100.0,"sast":87.5,"dependencies":36.2,"ci_actions":null,"posture":0.0,"scorecard":null},"summary":"Security posture is weak: 52 known vulnerabilities in 5 dependencies; 1 high-severity SAST findings. Weakest area: posture."}},"analyzer_results":[{"analyzer":"sec-scorecard","pillar":"security","status":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":"no published OpenSSF Scorecard result for this repo"},{"analyzer":"sec-registry","pillar":"security","status":"ok","tool_version":null,"metrics":{"declared":6.0,"checked":6.0,"missing":0.0,"recent":0.0,"lookup_errors":0.0},"findings":[],"evidence":[],"data":{"phantom":false},"error":null},{"analyzer":"ai-attribution","pillar":"ai_provenance","status":"ok","tool_version":"signatures-v1","metrics":{"commits":126.0,"attributed_commits":1.0,"attributed_commit_share":0.007936507936507936,"effective_loc":11314.0,"attributed_loc":68.0,"attributed_loc_share":0.006010252784161216,"tools_detected":1.0},"findings":[],"evidence":[{"kind":"attribution-summary","description":"Claude Code: 1 attributed commits, 68 lines added","ref":null,"url":null,"weight":1.0},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"e17d00e98b2475067edbdbb938f2a697c02fabf7","url":"https://github.com/lihaohong6/Blue-Archive-bot/commit/e17d00e98b2475067edbdbb938f2a697c02fabf7","weight":0.9}],"data":{"attributed_loc_by_commit":{"e17d00e98b2475067edbdbb938f2a697c02fabf7":68},"tools":{"claude-code":{"name":"Claude Code","commits":1,"loc":68,"first_seen":1794473367,"last_seen":1794473367}},"monthly":{"2023-12":{"loc":728,"attributed_loc":0},"2024-01":{"loc":1102,"attributed_loc":0},"2024-02":{"loc":52,"attributed_loc":0},"2024-04":{"loc":277,"attributed_loc":0},"2024-05":{"loc":176,"attributed_loc":0},"2024-06":{"loc":139,"attributed_loc":0},"2024-07":{"loc":295,"attributed_loc":0},"2024-08":{"loc":31,"attributed_loc":0},"2024-09":{"loc":9,"attributed_loc":0},"2024-10":{"loc":984,"attributed_loc":0},"2024-11":{"loc":374,"attributed_loc":0},"2024-12":{"loc":0,"attributed_loc":0},"2025-01":{"loc":39,"attributed_loc":0},"2025-02":{"loc":62,"attributed_loc":0},"2025-03":{"loc":24,"attributed_loc":0},"2025-04":{"loc":215,"attributed_loc":0},"2025-05":{"loc":233,"attributed_loc":0},"2025-07":{"loc":3,"attributed_loc":0},"2025-08":{"loc":35,"attributed_loc":0},"2025-10":{"loc":193,"attributed_loc":0},"2025-11":{"loc":289,"attributed_loc":0},"2026-07":{"loc":78,"attributed_loc":0},"2026-08":{"loc":160,"attributed_loc":0},"2026-09":{"loc":2095,"attributed_loc":0},"2026-10":{"loc":3653,"attributed_loc":0},"2026-11":{"loc":68,"attributed_loc":68}}},"error":null},{"analyzer":"ai-artifacts","pillar":"ai_provenance","status":"ok","tool_version":"signatures-v1","metrics":{"artifacts":0.0,"workflow_agents":0.0,"tools_configured":0.0},"findings":[],"evidence":[],"data":{"artifacts":[],"workflows":[],"tools":[]},"error":null},{"analyzer":"ai-velocity","pillar":"ai_provenance","status":"ok","tool_version":"prov-4","metrics":{"work_units":95.0,"flagged_units":1.0,"pre_ai_era_bursts":0.0,"pre_ai_era_measured_loc":0.0,"pre_ai_era_burst_loc":0.0,"measured_loc":11314.0,"flagged_loc":2597.0,"flagged_loc_share":0.22953862471274528,"max_loc_per_hour":637.4744306559389,"median_loc_per_hour":40.11220196353436,"pr_timed_units":0.0,"excluded_import_loc":0.0},"findings":[],"evidence":[{"kind":"velocity-burst","description":"2,597 lines of first-party code in ~4.1h (637 lines/hour, 2 commit session)","ref":"f07ecf84e41a469007d3bb99e794f513cf54a1de","url":"https://github.com/lihaohong6/Blue-Archive-bot/commit/f07ecf84e41a469007d3bb99e794f513cf54a1de","weight":0.19124232919678166}],"data":{"flagged_loc_by_commit":{"7c6bb1e30d8ff5e50a8c5b5b4e1f7b1635b9fa29":2590,"f07ecf84e41a469007d3bb99e794f513cf54a1de":7},"excluded_import_commits":[]},"error":null},{"analyzer":"ai-release-velocity","pillar":"ai_provenance","status":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"ai-stylometry","pillar":"ai_provenance","status":"ok","tool_version":null,"metrics":{"lines_scanned":6048.0,"index":0.0,"count:narrated_steps":0.0,"per_kloc:narrated_steps":0.0,"files:narrated_steps":0.0,"count:placeholder":0.0,"per_kloc:placeholder":0.0,"files:placeholder":0.0,"count:emoji_in_code":0.0,"per_kloc:emoji_in_code":0.0,"files:emoji_in_code":0.0,"count:assistant_voice":0.0,"per_kloc:assistant_voice":0.0,"files:assistant_voice":0.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-secrets","pillar":"security","status":"ok","tool_version":"gitleaks 8.30.1","metrics":{"secrets_current":0.0,"secrets_history":0.0,"secrets_nonprod":0.0,"secrets_low_confidence":0.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-sast","pillar":"security","status":"ok","tool_version":"opengrep 1.33.1; rules f1d2b562b414","metrics":{"findings":3.0,"findings_high":1.0,"findings_medium":2.0,"findings_low":0.0,"weighted_findings":2.3,"scanned_lines":6048.0,"parse_errors":1.0},"findings":[{"rule_id":"opengrep/python.lang.security.audit.subprocess-shell-true","severity":"high","message":"Found 'subprocess' function 'run' with 'shell=True'. This is dangerous because this call will spawn the command using a shell process. Doing so propagates current shell settings and variables, which makes it much easier for a malicious actor to execute commands. Use 'shell=False' instead. [confidence medium]","path":"portrait_spirite.py","line":146,"fingerprint":"python.lang.security.audit.subprocess-shell-true:portrait_spirite.py:146"},{"rule_id":"opengrep/python.lang.security.deserialization.avoid-pickle","severity":"medium","message":"Avoid using `pickle`, which is known to lead to code execution vulnerabilities. When unpickling, the serialized data could be manipulated to run arbitrary code. Instead, consider serializing the relevant data as JSON or a similar text-based serialization format. [confidence low]","path":"utils.py","line":51,"fingerprint":"python.lang.security.deserialization.avoid-pickle:utils.py:51"},{"rule_id":"opengrep/python.lang.security.deserialization.avoid-pickle","severity":"medium","message":"Avoid using `pickle`, which is known to lead to code execution vulnerabilities. When unpickling, the serialized data could be manipulated to run arbitrary code. Instead, consider serializing the relevant data as JSON or a similar text-based serialization format. [confidence low]","path":"utils.py","line":62,"fingerprint":"python.lang.security.deserialization.avoid-pickle:utils.py:62"}],"evidence":[],"data":{"rulesets":["python","javascript","bash"]},"error":null},{"analyzer":"sec-deps","pillar":"security","status":"ok","tool_version":"osv-scanner version: 2.7.1","metrics":{"vulnerable_packages":5.0,"vulnerabilities":52.0,"vulns_critical":8.0,"vulns_high":30.0,"vulns_medium":13.0,"vulns_low":0.0,"vulns_unknown":1.0,"penalty":61.0},"findings":[{"rule_id":"osv/GHSA-9v8h-qqgm-4m35","severity":"critical","message":"brotli@1.2.0 (PyPI) is affected by PYSEC-2026-4322, GHSA-9v8h-qqgm-4m35","path":"uv.lock","line":null,"fingerprint":"brotli@1.2.0 (PyPI):GHSA-9v8h-qqgm-4m35"},{"rule_id":"osv/GHSA-6q48-6c7w-9gw2","severity":"critical","message":"certifi@2026.7.22 (PyPI) is affected by PYSEC-2026-4320, GHSA-6q48-6c7w-9gw2","path":"uv.lock","line":null,"fingerprint":"certifi@2026.7.22 (PyPI):GHSA-6q48-6c7w-9gw2"},{"rule_id":"osv/GHSA-5x8w-8jj5-q52h","severity":"critical","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4330, GHSA-5x8w-8jj5-q52h","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-5x8w-8jj5-q52h"},{"rule_id":"osv/GHSA-8g5g-8vmr-9782","severity":"critical","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4332, GHSA-8g5g-8vmr-9782","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-8g5g-8vmr-9782"},{"rule_id":"osv/GHSA-v9pv-5gc8-w2m6","severity":"critical","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4339, GHSA-v9pv-5gc8-w2m6","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-v9pv-5gc8-w2m6"},{"rule_id":"osv/GHSA-xvh5-g6gv-559v","severity":"critical","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4363, GHSA-xvh5-g6gv-559v","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-xvh5-g6gv-559v"},{"rule_id":"osv/GHSA-332p-7hrc-92wf","severity":"critical","message":"pillow@12.3.0 (PyPI) is affected by GHSA-332p-7hrc-92wf","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-332p-7hrc-92wf"},{"rule_id":"osv/GHSA-w889-685w-c8fh","severity":"critical","message":"pillow@12.3.0 (PyPI) is affected by GHSA-w889-685w-c8fh","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-w889-685w-c8fh"},{"rule_id":"osv/GHSA-27h8-gf7j-v5hc","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4326, GHSA-27h8-gf7j-v5hc","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-27h8-gf7j-v5hc"},{"rule_id":"osv/GHSA-4558-3h8r-v8xp","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4327, GHSA-4558-3h8r-v8xp","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-4558-3h8r-v8xp"},{"rule_id":"osv/GHSA-4rr5-89j8-mwwm","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4328, GHSA-4rr5-89j8-mwwm","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-4rr5-89j8-mwwm"},{"rule_id":"osv/GHSA-58r4-6rv3-gfh8","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4329, GHSA-58r4-6rv3-gfh8","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-58r4-6rv3-gfh8"},{"rule_id":"osv/GHSA-7mwm-ghpf-9vrm","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4331, GHSA-7mwm-ghpf-9vrm","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-7mwm-ghpf-9vrm"},{"rule_id":"osv/GHSA-cp9v-662q-vvx9","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4333, GHSA-cp9v-662q-vvx9","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-cp9v-662q-vvx9"},{"rule_id":"osv/GHSA-pchr-8j38-3x4p","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4334, GHSA-pchr-8j38-3x4p","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-pchr-8j38-3x4p"},{"rule_id":"osv/GHSA-xgh8-jp6q-p5x8","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4335, GHSA-xgh8-jp6q-p5x8","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-xgh8-jp6q-p5x8"},{"rule_id":"osv/GHSA-g842-9rc4-69pw","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4338, GHSA-g842-9rc4-69pw","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-g842-9rc4-69pw"},{"rule_id":"osv/GHSA-3j72-p6qg-6xp7","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4341, GHSA-3j72-p6qg-6xp7","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-3j72-p6qg-6xp7"},{"rule_id":"osv/GHSA-g4qv-2jxx-769h","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4342, GHSA-g4qv-2jxx-769h","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-g4qv-2jxx-769h"},{"rule_id":"osv/GHSA-9v9v-9qvf-h2hj","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4343, GHSA-9v9v-9qvf-h2hj","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-9v9v-9qvf-h2hj"},{"rule_id":"osv/GHSA-22hg-r758-rrw9","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-22hg-r758-rrw9","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-22hg-r758-rrw9"},{"rule_id":"osv/GHSA-5xm2-6676-qcp9","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-5xm2-6676-qcp9","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-5xm2-6676-qcp9"},{"rule_id":"osv/GHSA-65qm-jvmh-6pqg","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-65qm-jvmh-6pqg","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-65qm-jvmh-6pqg"},{"rule_id":"osv/GHSA-78g4-xqwv-q3g8","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-78g4-xqwv-q3g8","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-78g4-xqwv-q3g8"},{"rule_id":"osv/GHSA-c6hw-5grf-ff96","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-c6hw-5grf-ff96","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-c6hw-5grf-ff96"},{"rule_id":"osv/GHSA-f2g6-542v-9j58","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-f2g6-542v-9j58","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-f2g6-542v-9j58"},{"rule_id":"osv/GHSA-g7cr-3p24-7wf7","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-g7cr-3p24-7wf7","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-g7cr-3p24-7wf7"},{"rule_id":"osv/GHSA-gg2r-wvfm-q9rx","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-gg2r-wvfm-q9rx","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-gg2r-wvfm-q9rx"},{"rule_id":"osv/GHSA-j4m9-6w36-pw47","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-j4m9-6w36-pw47","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-j4m9-6w36-pw47"},{"rule_id":"osv/GHSA-jg86-v3jv-hrpm","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-jg86-v3jv-hrpm","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-jg86-v3jv-hrpm"},{"rule_id":"osv/GHSA-mrfp-p49p-3hf2","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-mrfp-p49p-3hf2","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-mrfp-p49p-3hf2"},{"rule_id":"osv/GHSA-p4wg-p73j-c528","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-p4wg-p73j-c528","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-p4wg-p73j-c528"},{"rule_id":"osv/GHSA-q45j-58j2-45rg","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-q45j-58j2-45rg","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-q45j-58j2-45rg"},{"rule_id":"osv/GHSA-xcvg-w56q-r89m","severity":"high","message":"pillow@12.3.0 (PyPI) is affected by GHSA-xcvg-w56q-r89m","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-xcvg-w56q-r89m"},{"rule_id":"osv/GHSA-6655-6qjp-jx7x","severity":"high","message":"soupsieve@2.9.1 (PyPI) is affected by GHSA-6655-6qjp-jx7x","path":"uv.lock","line":null,"fingerprint":"soupsieve@2.9.1 (PyPI):GHSA-6655-6qjp-jx7x"},{"rule_id":"osv/GHSA-mmhr-3c5m-f64f","severity":"high","message":"soupsieve@2.9.1 (PyPI) is affected by GHSA-mmhr-3c5m-f64f","path":"uv.lock","line":null,"fingerprint":"soupsieve@2.9.1 (PyPI):GHSA-mmhr-3c5m-f64f"},{"rule_id":"osv/GHSA-8988-9cw3-xx77","severity":"high","message":"urllib3@2.7.0 (PyPI) is affected by PYSEC-2026-4175, GHSA-8988-9cw3-xx77","path":"uv.lock","line":null,"fingerprint":"urllib3@2.7.0 (PyPI):GHSA-8988-9cw3-xx77"},{"rule_id":"osv/GHSA-vxq7-64xx-v4gw","severity":"high","message":"urllib3@2.7.0 (PyPI) is affected by PYSEC-2026-4177, GHSA-vxq7-64xx-v4gw","path":"uv.lock","line":null,"fingerprint":"urllib3@2.7.0 (PyPI):GHSA-vxq7-64xx-v4gw"},{"rule_id":"osv/GHSA-654x-cwwv-5j9c","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4336, GHSA-654x-cwwv-5j9c","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-654x-cwwv-5j9c"},{"rule_id":"osv/GHSA-p8hx-v2p6-rp84","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4337, GHSA-p8hx-v2p6-rp84","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-p8hx-v2p6-rp84"},{"rule_id":"osv/GHSA-4rm8-3hmm-39fg","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by PYSEC-2026-4340, GHSA-4rm8-3hmm-39fg","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-4rm8-3hmm-39fg"},{"rule_id":"osv/GHSA-24rc-8hj2-v98c","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by GHSA-24rc-8hj2-v98c","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-24rc-8hj2-v98c"},{"rule_id":"osv/GHSA-254f-3936-288h","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by GHSA-254f-3936-288h","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-254f-3936-288h"},{"rule_id":"osv/GHSA-462x-pgg6-55fp","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by GHSA-462x-pgg6-55fp","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-462x-pgg6-55fp"},{"rule_id":"osv/GHSA-74r2-7ff9-mjj2","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by GHSA-74r2-7ff9-mjj2","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-74r2-7ff9-mjj2"},{"rule_id":"osv/GHSA-fc9g-5qg7-mf45","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by GHSA-fc9g-5qg7-mf45","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-fc9g-5qg7-mf45"},{"rule_id":"osv/GHSA-rfgq-q3w2-pmv2","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by GHSA-rfgq-q3w2-pmv2","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-rfgq-q3w2-pmv2"},{"rule_id":"osv/GHSA-vx6w-vv9f-6gvg","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by GHSA-vx6w-vv9f-6gvg","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-vx6w-vv9f-6gvg"},{"rule_id":"osv/GHSA-wqgw-9xfh-qf2g","severity":"medium","message":"pillow@12.3.0 (PyPI) is affected by GHSA-wqgw-9xfh-qf2g","path":"uv.lock","line":null,"fingerprint":"pillow@12.3.0 (PyPI):GHSA-wqgw-9xfh-qf2g"},{"rule_id":"osv/GHSA-4j63-6c4x-wfg4","severity":"medium","message":"soupsieve@2.9.1 (PyPI) is affected by GHSA-4j63-6c4x-wfg4","path":"uv.lock","line":null,"fingerprint":"soupsieve@2.9.1 (PyPI):GHSA-4j63-6c4x-wfg4"},{"rule_id":"osv/GHSA-7g44-g9rc-x53w","severity":"medium","message":"soupsieve@2.9.1 (PyPI) is affected by GHSA-7g44-g9rc-x53w","path":"uv.lock","line":null,"fingerprint":"soupsieve@2.9.1 (PyPI):GHSA-7g44-g9rc-x53w"},{"rule_id":"osv/GHSA-gh4c-6fx4-qh6g","severity":"medium","message":"urllib3@2.7.0 (PyPI) is affected by PYSEC-2026-4176, GHSA-gh4c-6fx4-qh6g","path":"uv.lock","line":null,"fingerprint":"urllib3@2.7.0 (PyPI):GHSA-gh4c-6fx4-qh6g"}],"evidence":[],"data":{"ecosystems":["PyPI"]},"error":null},{"analyzer":"sec-actions","pillar":"security","status":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-posture","pillar":"security","status":"ok","tool_version":null,"metrics":{"check:security_policy":0.0,"check:dependency_updates":0.0,"check:signed_commits":0.0,"check:lockfiles":1.0,"signed_commit_share":0.0079,"unpinned_manifests":0.0},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"sec-distribution","pillar":"security","status":"ok","tool_version":null,"metrics":{"signals":0.0,"binary_assets":0.0,"suspicious":0.0},"findings":[],"evidence":[],"data":{"signals":[],"suspicious":false,"unusual_traction":false,"metadata":true},"error":null},{"analyzer":"qual-complexity","pillar":"quality","status":"ok","tool_version":"lizard 1.25.1","metrics":{"functions":282.0,"function_nloc":3860.0,"mean_ccn":5.4,"p90_ccn":11.0,"complex_functions":14.0,"long_functions":2.0,"many_param_functions":3.0,"risky_nloc_share":0.2259},"findings":[],"evidence":[{"kind":"complex-function","description":"plan_switches in model_viewer/exporter/switches.py: complexity 53, 61 lines","ref":"model_viewer/exporter/switches.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/model_viewer/exporter/switches.py#L221","weight":0.8833333333333333},{"kind":"complex-function","description":"parse_story in story/story_parser.py: complexity 49, 126 lines","ref":"story/story_parser.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/story/story_parser.py#L81","weight":0.8166666666666667},{"kind":"complex-function","description":"mark_props in model_viewer/exporter/props.py: complexity 42, 53 lines","ref":"model_viewer/exporter/props.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/model_viewer/exporter/props.py#L25","weight":0.7},{"kind":"complex-function","description":"add_renderer in model_viewer/exporter/geometry.py: complexity 36, 71 lines","ref":"model_viewer/exporter/geometry.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/model_viewer/exporter/geometry.py#L83","weight":0.6},{"kind":"complex-function","description":"write_glb in model_viewer/exporter/glb.py: complexity 35, 124 lines","ref":"model_viewer/exporter/glb.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/model_viewer/exporter/glb.py#L57","weight":0.5833333333333334},{"kind":"complex-function","description":"runtime_parts in model_viewer/exporter/switches.py: complexity 34, 50 lines","ref":"model_viewer/exporter/switches.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/model_viewer/exporter/switches.py#L79","weight":0.5666666666666667},{"kind":"complex-function","description":"get_scenario_character_id in story/story_utils.py: complexity 31, 84 lines","ref":"story/story_utils.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/story/story_utils.py#L40","weight":0.5166666666666667},{"kind":"complex-function","description":"main in model_viewer/export_models.py: complexity 23, 66 lines","ref":"model_viewer/export_models.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/model_viewer/export_models.py#L41","weight":0.38333333333333336},{"kind":"complex-function","description":"particle_mesh in model_viewer/exporter/fx.py: complexity 22, 26 lines","ref":"model_viewer/exporter/fx.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/model_viewer/exporter/fx.py#L74","weight":0.36666666666666664},{"kind":"complex-function","description":"make_conversation in momotalk.py: complexity 21, 66 lines","ref":"momotalk.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/momotalk.py#L64","weight":0.35}],"data":{},"error":null},{"analyzer":"qual-duplication","pillar":"quality","status":"ok","tool_version":"repotrust-dup-w6","metrics":{"compared_lines":4813.0,"duplicated_lines":14.0,"duplicated_share":0.0029,"files":46.0},"findings":[],"evidence":[{"kind":"duplicate-code","description":"6+ duplicated lines: scripts/transcribe.py:13 and scripts/translate.py:11","ref":"scripts/transcribe.py","url":"https://github.com/lihaohong6/Blue-Archive-bot/blob/e17d00e98b2475067edbdbb938f2a697c02fabf7/scripts/transcribe.py#L13","weight":0.3}],"data":{},"error":null},{"analyzer":"qual-lint","pillar":"quality","status":"ok","tool_version":"opengrep 1.33.1; rules f1d2b562b414","metrics":{"findings":39.0,"weighted_findings":43.0,"scanned_lines":6048.0,"category:best-practice":26.0,"category:correctness":1.0,"category:maintainability":12.0},"findings":[{"rule_id":"opengrep/python.lang.best-practice.arbitrary-sleep","severity":"high","message":"time.sleep() call; did you mean to leave this in?","path":"scripts/manga.py","line":70,"fingerprint":"python.lang.best-practice.arbitrary-sleep:scripts/manga.py:70"},{"rule_id":"opengrep/python.lang.best-practice.arbitrary-sleep","severity":"high","message":"time.sleep() call; did you mean to leave this in?","path":"scripts/translate.py","line":38,"fingerprint":"python.lang.best-practice.arbitrary-sleep:scripts/translate.py:38"},{"rule_id":"opengrep/python.requests.best-practice.use-raise-for-status","severity":"medium","message":"There's an HTTP request made with requests, but the raise_for_status() utility method isn't used. This can result in request errors going unnoticed and your code behaving in unexpected ways, such as if your authorization API returns a 500 error while you're only checking for a 401.","path":"portrait_spirite.py","line":25,"fingerprint":"python.requests.best-practice.use-raise-for-status:portrait_spirite.py:25"},{"rule_id":"opengrep/python.requests.best-practice.use-timeout","severity":"medium","message":"Detected a 'requests' call without a timeout set. By default, 'requests' calls wait until the connection is closed. This means a 'requests' call without a timeout will hang the program if a response is never received. Consider setting a timeout for all 'requests'.","path":"portrait_spirite.py","line":25,"fingerprint":"python.requests.best-practice.use-timeout:portrait_spirite.py:25"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"portrait_spirite.py","line":102,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:portrait_spirite.py:102"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"portrait_spirite.py","line":116,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:portrait_spirite.py:116"},{"rule_id":"opengrep/python.requests.best-practice.use-raise-for-status","severity":"medium","message":"There's an HTTP request made with requests, but the raise_for_status() utility method isn't used. This can result in request errors going unnoticed and your code behaving in unexpected ways, such as if your authorization API returns a 500 error while you're only checking for a 401.","path":"scripts/manga.py","line":42,"fingerprint":"python.requests.best-practice.use-raise-for-status:scripts/manga.py:42"},{"rule_id":"opengrep/python.requests.best-practice.use-timeout","severity":"medium","message":"Detected a 'requests' call without a timeout set. By default, 'requests' calls wait until the connection is closed. This means a 'requests' call without a timeout will hang the program if a response is never received. Consider setting a timeout for all 'requests'.","path":"scripts/manga.py","line":42,"fingerprint":"python.requests.best-practice.use-timeout:scripts/manga.py:42"},{"rule_id":"opengrep/python.requests.best-practice.use-raise-for-status","severity":"medium","message":"There's an HTTP request made with requests, but the raise_for_status() utility method isn't used. This can result in request errors going unnoticed and your code behaving in unexpected ways, such as if your authorization API returns a 500 error while you're only checking for a 401.","path":"scripts/manga_jp.py","line":28,"fingerprint":"python.requests.best-practice.use-raise-for-status:scripts/manga_jp.py:28"},{"rule_id":"opengrep/python.requests.best-practice.use-timeout","severity":"medium","message":"Detected a 'requests' call without a timeout set. By default, 'requests' calls wait until the connection is closed. This means a 'requests' call without a timeout will hang the program if a response is never received. Consider setting a timeout for all 'requests'.","path":"scripts/manga_jp.py","line":28,"fingerprint":"python.requests.best-practice.use-timeout:scripts/manga_jp.py:28"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"scripts/missions.py","line":23,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:scripts/missions.py:23"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"scripts/missions.py","line":39,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:scripts/missions.py:39"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"scripts/missions.py","line":51,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:scripts/missions.py:51"},{"rule_id":"opengrep/python.lang.correctness.use-sys-exit","severity":"medium","message":"Detected use of `exit`. Use `sys.exit` over the python shell `exit` built-in. `exit` is a helper for the interactive shell and may not be available on all Python implementations.","path":"scripts/missions.py","line":74,"fingerprint":"python.lang.correctness.use-sys-exit:scripts/missions.py:74"},{"rule_id":"opengrep/python.requests.best-practice.use-raise-for-status","severity":"medium","message":"There's an HTTP request made with requests, but the raise_for_status() utility method isn't used. This can result in request errors going unnoticed and your code behaving in unexpected ways, such as if your authorization API returns a 500 error while you're only checking for a 401.","path":"scripts/nexon_scrap.py","line":19,"fingerprint":"python.requests.best-practice.use-raise-for-status:scripts/nexon_scrap.py:19"},{"rule_id":"opengrep/python.requests.best-practice.use-timeout","severity":"medium","message":"Detected a 'requests' call without a timeout set. By default, 'requests' calls wait until the connection is closed. This means a 'requests' call without a timeout will hang the program if a response is never received. Consider setting a timeout for all 'requests'.","path":"scripts/nexon_scrap.py","line":19,"fingerprint":"python.requests.best-practice.use-timeout:scripts/nexon_scrap.py:19"},{"rule_id":"opengrep/python.requests.best-practice.use-raise-for-status","severity":"medium","message":"There's an HTTP request made with requests, but the raise_for_status() utility method isn't used. This can result in request errors going unnoticed and your code behaving in unexpected ways, such as if your authorization API returns a 500 error while you're only checking for a 401.","path":"scripts/nexon_scrap.py","line":36,"fingerprint":"python.requests.best-practice.use-raise-for-status:scripts/nexon_scrap.py:36"},{"rule_id":"opengrep/python.requests.best-practice.use-timeout","severity":"medium","message":"Detected a 'requests' call without a timeout set. By default, 'requests' calls wait until the connection is closed. This means a 'requests' call without a timeout will hang the program if a response is never received. Consider setting a timeout for all 'requests'.","path":"scripts/nexon_scrap.py","line":36,"fingerprint":"python.requests.best-practice.use-timeout:scripts/nexon_scrap.py:36"},{"rule_id":"opengrep/python.requests.best-practice.use-raise-for-status","severity":"medium","message":"There's an HTTP request made with requests, but the raise_for_status() utility method isn't used. This can result in request errors going unnoticed and your code behaving in unexpected ways, such as if your authorization API returns a 500 error while you're only checking for a 401.","path":"scripts/nexon_scrap.py","line":49,"fingerprint":"python.requests.best-practice.use-raise-for-status:scripts/nexon_scrap.py:49"},{"rule_id":"opengrep/python.requests.best-practice.use-timeout","severity":"medium","message":"Detected a 'requests' call without a timeout set. By default, 'requests' calls wait until the connection is closed. This means a 'requests' call without a timeout will hang the program if a response is never received. Consider setting a timeout for all 'requests'.","path":"scripts/nexon_scrap.py","line":49,"fingerprint":"python.requests.best-practice.use-timeout:scripts/nexon_scrap.py:49"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"scripts/translate.py","line":10,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:scripts/translate.py:10"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"skills/skill_classification.py","line":26,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:skills/skill_classification.py:26"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"skills/skill_classification.py","line":30,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:skills/skill_classification.py:30"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"skills/skill_classification.py","line":57,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:skills/skill_classification.py:57"},{"rule_id":"opengrep/python.lang.best-practice.unspecified-open-encoding","severity":"medium","message":"Missing 'encoding' parameter. 'open()' uses device locale encodings by default, corrupting files with special characters. Specify the encoding to ensure cross-platform support when opening files in text mode (e.g. encoding=\"utf-8\").","path":"skills/skill_classification.py","line":79,"fingerprint":"python.lang.best-practice.unspecified-open-encoding:skills/skill_classification.py:79"},{"rule_id":"opengrep/python.lang.maintainability.return-not-in-function","severity":"medium","message":"`return` only makes sense inside a function","path":"story/story_utils.py","line":258,"fingerprint":"python.lang.maintainability.return-not-in-function:story/story_utils.py:258"},{"rule_id":"opengrep/python.lang.maintainability.return-not-in-function","severity":"medium","message":"`return` only makes sense inside a function","path":"story/story_utils.py","line":259,"fingerprint":"python.lang.maintainability.return-not-in-function:story/story_utils.py:259"},{"rule_id":"opengrep/python.requests.best-practice.use-raise-for-status","severity":"medium","message":"There's an HTTP request made with requests, but the raise_for_status() utility method isn't used. This can result in request errors going unnoticed and your code behaving in unexpected ways, such as if your authorization API returns a 500 error while you're only checking for a 401.","path":"update.py","line":8,"fingerprint":"python.requests.best-practice.use-raise-for-status:update.py:8"},{"rule_id":"opengrep/python.requests.best-practice.use-timeout","severity":"medium","message":"Detected a 'requests' call without a timeout set. By default, 'requests' calls wait until the connection is closed. This means a 'requests' call without a timeout will hang the program if a response is never received. Consider setting a timeout for all 'requests'.","path":"update.py","line":8,"fingerprint":"python.requests.best-practice.use-timeout:update.py:8"},{"rule_id":"opengrep/python.lang.maintainability.return-not-in-function","severity":"medium","message":"`return` only makes sense inside a function","path":"utils.py","line":23,"fingerprint":"python.lang.maintainability.return-not-in-function:utils.py:23"},{"rule_id":"opengrep/python.lang.maintainability.return-not-in-function","severity":"medium","message":"`return` only makes sense inside a function","path":"utils.py","line":27,"fingerprint":"python.lang.maintainability.return-not-in-function:utils.py:27"},{"rule_id":"opengrep/python.lang.maintainability.return-not-in-function","severity":"medium","message":"`return` only makes sense inside a function","path":"utils.py","line":30,"fingerprint":"python.lang.maintainability.return-not-in-function:utils.py:30"},{"rule_id":"opengrep/python.lang.maintainability.code-after-unconditional-return","severity":"medium","message":"code after return statement will not be executed","path":"utils.py","line":30,"fingerprint":"python.lang.maintainability.code-after-unconditional-return:utils.py:30"},{"rule_id":"opengrep/python.lang.maintainability.return-not-in-function","severity":"medium","message":"`return` only makes sense inside a function","path":"utils.py","line":41,"fingerprint":"python.lang.maintainability.return-not-in-function:utils.py:41"},{"rule_id":"opengrep/python.lang.maintainability.code-after-unconditional-return","severity":"medium","message":"code after return statement will not be executed","path":"utils.py","line":41,"fingerprint":"python.lang.maintainability.code-after-unconditional-return:utils.py:41"},{"rule_id":"opengrep/python.lang.maintainability.return-not-in-function","severity":"medium","message":"`return` only makes sense inside a function","path":"utils.py","line":45,"fingerprint":"python.lang.maintainability.return-not-in-function:utils.py:45"},{"rule_id":"opengrep/python.lang.maintainability.code-after-unconditional-return","severity":"medium","message":"code after return statement will not be executed","path":"utils.py","line":45,"fingerprint":"python.lang.maintainability.code-after-unconditional-return:utils.py:45"},{"rule_id":"opengrep/python.lang.maintainability.return-not-in-function","severity":"medium","message":"`return` only makes sense inside a function","path":"utils.py","line":63,"fingerprint":"python.lang.maintainability.return-not-in-function:utils.py:63"},{"rule_id":"opengrep/python.lang.maintainability.code-after-unconditional-return","severity":"medium","message":"code after return statement will not be executed","path":"utils.py","line":63,"fingerprint":"python.lang.maintainability.code-after-unconditional-return:utils.py:63"}],"evidence":[],"data":{},"error":null},{"analyzer":"qual-testing","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:has_tests":0.0,"check:test_ratio":0.0,"check:ci_present":0.0,"check:ci_runs_tests":0.0,"check:ci_runs_lint":0.0,"check:tests_cochange":0.0,"test_lines":0.0,"source_lines":6048.0,"test_ratio":0.0,"ci_files":0.0,"cochange_share":0.0,"cochange_commits":116.0},"findings":[],"evidence":[],"data":{"test_commands":[],"lint_commands":[]},"error":null},{"analyzer":"qual-docs","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:readme":0.5,"check:license":1.0,"check:contributing":0.0,"check:changelog":0.0,"readme_lines":0.0},"findings":[],"evidence":[{"kind":"docs","description":"README.md","ref":"README.md","url":null,"weight":0.0},{"kind":"docs","description":"LICENSE","ref":"LICENSE","url":null,"weight":0.0}],"data":{},"error":null},{"analyzer":"qual-type-safety","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:strict_config":0.0,"check:low_escape_density":1.0,"escapes":2.0,"escapes_per_kloc":0.333},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"x-blame","pillar":"ai_provenance","status":"ok","tool_version":"git-blame","metrics":{"ai_lines":68.0,"other_lines":5980.0,"files_blamed":46.0,"blame_failures":0.0,"quality:ai_findings":0.0,"quality:ai_per_kloc":0.0,"quality:other_findings":39.0,"quality:other_per_kloc":6.522,"security:ai_findings":0.0,"security:ai_per_kloc":0.0,"security:other_findings":3.0,"security:other_per_kloc":0.502},"findings":[],"evidence":[],"data":{"sampled":false,"comparable":false},"error":null}],"flags":[]}