{"schema_version":"2","scorer_version":"0.1.0","scoring_version":"prov-5+qual-2+sec-2","generated_at":"2026-11-14T14:52:07.983105Z","repo":{"ref":{"host":"github.com","owner":"thade","name":"speakerctrl"},"default_branch":"main","clone_url":"https://github.com/thade/speakerctrl.git","html_url":"https://github.com/thade/speakerctrl","description":"speakerctrl`is the central control daemon for SpeakerOS.  It turns a Raspberry Pi into a single-purpose, appliance-style network speaker.","stars":0,"forks":0,"is_fork":false,"is_archived":false,"is_private":false,"size_kb":178,"primary_language":"Rust","license_spdx":"Apache-2.0","created_at":"2026-01-09T12:52:20Z","pushed_at":"2026-02-17T07:14:24Z","security_policy_url":null,"distribution":{"owner_created_at":"2008-02-28T09:39:13Z","owner_type":"User","release_assets":[]}},"commit_sha":"626df55784566ee47e49d4d9228a8582f0a14bc9","profile":{"lines_by_language":{"Rust":6802,"Shell":110},"files_by_category":{"source":17,"other":9,"docs":7,"config":5,"generated":1,"test":1},"source_lines":6853,"test_lines":59},"pillars":{"ai_provenance":{"score":0.0,"confidence":0.86,"coverage":1.0,"label":"explicit","breakdown":{"attributed_share":0.0002,"suspected_share":0.0,"estimated_share":0.0002,"ai_artifacts":1.0,"flagged_work_units":0.0,"flagged_releases":0.0,"style_index":1.897},"summary":"Explicit AI attribution on 0% of first-party code added; an estimated 0% including velocity signals."},"quality":{"score":73.1,"confidence":0.9,"coverage":1.0,"label":"adequate","breakdown":{"complexity":81.6,"duplication":69.1,"lint":99.1,"testing":56.3,"docs":65.0,"type_safety":null,"process":null},"summary":"Code quality is adequate: test-to-source ratio 0.01, CI runs tests; 7% of function code in complex or long functions; 6% duplicated lines. Weakest area: testing."},"security":{"score":76.5,"confidence":0.85,"coverage":1.0,"label":"adequate","breakdown":{"secrets":100.0,"sast":97.5,"dependencies":63.8,"ci_actions":77.1,"posture":0.0,"scorecard":null},"summary":"Security posture is adequate: 9 known vulnerabilities in 9 dependencies; 1 high-severity workflow issues. 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":12.0,"checked":12.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":65.0,"attributed_commits":6.0,"attributed_commit_share":0.09230769230769231,"effective_loc":8387.0,"attributed_loc":2.0,"attributed_loc_share":0.0002384642899725766,"tools_detected":1.0},"findings":[],"evidence":[{"kind":"attribution-summary","description":"Claude Code: 6 attributed commits, 2 lines added","ref":null,"url":null,"weight":1.0},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"626df55784566ee47e49d4d9228a8582f0a14bc9","url":"https://github.com/thade/speakerctrl/commit/626df55784566ee47e49d4d9228a8582f0a14bc9","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"7e8cc8b991ed2001abae09860929a33dc0465247","url":"https://github.com/thade/speakerctrl/commit/7e8cc8b991ed2001abae09860929a33dc0465247","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"d1e1c4faca5a7fb015ae7f080476e6146afaf544","url":"https://github.com/thade/speakerctrl/commit/d1e1c4faca5a7fb015ae7f080476e6146afaf544","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"27c0b5062f5de461e5742d8a64a2e57e822b1ca7","url":"https://github.com/thade/speakerctrl/commit/27c0b5062f5de461e5742d8a64a2e57e822b1ca7","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"a08d97929eb256b3c6569e3432ff17fd50aefe7a","url":"https://github.com/thade/speakerctrl/commit/a08d97929eb256b3c6569e3432ff17fd50aefe7a","weight":0.9},{"kind":"attributed-commit","description":"Claude Code: trailer 'Co-Authored-By: Claude'","ref":"f2a26d81cac5640649b2ea8d2458c6bb9c97e1e2","url":"https://github.com/thade/speakerctrl/commit/f2a26d81cac5640649b2ea8d2458c6bb9c97e1e2","weight":0.9}],"data":{"attributed_loc_by_commit":{"f2a26d81cac5640649b2ea8d2458c6bb9c97e1e2":0,"a08d97929eb256b3c6569e3432ff17fd50aefe7a":2,"27c0b5062f5de461e5742d8a64a2e57e822b1ca7":0,"d1e1c4faca5a7fb015ae7f080476e6146afaf544":0,"7e8cc8b991ed2001abae09860929a33dc0465247":0,"626df55784566ee47e49d4d9228a8582f0a14bc9":0},"tools":{"claude-code":{"name":"Claude Code","commits":6,"loc":2,"first_seen":1771306969,"last_seen":1771312461}},"monthly":{"2026-01":{"loc":8385,"attributed_loc":0},"2026-02":{"loc":2,"attributed_loc":2}}},"error":null},{"analyzer":"ai-artifacts","pillar":"ai_provenance","status":"ok","tool_version":"signatures-v1","metrics":{"artifacts":1.0,"workflow_agents":0.0,"tools_configured":1.0,"earliest_adoption":1767966585.0},"findings":[],"evidence":[{"kind":"ai-artifact","description":"AGENTS.md (generic-agent configuration)","ref":"AGENTS.md","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/AGENTS.md","weight":0.5}],"data":{"artifacts":[{"tool":"generic-agent","path":"AGENTS.md","added_at":1767966585}],"workflows":[],"tools":["generic-agent"]},"error":null},{"analyzer":"ai-velocity","pillar":"ai_provenance","status":"ok","tool_version":"prov-4","metrics":{"work_units":16.0,"flagged_units":0.0,"pre_ai_era_bursts":0.0,"pre_ai_era_measured_loc":0.0,"pre_ai_era_burst_loc":0.0,"measured_loc":8387.0,"flagged_loc":0.0,"flagged_loc_share":0.0,"max_loc_per_hour":707.2316904652234,"median_loc_per_hour":164.0,"pr_timed_units":0.0,"excluded_import_loc":0.0},"findings":[],"evidence":[],"data":{"flagged_loc_by_commit":{},"excluded_import_commits":[]},"error":null},{"analyzer":"ai-release-velocity","pillar":"ai_provenance","status":"ok","tool_version":"prov-4","metrics":{"releases":4.0,"flagged_releases":0.0,"max_loc_per_day":2512.3},"findings":[],"evidence":[],"data":{"releases":[{"from":"v0.1.1","to":"0.3.0","loc":2881,"days":3.57,"loc_per_day":806.0,"flagged":false},{"from":"0.3.0","to":"v0.3.0","loc":0,"days":0.04,"loc_per_day":0.0,"flagged":false},{"from":"v0.3.0","to":"v0.4.1","loc":537,"days":0.21,"loc_per_day":2512.3,"flagged":false},{"from":"v0.4.1","to":"v0.4.2","loc":0,"days":10.75,"loc_per_day":0.0,"flagged":false}]},"error":null},{"analyzer":"ai-stylometry","pillar":"ai_provenance","status":"ok","tool_version":null,"metrics":{"lines_scanned":6853.0,"index":1.897,"count:narrated_steps":1.0,"per_kloc:narrated_steps":0.146,"files:narrated_steps":1.0,"count:placeholder":6.0,"per_kloc:placeholder":0.876,"files:placeholder":2.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":[{"kind":"stylometry:narrated_steps","description":"step-by-step narration comment: // First, try to find a preferred output that's available","ref":"crates/speakerctrl-daemon/src/audio.rs:146","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/audio.rs#L146","weight":0.0},{"kind":"stylometry:placeholder","description":"placeholder or demo-only phrasing: // In a real implementation, we would:","ref":"crates/speakerctrl-daemon/src/network.rs:231","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/network.rs#L231","weight":0.0},{"kind":"stylometry:placeholder","description":"placeholder or demo-only phrasing: // In a real implementation, this would:","ref":"crates/speakerctrl-daemon/src/recovery.rs:106","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/recovery.rs#L106","weight":0.0},{"kind":"stylometry:placeholder","description":"placeholder or demo-only phrasing: // In a real scenario, we'd try to restart the service and check if it comes back up","ref":"crates/speakerctrl-daemon/src/recovery.rs:113","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/recovery.rs#L113","weight":0.0},{"kind":"stylometry:placeholder","description":"placeholder or demo-only phrasing: // In a real implementation, this would use systemd to restart the service","ref":"crates/speakerctrl-daemon/src/recovery.rs:121","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/recovery.rs#L121","weight":0.0},{"kind":"stylometry:placeholder","description":"placeholder or demo-only phrasing: // This is a placeholder implementation","ref":"crates/speakerctrl-daemon/src/recovery.rs:125","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/recovery.rs#L125","weight":0.0},{"kind":"stylometry:placeholder","description":"placeholder or demo-only phrasing: // In a real system, we would use systemd commands to restart the service","ref":"crates/speakerctrl-daemon/src/recovery.rs:126","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/recovery.rs#L126","weight":0.0}],"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":2.0,"findings_high":0.0,"findings_medium":0.0,"findings_low":2.0,"weighted_findings":0.5,"scanned_lines":6853.0,"parse_errors":0.0},"findings":[{"rule_id":"opengrep/rust.lang.security.temp-dir","severity":"low","message":"temp_dir should not be used for security operations. From the docs: 'The temporary directory may be shared among users, or between processes with different privileges; thus, the creation of any files or directories in the temporary directory must use a secure method to create a uniquely named file.  [confidence high]","path":"crates/speakerctrl-core/src/persist.rs","line":296,"fingerprint":"rust.lang.security.temp-dir:crates/speakerctrl-core/src/persist.rs:296"},{"rule_id":"opengrep/rust.lang.security.temp-dir","severity":"low","message":"temp_dir should not be used for security operations. From the docs: 'The temporary directory may be shared among users, or between processes with different privileges; thus, the creation of any files or directories in the temporary directory must use a secure method to create a uniquely named file.  [confidence high]","path":"crates/speakerctrl-daemon/src/network.rs","line":1441,"fingerprint":"rust.lang.security.temp-dir:crates/speakerctrl-daemon/src/network.rs:1441"}],"evidence":[],"data":{"rulesets":["rust","bash"]},"error":null},{"analyzer":"sec-deps","pillar":"security","status":"ok","tool_version":"osv-scanner version: 2.7.1","metrics":{"vulnerable_packages":9.0,"vulnerabilities":9.0,"vulns_critical":0.0,"vulns_high":0.0,"vulns_medium":1.0,"vulns_low":0.0,"vulns_unknown":8.0,"penalty":27.0},"findings":[{"rule_id":"osv/GHSA-434x-w66g-qw3r","severity":"medium","message":"bytes@1.11.0 (crates.io) is affected by RUSTSEC-2026-0007, GHSA-434x-w66g-qw3r","path":"Cargo.lock","line":null,"fingerprint":"bytes@1.11.0 (crates.io):GHSA-434x-w66g-qw3r"},{"rule_id":"osv/RUSTSEC-2026-0221","severity":"medium","message":"event-listener@5.4.1 (crates.io) is affected by RUSTSEC-2026-0221","path":"Cargo.lock","line":null,"fingerprint":"event-listener@5.4.1 (crates.io):RUSTSEC-2026-0221"},{"rule_id":"osv/RUSTSEC-2026-0441","severity":"medium","message":"pin-utils@0.1.0 (crates.io) is affected by RUSTSEC-2026-0441","path":"Cargo.lock","line":null,"fingerprint":"pin-utils@0.1.0 (crates.io):RUSTSEC-2026-0441"},{"rule_id":"osv/GHSA-cq8v-f236-94qc","severity":"medium","message":"rand@0.8.5 (crates.io) is affected by RUSTSEC-2026-0097, GHSA-cq8v-f236-94qc","path":"Cargo.lock","line":null,"fingerprint":"rand@0.8.5 (crates.io):GHSA-cq8v-f236-94qc"},{"rule_id":"osv/RUSTSEC-2026-0486","severity":"medium","message":"rustix@1.1.3 (crates.io) is affected by RUSTSEC-2026-0486","path":"Cargo.lock","line":null,"fingerprint":"rustix@1.1.3 (crates.io):RUSTSEC-2026-0486"},{"rule_id":"osv/RUSTSEC-2026-0386","severity":"medium","message":"tokio@1.49.0 (crates.io) is affected by RUSTSEC-2026-0386","path":"Cargo.lock","line":null,"fingerprint":"tokio@1.49.0 (crates.io):RUSTSEC-2026-0386"},{"rule_id":"osv/RUSTSEC-2026-0371","severity":"medium","message":"zbus_names@3.0.0 (crates.io) is affected by RUSTSEC-2026-0371","path":"Cargo.lock","line":null,"fingerprint":"zbus_names@3.0.0 (crates.io):RUSTSEC-2026-0371"},{"rule_id":"osv/RUSTSEC-2026-0370","severity":"medium","message":"zvariant@4.2.0 (crates.io) is affected by RUSTSEC-2026-0370","path":"Cargo.lock","line":null,"fingerprint":"zvariant@4.2.0 (crates.io):RUSTSEC-2026-0370"},{"rule_id":"osv/RUSTSEC-2026-0372","severity":"medium","message":"zvariant_derive@4.2.0 (crates.io) is affected by RUSTSEC-2026-0372","path":"Cargo.lock","line":null,"fingerprint":"zvariant_derive@4.2.0 (crates.io):RUSTSEC-2026-0372"}],"evidence":[],"data":{"ecosystems":["crates.io"]},"error":null},{"analyzer":"sec-actions","pillar":"security","status":"ok","tool_version":"zizmor 1.32.0","metrics":{"workflows":1.0,"findings":3.0,"findings_high":1.0,"findings_medium":2.0,"findings_low":0.0,"penalty":15.6},"findings":[{"rule_id":"zizmor/unpinned-uses","severity":"high","message":"unpinned action reference [confidence high]","path":".github/workflows/ci.yml","line":18,"fingerprint":"unpinned-uses:.github/workflows/ci.yml:18"},{"rule_id":"zizmor/artipacked","severity":"medium","message":"credential persistence through GitHub Actions artifacts [confidence low]","path":".github/workflows/ci.yml","line":18,"fingerprint":"artipacked:.github/workflows/ci.yml:18"},{"rule_id":"zizmor/excessive-permissions","severity":"medium","message":"overly broad permissions [confidence medium]","path":".github/workflows/ci.yml","line":13,"fingerprint":"excessive-permissions:.github/workflows/ci.yml:13"}],"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":0.0,"signed_commit_share":0.0308,"unpinned_manifests":2.0},"findings":[],"evidence":[{"kind":"posture","description":"crates/speakerctrl-core/Cargo.toml has no lockfile alongside it (unpinned dependencies)","ref":"crates/speakerctrl-core/Cargo.toml","url":null,"weight":0.3},{"kind":"posture","description":"crates/speakerctrl-daemon/Cargo.toml has no lockfile alongside it (unpinned dependencies)","ref":"crates/speakerctrl-daemon/Cargo.toml","url":null,"weight":0.3}],"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":368.0,"function_nloc":4757.0,"mean_ccn":2.75,"p90_ccn":6.0,"complex_functions":2.0,"long_functions":2.0,"many_param_functions":0.0,"risky_nloc_share":0.0679},"findings":[],"evidence":[{"kind":"complex-function","description":"run_monitor in crates/speakerctrl-daemon/src/bluetooth_monitor.rs: complexity 50, 172 lines","ref":"crates/speakerctrl-daemon/src/bluetooth_monitor.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/bluetooth_monitor.rs#L33","weight":0.8333333333333334},{"kind":"complex-function","description":"main in crates/speakerctrl-daemon/src/main.rs: complexity 27, 151 lines","ref":"crates/speakerctrl-daemon/src/main.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/main.rs#L128","weight":0.45}],"data":{},"error":null},{"analyzer":"qual-duplication","pillar":"quality","status":"ok","tool_version":"repotrust-dup-w6","metrics":{"compared_lines":4794.0,"duplicated_lines":295.0,"duplicated_share":0.0615,"files":17.0},"findings":[],"evidence":[{"kind":"duplicate-code","description":"6+ duplicated lines: crates/speakerctrl-core/src/persist.rs:286 and crates/speakerctrl-daemon/src/network.rs:1423","ref":"crates/speakerctrl-core/src/persist.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-core/src/persist.rs#L286","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: crates/speakerctrl-daemon/src/audio.rs:383 and crates/speakerctrl-daemon/src/pipewire_monitor.rs:151","ref":"crates/speakerctrl-daemon/src/audio.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/audio.rs#L383","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: crates/speakerctrl-daemon/src/audio.rs:469 and crates/speakerctrl-daemon/src/audio.rs:495","ref":"crates/speakerctrl-daemon/src/audio.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/audio.rs#L469","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: crates/speakerctrl-daemon/src/bluetooth.rs:131 and crates/speakerctrl-daemon/src/bluetooth.rs:143","ref":"crates/speakerctrl-daemon/src/bluetooth.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/bluetooth.rs#L131","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: crates/speakerctrl-daemon/src/bluetooth_monitor.rs:155 and crates/speakerctrl-daemon/src/bluetooth_monitor.rs:216","ref":"crates/speakerctrl-daemon/src/bluetooth_monitor.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/bluetooth_monitor.rs#L155","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: crates/speakerctrl-daemon/src/main.rs:647 and crates/speakerctrl-daemon/src/main.rs:663","ref":"crates/speakerctrl-daemon/src/main.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/main.rs#L647","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: crates/speakerctrl-daemon/src/network.rs:185 and crates/speakerctrl-daemon/src/network.rs:949","ref":"crates/speakerctrl-daemon/src/network.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/network.rs#L185","weight":0.3},{"kind":"duplicate-code","description":"6+ duplicated lines: crates/speakerctrl-daemon/src/web.rs:444 and crates/speakerctrl-daemon/src/web.rs:464","ref":"crates/speakerctrl-daemon/src/web.rs","url":"https://github.com/thade/speakerctrl/blob/626df55784566ee47e49d4d9228a8582f0a14bc9/crates/speakerctrl-daemon/src/web.rs#L444","weight":0.3}],"data":{},"error":null},{"analyzer":"qual-lint","pillar":"quality","status":"ok","tool_version":"opengrep 1.33.1; rules f1d2b562b414","metrics":{"findings":1.0,"weighted_findings":0.25,"scanned_lines":6853.0,"category:correctness":1.0},"findings":[{"rule_id":"opengrep/bash.lang.correctness.unquoted-variable-expansion-in-command","severity":"low","message":"Variable expansions must be double-quoted so as to prevent being split into multiple pieces according to whitespace or whichever separator is specified by the IFS variable. If you really wish to split the variable's contents, you may use a variable that starts with an underscore e.g. $_X instead of ","path":"build_package.sh","line":51,"fingerprint":"bash.lang.correctness.unquoted-variable-expansion-in-command:build_package.sh:51"}],"evidence":[],"data":{},"error":null},{"analyzer":"qual-testing","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:has_tests":1.0,"check:test_ratio":0.0172,"check:ci_present":1.0,"check:ci_runs_tests":1.0,"check:ci_runs_lint":0.0,"check:tests_cochange":0.0889,"test_lines":59.0,"source_lines":6853.0,"test_ratio":0.0086,"ci_files":1.0,"cochange_share":0.0222,"cochange_commits":45.0},"findings":[],"evidence":[{"kind":"ci","description":"CI config: .github/workflows/ci.yml","ref":".github/workflows/ci.yml","url":null,"weight":0.0},{"kind":"ci","description":"CI runs tests (go test, cargo test)","ref":null,"url":null,"weight":0.0}],"data":{"test_commands":["go test","cargo test"],"lint_commands":[]},"error":null},{"analyzer":"qual-docs","pillar":"quality","status":"ok","tool_version":null,"metrics":{"check:readme":1.0,"check:license":1.0,"check:contributing":0.0,"check:changelog":0.0,"readme_lines":95.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":"skipped","tool_version":null,"metrics":{},"findings":[],"evidence":[],"data":{},"error":null},{"analyzer":"x-blame","pillar":"ai_provenance","status":"ok","tool_version":"git-blame","metrics":{"ai_lines":2.0,"other_lines":6851.0,"files_blamed":17.0,"blame_failures":0.0,"quality:ai_findings":0.0,"quality:ai_per_kloc":0.0,"quality:other_findings":1.0,"quality:other_per_kloc":0.146,"security:ai_findings":0.0,"security:ai_per_kloc":0.0,"security:other_findings":2.0,"security:other_per_kloc":0.292},"findings":[],"evidence":[],"data":{"sampled":false,"comparable":false},"error":null}],"flags":[]}