公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-24 07:55 UTC

GeiserX / whisper-subs

Jellyfin plugin for local AI-powered subtitle generation using Whisper - all processing stays on your server

C# · HTMLGPL-3.0★ 81 星标⑂ 6 复刻始于 2025年12月在 GitHub 上查看 ↗

GeiserX/whisper-subs 的健康指数为 100 分中的 63 分,处于「中等」区间。 其得分最高的类别是Vitality(83/100),最低的是Community & Adoption(43/100)。 最近一次更新在 3 天前。 近期的大部分工作由 1 位贡献者完成。

63
总分 / 100
中等

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。

63
优秀85-100堪称典范;基本满足所有检验标准
良好70-84健康;仅有轻微不足
中等50-69可接受,但存在明显不足;建议进行审查
存在风险30-49存在重大薄弱环节;采用时应保持审慎
危急1-29问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。

所有权

Sergio Fernández个人账户
113 关注者186 个公开仓库始于 2014年10月

该仓库由个人账户拥有。相较于组织支持的项目,单一所有者项目的延续性风险更高。

按类别列示的指标

活力

项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?

83良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 3 天前
13.8/36提交节奏 — 52 周中有 20 周有提交
18/18提交量 — 最近一年 249 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 23 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year249
human_commit_share0.95
days_since_last_push3
active_weeks_last_year20

发布纪律

90优秀
评分方式
27/27有发布版本 — 已发布 91 个发布版本
36/36发布时效 — 最近一次发布版本于 10 天前
27/27发布节奏 — 约每 1.2 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — Project has not signed or included provenance with any releases.
所用输入
releases_count91
latest_release_tagv4.3.1.0
releases_from_tags
days_since_latest_release10
mean_days_between_releases1.2

社区与采用

项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?

43存在风险 · 占总体的 18%

流行度与采用

37存在风险
评分方式
30.9/60星标 — 81 个星标
5.8/25复刻 — 6 个复刻
0/15关注者 — 1 位关注者
所用输入
forks6
stars81
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

50中等
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(GPL-3.0)
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template

可持续性与治理

项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?

50中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0.4/22.5提交分布 — 头号贡献者编写了 98% 的提交
4.1/13.5贡献者广度 — 3 位贡献者
0/10OpenSSF Scorecard:Contributors — project has 0 contributing companies or organizations -- score normalized to 0
所用输入
bus_factor1
contributors_sampled3
top_contributor_share0.983
评分方式
44/46.8议题解决 — 94% 的议题已关闭
37.9/38.3PR 接受 — 已裁定的 PR 中 102/103 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/18 approved changesets -- score normalized to 0
所用输入
merged_prs102
open_issues2
closed_issues32
issue_closed_ratio0.941
closed_unmerged_prs1
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
14.8/25所有者影响力 — GeiserX 有 113 位关注者
25/25既往记录 — 186 个公开仓库,账户约 11 年
所用输入
followers113
owner_typeUser
is_verified
owner_loginGeiserX
public_repos186
account_age_days4,302
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。

工程质量

基础的工程与文档实践是否到位?

75良好 · 占总体的 20%

工程实践

68中等
评分方式
24/24CI 工作流 — 4 个工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
0/6.4.editorconfig
20/20OpenSSF Scorecard:CI-Tests — 19 out of 19 merged PRs checked by a CI test -- score normalized to 10
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config

文档

85优秀
评分方式
30/30README
25/25文档目录
0/15文档 / 主页站点
10/10仓库描述
10/10主题标签 — 20 个主题标签
10/10Wiki
所用输入
topicsaccessibility, ai, automation, csharp, dotnet, hacktoberfest, homelab, jellyfin, jellyfin-plugin, media-management, media-server, open-source, parakeet, self-hosted, speech-to-text, stt, subtitles, transcription, whisper, whisper-cpp
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?

62中等 · 占总体的 16%

安全态势

52中等
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 19 out of 19 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/18 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 23 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
2/5Security-Policy — security policy file detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated18
scorecard_versionv5.5.0
checks_inconclusive0
scorecard_aggregate5.2
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
0/25间接依赖不含已知公告 — 在此范围内,传递依赖集合无法与开发和测试依赖区分
0/40没有长期未处理的公告 — 没有公告带有发布日期
所用输入
sourceosv
advisories0
affected_packages0
assessed_packages3
unassessed_packages5
affected_by_severitynone
direct_affected_packages0
已排除计分(无数据或不适用):间接依赖不含已知公告, 没有长期未处理的公告。 其余权重已重新归一化。 已将 3 个已解析依赖与 OSV 比对。 有 5 项无法评估——没有已解析的版本、生态系统不受支持,或超出所报告的软件包清单。 该仓库未发布任何索引可解析的软件包,因此改为评估仓库依赖图。该图将开发与测试版本固定同交付的依赖混在一起,因此仅对声明的运行时依赖计分;传递性发现仅作为背景信息列出,不计入评分。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。

78良好 · 占总体的 0%
评分方式
45/45代理指令 — CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 95 次人类提交中有 93 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.979
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes41,683
评分方式
12.6/18一条命令的引导启动 — WhisperSubs.Tests/WhisperSubs.Tests.csproj, WhisperSubs.csproj(工具链约定,无任务运行器)
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — C#(静态类型)
10/10可复现环境 — Dockerfile
0/10已体现的代理实践 — 最近 100 次提交中没有代理编写的提交
8/8自动化维护 — 最近 100 次提交中有 5 次为自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
所用输入
has_nix
has_tests
lockfiles
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0
toolchain_manifestsWhisperSubs.Tests/WhisperSubs.Tests.csproj, WhisperSubs.csproj
dependency_bot_commit_share0.05
评分方式
45/45可类型检查的代码 — C#(静态类型)
54.5/55可控的文件大小 — 采样的 107 个源文件中有 1 个超过 60KB
所用输入
primary_languageC#
largest_source_bytes105,363
source_files_sampled107
oversized_source_files1

关键数据

81GitHub 星标
3贡献者
249最近 12 个月提交数
3距最近推送天数
91发布版本数
1巴士系数(bus factor)
2开放议题
NuGet软件包生态系统数

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • Could not fetch nuget package 'WhisperSubs' from its registry

更多细节

Star 与 Fork 历史 0 ★ / 6 ⇿
0Star
6Fork
43发布

每颗 star 和每个 fork 的添加时间,来自 GitHub 并按天汇总。累计增长位于其构成来源——每日新增——的正上方,二者可相互对照:稳定的自然增长与短暂的突增形态截然不同。当这一差别可被衡量时,它会作为增长真实性予以报告。

123456612026-042026-062026-07
主版本 0次版本 0修订 0
OpenSSF Scorecard 5.2 / 10
5.2综合

来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。Scorecard v5.5.0 · 2026-07-24 07:55 UTC

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests19 out of 19 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/18 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 23 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
4Security-Policysecurity policy file detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
直接依赖 8
注册表软件包版本约束清单文件
NuGetMicrosoft.NET.Test.Sdk17.*WhisperSubs.Tests/WhisperSubs.Tests.csproj
NuGetxunit2.*WhisperSubs.Tests/WhisperSubs.Tests.csproj
NuGetxunit.runner.visualstudio2.*WhisperSubs.Tests/WhisperSubs.Tests.csproj
NuGetMoq4.*WhisperSubs.Tests/WhisperSubs.Tests.csproj
NuGetcoverlet.collector6.*WhisperSubs.Tests/WhisperSubs.Tests.csproj
NuGetJellyfin.Model10.11.0WhisperSubs.csproj
NuGetJellyfin.Controller10.11.0WhisperSubs.csproj
NuGetMicrosoft.Extensions.Http9.0.18WhisperSubs.csproj
全部依赖 8

来自 GitHub 依赖图的完整解析依赖集合:8 个直接依赖与 0 个间接(传递)软件包。仓库提交锁文件时,传递闭包才是完整的。

注册表软件包版本关系
NuGetcoverlet.collector直接
NuGetJellyfin.Controller10.11.0直接
NuGetJellyfin.Model10.11.0直接
NuGetMicrosoft.Extensions.Http9.0.18直接
NuGetMicrosoft.NET.Test.Sdk直接
NuGetMoq直接
NuGetxunit直接
NuGetxunit.runner.visualstudio直接
依赖安全公告 0

该仓库未发布可被索引解析的包,因此评估的是其自身的依赖图——共 3 个包,其中也包含从不交付的开发与测试版本固定:0 个存在已知公告,0 个为直接依赖。 有 5 个无法评估——没有已解析的版本、生态系统不受支持,或不在所列包清单之内。

没有已知公告影响已评估的依赖。

公告表示依赖图中记录的版本落入某条公告的受影响范围。可达性未经分析,且依赖图包含开发与测试的版本固定——某项发现可能只涉及工具链而非交付的软件。

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "accessibility",
        "ai",
        "automation",
        "csharp",
        "dotnet",
        "hacktoberfest",
        "homelab",
        "jellyfin",
        "jellyfin-plugin",
        "media-management",
        "media-server",
        "open-source",
        "parakeet",
        "self-hosted",
        "speech-to-text",
        "stt",
        "subtitles",
        "transcription",
        "whisper",
        "whisper-cpp"
      ],
      "is_fork": false,
      "size_kb": 1228,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "C#": 943627,
        "HTML": 166918,
        "Shell": 3743,
        "Python": 38452,
        "Dockerfile": 7271,
        "JavaScript": 14959
      },
      "pushed_at": "2026-07-20T23:25:42Z",
      "created_at": "2025-12-05T21:24:26Z",
      "owner_type": "User",
      "updated_at": "2026-07-23T21:00:26Z",
      "description": "Jellyfin plugin for local AI-powered subtitle generation using Whisper - all processing stays on your server",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "GPL-3.0",
      "default_branch": "main",
      "license_spdx_raw": "GPL-3.0",
      "primary_language": "C#",
      "significant_languages": [
        "C#",
        "HTML"
      ]
    },
    "owner": {
      "blog": "https://geiser.cloud",
      "name": "Sergio Fernández",
      "type": "User",
      "login": "GeiserX",
      "company": null,
      "location": "Murcia, Spain",
      "followers": 113,
      "avatar_url": "https://avatars.githubusercontent.com/u/9169332?v=4",
      "created_at": "2014-10-12T21:57:52Z",
      "is_verified": null,
      "public_repos": 186,
      "account_age_days": 4302
    },
    "license": {
      "state": "standard",
      "spdx_id": "GPL-3.0",
      "raw_spdx": "GPL-3.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v4.3.1.0",
          "kind": "other",
          "published_at": "2026-07-13T21:26:45Z"
        },
        {
          "tag": "v4.3.0.0",
          "kind": "other",
          "published_at": "2026-07-12T20:44:05Z"
        },
        {
          "tag": "v4.2.0.0",
          "kind": "other",
          "published_at": "2026-07-10T00:16:49Z"
        },
        {
          "tag": "v4.1.1.0",
          "kind": "other",
          "published_at": "2026-07-07T00:17:01Z"
        },
        {
          "tag": "v4.1.0.0",
          "kind": "other",
          "published_at": "2026-07-06T22:36:30Z"
        },
        {
          "tag": "v4.0.0.0",
          "kind": "other",
          "published_at": "2026-07-06T17:26:38Z"
        },
        {
          "tag": "v3.29.0.0",
          "kind": "other",
          "published_at": "2026-07-06T12:09:11Z"
        },
        {
          "tag": "v3.28.0.0",
          "kind": "other",
          "published_at": "2026-07-05T16:53:42Z"
        },
        {
          "tag": "v3.27.0.0",
          "kind": "other",
          "published_at": "2026-07-05T13:32:38Z"
        },
        {
          "tag": "v3.26.0.1",
          "kind": "other",
          "published_at": "2026-07-02T16:50:37Z"
        },
        {
          "tag": "v3.26.0.0",
          "kind": "other",
          "published_at": "2026-07-02T15:45:48Z"
        },
        {
          "tag": "v3.25.0.0",
          "kind": "other",
          "published_at": "2026-07-01T14:01:06Z"
        },
        {
          "tag": "v3.24.0.0",
          "kind": "other",
          "published_at": "2026-06-29T09:59:45Z"
        },
        {
          "tag": "v3.23.0.0",
          "kind": "other",
          "published_at": "2026-06-28T13:03:03Z"
        },
        {
          "tag": "v3.22.1.0",
          "kind": "other",
          "published_at": "2026-06-27T23:45:07Z"
        },
        {
          "tag": "v3.22.0.0",
          "kind": "other",
          "published_at": "2026-06-26T17:57:25Z"
        },
        {
          "tag": "v3.21.3.0",
          "kind": "other",
          "published_at": "2026-06-26T15:59:43Z"
        },
        {
          "tag": "v3.21.2.0",
          "kind": "other",
          "published_at": "2026-06-26T10:37:09Z"
        },
        {
          "tag": "v3.21.1.0",
          "kind": "other",
          "published_at": "2026-06-25T20:50:33Z"
        },
        {
          "tag": "v3.21.0.0",
          "kind": "other",
          "published_at": "2026-06-25T15:25:47Z"
        },
        {
          "tag": "v3.20.0.0",
          "kind": "other",
          "published_at": "2026-06-18T19:31:40Z"
        },
        {
          "tag": "v3.19.1.0",
          "kind": "other",
          "published_at": "2026-06-18T13:52:23Z"
        },
        {
          "tag": "v3.19.0.0",
          "kind": "other",
          "published_at": "2026-06-16T18:14:29Z"
        },
        {
          "tag": "v3.18.8.0",
          "kind": "other",
          "published_at": "2026-06-16T14:16:47Z"
        },
        {
          "tag": "v3.18.7.0",
          "kind": "other",
          "published_at": "2026-06-14T23:07:27Z"
        },
        {
          "tag": "v3.18.6.0",
          "kind": "other",
          "published_at": "2026-06-13T20:37:17Z"
        },
        {
          "tag": "v3.18.5.0",
          "kind": "other",
          "published_at": "2026-06-07T13:48:48Z"
        },
        {
          "tag": "v3.18.4.0",
          "kind": "other",
          "published_at": "2026-06-06T22:58:14Z"
        },
        {
          "tag": "v3.18.3.0",
          "kind": "other",
          "published_at": "2026-06-06T22:43:26Z"
        },
        {
          "tag": "v3.18.2.0",
          "kind": "other",
          "published_at": "2026-06-06T17:31:36Z"
        },
        {
          "tag": "v3.18.1.0",
          "kind": "other",
          "published_at": "2026-05-25T18:24:49Z"
        },
        {
          "tag": "v3.18.0.0",
          "kind": "other",
          "published_at": "2026-05-19T09:33:59Z"
        },
        {
          "tag": "v3.17.1.0",
          "kind": "other",
          "published_at": "2026-05-15T19:15:08Z"
        },
        {
          "tag": "v3.17.0.0",
          "kind": "other",
          "published_at": "2026-05-12T09:15:19Z"
        },
        {
          "tag": "v3.16.0.0",
          "kind": "other",
          "published_at": "2026-05-11T10:49:18Z"
        },
        {
          "tag": "v3.15.0.0",
          "kind": "other",
          "published_at": "2026-05-11T09:36:39Z"
        },
        {
          "tag": "v3.14.2.0",
          "kind": "other",
          "published_at": "2026-05-07T22:59:39Z"
        },
        {
          "tag": "v3.14.1.0",
          "kind": "other",
          "published_at": "2026-05-07T21:48:47Z"
        },
        {
          "tag": "v3.14.0.0",
          "kind": "other",
          "published_at": "2026-05-05T10:59:01Z"
        },
        {
          "tag": "v3.13.2.0",
          "kind": "other",
          "published_at": "2026-05-04T23:15:18Z"
        },
        {
          "tag": "v3.13.1.0",
          "kind": "other",
          "published_at": "2026-05-04T23:10:15Z"
        },
        {
          "tag": "v3.13.0.0",
          "kind": "other",
          "published_at": "2026-05-04T17:48:45Z"
        },
        {
          "tag": "v3.12.2.0",
          "kind": "other",
          "published_at": "2026-04-29T19:29:43Z"
        },
        {
          "tag": "v3.12.1.0",
          "kind": "other",
          "published_at": "2026-04-28T23:39:25Z"
        },
        {
          "tag": "v3.12.0.0",
          "kind": "other",
          "published_at": "2026-04-28T09:43:25Z"
        },
        {
          "tag": "v3.11.3.0",
          "kind": "other",
          "published_at": "2026-04-23T08:45:37Z"
        },
        {
          "tag": "v3.11.2.0",
          "kind": "other",
          "published_at": "2026-04-18T11:55:38Z"
        },
        {
          "tag": "v3.11.1.0",
          "kind": "other",
          "published_at": "2026-04-17T22:55:53Z"
        },
        {
          "tag": "v3.11.0.0",
          "kind": "other",
          "published_at": "2026-04-16T11:52:32Z"
        },
        {
          "tag": "v3.10.0.0",
          "kind": "other",
          "published_at": "2026-04-16T08:43:14Z"
        },
        {
          "tag": "v3.9.1.0",
          "kind": "other",
          "published_at": "2026-04-15T11:51:43Z"
        },
        {
          "tag": "v3.9.0.0",
          "kind": "other",
          "published_at": "2026-04-15T10:52:14Z"
        },
        {
          "tag": "v3.8.5.0",
          "kind": "other",
          "published_at": "2026-04-15T09:45:40Z"
        },
        {
          "tag": "v3.8.4.0",
          "kind": "other",
          "published_at": "2026-04-14T23:19:28Z"
        },
        {
          "tag": "v3.8.3.0",
          "kind": "other",
          "published_at": "2026-04-14T23:15:00Z"
        },
        {
          "tag": "v3.8.2.0",
          "kind": "other",
          "published_at": "2026-04-14T23:11:55Z"
        },
        {
          "tag": "v3.8.1.0",
          "kind": "other",
          "published_at": "2026-04-14T23:07:09Z"
        },
        {
          "tag": "v3.8.0.0",
          "kind": "other",
          "published_at": "2026-04-14T23:01:43Z"
        },
        {
          "tag": "v3.7.1.0",
          "kind": "other",
          "published_at": "2026-04-13T15:50:13Z"
        },
        {
          "tag": "v3.7.0.0",
          "kind": "other",
          "published_at": "2026-04-13T08:56:49Z"
        },
        {
          "tag": "v3.6.0.0",
          "kind": "other",
          "published_at": "2026-04-13T08:13:50Z"
        },
        {
          "tag": "v3.5.0.0",
          "kind": "other",
          "published_at": "2026-04-11T21:32:24Z"
        },
        {
          "tag": "v3.4.0.0",
          "kind": "other",
          "published_at": "2026-04-11T19:26:48Z"
        },
        {
          "tag": "v3.3.0.0",
          "kind": "other",
          "published_at": "2026-04-11T18:16:40Z"
        },
        {
          "tag": "v3.2.0.0",
          "kind": "other",
          "published_at": "2026-04-10T22:38:50Z"
        },
        {
          "tag": "v3.1.5.0",
          "kind": "other",
          "published_at": "2026-04-08T08:42:09Z"
        },
        {
          "tag": "v3.1.4.0",
          "kind": "other",
          "published_at": "2026-04-06T23:02:46Z"
        },
        {
          "tag": "v3.1.3.0",
          "kind": "other",
          "published_at": "2026-04-06T22:57:15Z"
        },
        {
          "tag": "v3.1.2.0",
          "kind": "other",
          "published_at": "2026-04-06T22:48:05Z"
        },
        {
          "tag": "v3.1.1.0",
          "kind": "other",
          "published_at": "2026-04-06T18:24:54Z"
        },
        {
          "tag": "v3.1.1",
          "kind": "patch",
          "published_at": "2026-04-06T18:24:26Z"
        },
        {
          "tag": "v3.1.0.0",
          "kind": "other",
          "published_at": "2026-04-06T15:39:44Z"
        },
        {
          "tag": "v3.0.0.0",
          "kind": "other",
          "published_at": "2026-04-06T15:08:41Z"
        },
        {
          "tag": "v2.5.0.0",
          "kind": "other",
          "published_at": "2026-04-03T08:44:17Z"
        },
        {
          "tag": "v2.4.0.0",
          "kind": "other",
          "published_at": "2026-03-25T19:42:27Z"
        },
        {
          "tag": "v2.3.0.0",
          "kind": "other",
          "published_at": "2026-03-25T09:39:15Z"
        },
        {
          "tag": "v2.2.0.0",
          "kind": "other",
          "published_at": "2026-03-25T09:22:13Z"
        },
        {
          "tag": "v2.1.0.0",
          "kind": "other",
          "published_at": "2026-03-24T21:15:25Z"
        },
        {
          "tag": "v2.0.0.0",
          "kind": "other",
          "published_at": "2026-03-24T15:30:59Z"
        },
        {
          "tag": "v1.0.4.2",
          "kind": "other",
          "published_at": "2025-12-09T21:29:34Z"
        },
        {
          "tag": "v1.0.4.1",
          "kind": "other",
          "published_at": "2025-12-09T19:45:09Z"
        },
        {
          "tag": "v1.0.4.0",
          "kind": "other",
          "published_at": "2025-12-09T19:40:16Z"
        },
        {
          "tag": "v1.0.3.5",
          "kind": "other",
          "published_at": "2025-12-09T19:32:48Z"
        },
        {
          "tag": "v1.0.3.4",
          "kind": "other",
          "published_at": "2025-12-09T19:31:51Z"
        },
        {
          "tag": "v1.0.3.3",
          "kind": "other",
          "published_at": "2025-12-09T19:21:33Z"
        },
        {
          "tag": "v1.0.3.2",
          "kind": "other",
          "published_at": "2025-12-09T19:16:35Z"
        },
        {
          "tag": "v1.0.3.1",
          "kind": "other",
          "published_at": "2025-12-09T19:10:25Z"
        },
        {
          "tag": "v1.0.3.0",
          "kind": "other",
          "published_at": "2025-12-09T18:58:16Z"
        },
        {
          "tag": "v1.0.2.0",
          "kind": "other",
          "published_at": "2025-12-07T18:10:14Z"
        },
        {
          "tag": "v1.0.1.0",
          "kind": "other",
          "published_at": "2025-12-05T22:15:03Z"
        },
        {
          "tag": "v1.0.0.0",
          "kind": "other",
          "published_at": "2025-12-05T21:32:34Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "129503878cd479d1068694641a2ec0eb20ac9781",
          "body": "Bumps Microsoft.Extensions.Http from 9.0.17 to 9.0.18\n\n---\nupdated-dependencies:\n- dependency-name: Microsoft.Extensions.Http\n  dependency-version: 9.0.18\n  dependency-type: direct:production\n  update-type: version-update:semver-patch\n  dependency-group: minor-and-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps: Bump the minor-and-patch group with 1 update (#137)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-20T23:25:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "db4a48b99546e5fc3ce0257b03a07e7eb96b04c6",
          "body": "…-endpoint concurrency + worker self-heal (#136)\n\n* fix(worker): serialise inference + self-heal a wedged whisper-server\n\nwhisper.cpp's whisper-server runs one inference at a time, so a request arriving mid-transcription\nsits in the OS accept queue behind it — invisible to the disconnect-watcher — a\n[…]\n the exact\ncompute_backend_timeout scaling the review corrected (long film not guillotined, still bounded)\nand the inflight semaphore's exactly-once/cancelled-client/over-release accounting. 10 tests.",
          "is_bot": false,
          "headline": "fix(v4.3.1): eliminate M4 worker stalls — lightweight detection + per…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-13T21:23:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6d7280f1fe02b403a3d2170d4a14f479a8fda16e",
          "body": null,
          "is_bot": false,
          "headline": "docs: worklog — configurable naming shipped + released 4.3.0.0 (#135)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-13T20:45:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8c13fb70b1d484c3ee288e144a567ef22a215576",
          "body": "…sperSubs) + release 4.3.0.0 (#134)\n\n* feat: configurable subtitle filename naming with brand label (default WhisperSubs)\n\nAdds SubtitleLabel + SubtitleFilenameTemplate config (default {name}.{lang}.{label}{.type}\n-> Episode.en.WhisperSubs.srt), so the Jellyfin picker reads 'WhisperSubs - English' i\n[…]\n Classify (legacy OR new), switched hasFullSrt and\nthe status full-bucket to Classify==Full, and delete a resumed legacy partial after the canonical\nwrite. +4 regression tests. 1059 tests, 0 warnings.",
          "is_bot": false,
          "headline": "feat: configurable subtitle filename naming (brand label, default Whi…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-12T20:39:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "60325c5276ef55ecdb837d2dd700fb3e111a6ae3",
          "body": "release: 4.2.0.0 — hot-add workers, multi-audio toggle, auto-retry, GenerateAll allow-list",
          "is_bot": false,
          "headline": "Merge pull request #133 from GeiserX/v4-dev",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-10T00:13:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "11b5cc62fd87203c33d4c577b063a2b307380bd0",
          "body": "… auto-retry, GenerateAll allow-list)",
          "is_bot": false,
          "headline": "release: bump plugin to 4.2.0.0 (hot-add workers, multi-audio toggle,…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-10T00:10:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "af857afbed4c9f3ec8a7aac300c1ac142f8822f6",
          "body": "… all beads resolved",
          "is_bot": false,
          "headline": "docs(loop): /sergio-loop complete — 9gq merged (#132), ezg won't-fix,…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T23:42:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6eb3b430411ab38c88f9413b87a24db9397f7f7c",
          "body": "…isper-subs-9gq) (#132)\n\n* feat: hot-add workers to the live pool without a restart (whisper-subs-9gq)\n\nA worker added to the config mid-backlog previously never joined the live pool:\nGetPool only rebuilds when the pool is idle (ActiveJobs == 0), so a just-added\nworker (e.g. a new Mac mini) was unus\n[…]\nt-shrink accounting.\n\nAdds 12 unit tests (WorkerPoolReconcileTests, WorkerSignatureTests): 985 green.\n\n* fix: harden 9gq — over-release tripwire, log added/removed workers, order-insensitive signature",
          "is_bot": false,
          "headline": "feat: hot-add workers to the live pool without a Jellyfin restart (wh…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T23:34:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7c85b17fce6672b624e6c493297daeb7104cfb01",
          "body": "…freeze; start 9gq",
          "is_bot": false,
          "headline": "docs(loop): czk+qv4 merged (#131); re-record meo resolution + schema-…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T22:14:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5d213328b50ac1c1c9ff375d63b7ecde2a02a161",
          "body": "…#131)\n\nwhisper-subs-czk: invert the GenerateAll / user-request guard from a\nreject-list to an allow-list. The old MediaItemResolver.IsWholeLibraryContainer\nonly blocked library roots (CollectionFolder / UserView / AggregateFolder), so a\nBoxSet collection, MusicArtist, or plain Folder slipped throug\n[…]\neintroduce\nthe reserve-leak the bead described.\n\nAdds MediaItemResolverTests covering the allowed leaves/containers and the\nrejected BoxSet / MusicArtist / Folder / CollectionFolder / AggregateFolder.",
          "is_bot": false,
          "headline": "fix: allow-list GenerateAll targets + document the de-dup invariant (…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T22:11:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c79881c2c6dd8654a7a82a154bcbf291a845fa64",
          "body": "…ct verifying ezg/qv4/czk + designing 9gq",
          "is_bot": false,
          "headline": "docs(loop): continue with other beads; M4 health reconfirmed; archite…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T21:10:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b3b10a15be66d91536b165bf29bd9a5fd92af784",
          "body": "…oop deactivated",
          "is_bot": false,
          "headline": "docs(loop): /sergio-loop complete — M4 worker + beads 1t0/v00 done; l…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T21:00:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "941a8f0cd26548a5739bbea117d9f2b2e332a6f8",
          "body": "…gq filed",
          "is_bot": false,
          "headline": "docs(loop): v00 PR #130; M4-restart deferred (active viewers); bead 9…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T20:58:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "62c1d31c28f1a7e3b0791ce1d31c12dafaff6c0e",
          "body": "…ription (whisper-subs-v00)",
          "is_bot": false,
          "headline": "feat: add AudioLanguageSelection toggle + document multi-audio transc…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T20:52:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "614f373c7117ef89faa39d7ac273902fc3e7707c",
          "body": null,
          "is_bot": false,
          "headline": "docs(loop): 1t0 merged (#129); v00 in progress",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T20:40:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1fd3da79ecbc71d67a9fc5ac1c699f66e9e3ce9d",
          "body": "…isper-subs-1t0) (#129)\n\n* feat: auto-retry killed/cancelled jobs + persist in-flight leases (whisper-subs-1t0)\n\nThe queue previously persisted only the pending lanes. An item that was DEQUEUED and running lived solely in the in-memory _inFlight set, so if its task was stopped, Jellyfin restarted, o\n[…]\nding unchanged), Pending-InFlight overlap collapse,\nskip of unparseable/missing items, tier-less normalisation, and ShouldRestore /\nRestoredRetryCount truth tables. Full suite 949 passing, 0 warnings.",
          "is_bot": false,
          "headline": "feat: auto-retry killed/cancelled jobs + persist in-flight leases (wh…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T20:38:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8c433877a44e01ab6917d7bbfdd0f788b075f878",
          "body": "… for idle",
          "is_bot": false,
          "headline": "docs(loop): v00 design recorded; 1t0 in flight; M4 activation waiting…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T19:45:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5b0fbf1437dd32380427bcd0f0e8b8a7e144e048",
          "body": "…-delete + M4 activation deferred",
          "is_bot": false,
          "headline": "docs(loop): Mac mini M4 Metal worker built+verified (46x faster); meo…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-09T19:41:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6de1b715121bbc3f94b3208a5b35fb6e74b74c7b",
          "body": "…accuracy) (#128)\n\n* fix: Workers/TestConnection distinguishes reachable-but-slow from unreachable (#126)\n\nA slow GPU worker (e.g. large-v3 on an Intel iGPU) can take longer than the probe's transcribe timeout to decode even the silent test clip, because whisper decodes silence as a worst-case full-\n[…]\nthe image at /opt/whisper-vad/ -- outside the /models bind-mount so a mounted cache can't shadow it -- with a build-time size guard. Bump worker VERSION 0.1.1 -> 0.1.2 (VAD-on is a change from 0.1.1).",
          "is_bot": false,
          "headline": "release: 4.1.1.0 (TestConnection fix) + worker image 0.1.2 (decoding …",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-07T00:13:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cccd5e63dc6b5332a55651708795f4970cf6aa66",
          "body": "* fix: v4.0.1 — post-release audit fixes + v4.0 docs + worker-image robustness (#122)\n\n* fix: dispatcher wedge-on-throw, atomic queue.json, SSRF hardening, single-server panel (v4.0.1)\n\nPost-release audit fixes:\n- CONC-H1: EnsureDispatching built the pool OUTSIDE the Task.Run try, so a throw from\n  \n[…]\nmage workflow's push-trigger tag now comes from worker/VERSION\ninstead of a hardcoded 0.1.0 default, so a main push can never re-push an\nexisting tag with different content. Dispatch input still wins.",
          "is_bot": false,
          "headline": "release: 4.1.0.0 — parallel automatic sweep + 4.0.1 hardening (#125)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T22:33:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "347765daf3a5e8fd392209c00ab6e2ca0e9ef8f9",
          "body": "…121)\n\nPublishes drumsergio/whisper-subs-worker on worker/ changes + via workflow_dispatch,\nso the v4.0 example worker can be deployed by pulling the image (never :latest).\nFree ubuntu-latest (public repo); push/dispatch only (no fork-PR secret exposure).",
          "is_bot": false,
          "headline": "ci: build + push the worker image to Docker Hub (worker-image.yml) (#…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T17:45:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "671d6a0b0d9ce9660312960c908bcab5f0d5cc7f",
          "body": "…#120)\n\nrelease: v4.0.0.0 — distributed / pooled multi-worker transcription",
          "is_bot": false,
          "headline": "release: v4.0.0.0 — distributed / pooled multi-worker transcription (…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T17:23:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9ac4f35135c402217ae5d480125c0755b8ad7b33",
          "body": "…ker transcription)",
          "is_bot": false,
          "headline": "chore(release): bump version to 4.0.0.0 (distributed/pooled multi-wor…",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T17:13:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ddfb0daea198696361a2b840109641f4139fc1f",
          "body": "…ty (v4.0 PR-5) (#119)\n\nWorker-pool config section + queue inbound/outbound + per-worker 'what's running where' panels + Test-connection. Backend unit-tested; simple-by-default.",
          "is_bot": false,
          "headline": "feat(ui+api): worker-pool config UI + queue inbound/outbound visibili…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T17:12:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aa51027fe43412dd54dbe3b54836e9698d914962",
          "body": "….0 PR-4) (#118)\n\nExample whisper.cpp+Vulkan worker image behind a stdlib OpenAI-compatible adapter, security-reviewed + hardened. Additive worker/ files only.",
          "is_bot": false,
          "headline": "feat(worker): whisper.cpp + Vulkan OpenAI-compatible worker image (v4…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T17:11:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cb004057351a56e8140afb5d2dd07d72ead6c9a7",
          "body": "…ionLock (v4.0 PR-3) (#117)\n\nReplace the single global TranscriptionLock(1,1) + single-worker drain with a shared WorkerPool gating concurrency at ΣMaxConcurrency and routing each job to the cheapest capable free worker. Default one local worker = one job at a time (byte-identical to the old lock); \n[…]\nabbit; fixed a double-dispatch race (dispatch-gate atomicity), a latent _isDraining wedge, a stuck task-running flag, /Queue processed-count parity, and AcquireAsync self-guard. 879 tests, 0 warnings.",
          "is_bot": false,
          "headline": "feat(workers): N-slot pool dispatcher replacing the global Transcript…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T15:05:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b15612c1552b86a3fe4dddab97766debd2ce4ee2",
          "body": "… 2/5)\n\nPure worker-selection model + config for the distributed pool, backend-agnostic and simple-by-default. WorkerScheduling (cost-weighted local-first routing), WhisperWorker config (empty by default), ITranscriptionWorker, and the backward-compat WorkerPlan — all pure logic 100% covered, no runtime change yet. Dispatcher wiring is PR-3.",
          "is_bot": false,
          "headline": "feat(workers): worker model + cost-weighted routing + config (v4.0 PR…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T12:22:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ee25673bc813c0fbf31fde92625b6f1b63f24511",
          "body": "whisper-subs is a PUBLIC repo, so GitHub-hosted runners are free + unlimited\n(matches the public-repo CI policy). Switches the 8 build-whisper matrix jobs\nfrom [self-hosted, Linux, X64] to ubuntu-latest, removing the dependency on the\nself-hosted fleet for releases. The workflow already installs all build deps\n(cmake, CUDA via Jimver, Vulkan SDK, aarch64 cross-toolchain) and cross-compiles\narm64 (no QEMU emulation), so it runs cleanly on a stock ubuntu-latest.",
          "is_bot": false,
          "headline": "ci: build releases on free GitHub-hosted runners, not self-hosted (#115)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T12:05:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6192cbe3e815457b0f46bba8cd99d93873707044",
          "body": null,
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'origin/main' into v4-dev",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T11:26:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5b058e06fd043844a3534fed95fc480520fa9cf3",
          "body": "… (v3.29.0.0)\n\nPure 3.x correctness fixes, valuable to all current users:\n- Per-call deadline (audio-length-derived, clamped) replaces the fixed 30-min HttpClient.Timeout that caused the 70-hour-stuck-task class; deadline surfaces as TimeoutException, caller-cancel propagates.\n- Forced-detection loo\n[…]\ng ~260MB x N in RAM.\nCodeRabbit reviewed the substance clean; two hardening fixes (deadline ceiling, multi-writer-safe temp) added from an adversarial review pass. 844 tests, pure policy 100% covered.",
          "is_bot": false,
          "headline": "fix: transcription resilience — bound calls, atomic writes, fail-fast…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T11:25:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0fba9f0884d43809ec7d6b67781cb91210ecf083",
          "body": null,
          "is_bot": false,
          "headline": "chore: let CodeRabbit review PRs into the v4-dev integration branch",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T10:31:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bf756426ff9107c402904c5ebb72cda9f818c5df",
          "body": null,
          "is_bot": false,
          "headline": "ci: run CI on the v4-dev integration branch (release stays main-only)",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-06T10:28:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c5cd3af97173636e984e342b1676508943850627",
          "body": "User-facing subtitle requests + a named-tier priority queue (Critical > High > Medium > Low > Background), tier assigned server-side by role. Opt-in and off by default (existing installs unchanged); when on, approval-required with per-user quota/caps/de-dup. Separate authenticated request controller keeps the admin controller's elevation. 835 tests, 100% patch coverage, 4-lens review + CodeRabbit addressed.\n\nCloses #112",
          "is_bot": false,
          "headline": "feat: subtitle request system with named-tier priority queue (#112)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-05T16:47:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f01793cffd190683d1d21bddcf6ec987c7793965",
          "body": "…110) (#111)\n\nThe scheduled task re-probed the filesystem for every candidate item on\nevery run (~5 directory scans across the media + metadata dirs per item), so\na large library spent tens of minutes each run just re-confirming subtitles\nthat already exist — a 13k-item library took ~40 minutes to r\n[…]\ning (blind to the plugin's own un-indexed .generated.srt\nsidecars — verified against Jellyfin 10.11 source) after a research panel;\nmirrors the change-token cache pattern used by intro-skipper/Bazarr.",
          "is_bot": false,
          "headline": "feat(scan): cache already-subtitled items so repeat runs skip fast (#…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-05T13:26:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3d080a149acac6d6ef66d5b13a85bca5d6160c81",
          "body": "The GitHub Pages deployment for 4cbb37d wedged in deployment_queued across\ntwo attempts (deploy-pages keys the Pages deployment by commit SHA, so\nretries of the same SHA inherit the wedged state), leaving the release\nassets published but the plugin manifest stuck at 3.25.0.0. No code\nchanges — a fresh version/SHA gets a fresh Pages deployment.",
          "is_bot": false,
          "headline": "chore(release): 3.26.0.1 — redeploy manifest",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-02T16:42:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "46ac827157ea23962e367c27915b83a7850b156d",
          "body": "GitHub Pages deployments for 4cbb37d wedged in deployment_queued across two\nattempts (deploy-pages derives the deployment id from the commit SHA, and the\ncanceled deployment blocks retries of the same SHA). A fresh commit gets a\nfresh deployment id. No code changes.",
          "is_bot": false,
          "headline": "chore: retrigger release deploy",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-07-02T16:34:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4cbb37d178f523a4366bbfb4c71f7e0634ceec2b",
          "body": "…) (#109)\n\n* feat(web): inject via File Transformation plugin when installed (#108)\n\nRegister a serve-time index.html transformation with IAmParadox27's File\nTransformation plugin whenever it is installed, so the in-page \"Generate\nSubtitles\" button works on read-only web roots (Docker) without any\np\n[…]\nbly — stop) from a FAILED scan (error while\nassemblies still load at startup — keep retrying), so a transient scan\nexception on the first attempt no longer disables the integration for the\nwhole boot.",
          "is_bot": false,
          "headline": "feat(web): inject via File Transformation plugin when installed (#108…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-02T15:38:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ff0b31484ffe6ff5c9d75cd74b60b1cc404bcae6",
          "body": "Bumps the github-actions group with 2 updates: [actions/cache](https://github.com/actions/cache) and [actions/checkout](https://github.com/actions/checkout).\n\n\nUpdates `actions/cache` from 5 to 6\n- [Release notes](https://github.com/actions/cache/releases)\n- [Changelog](https://github.com/actions/ca\n[…]\nsion-update:semver-major\n  dependency-group: github-actions\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "ci: bump the github-actions group with 2 updates (#107)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-01T23:59:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "28f46383831905c8698fd66bda7d79cc9f63e13f",
          "body": "…#105) (#106)\n\n* feat(vad): selectable Silero VAD model + tunable --vad-* parameters (#105)\n\nLet users choose the Silero VAD model and tune whisper-cli's native VAD\nparameters, addressing #105. Fully backward compatible: the default config\nproduces a byte-identical whisper-cli command and uses the s\n[…]\nd cap is meaningless — unlike\nthe other tuning fields where 0 is a valid setting. Addresses CodeRabbit\nreview on #106. Behavior unchanged (pinned by AppendVadTuning_MaxSpeechS_ExactlyZero_NotEmitted).",
          "is_bot": false,
          "headline": "feat(vad): selectable Silero VAD model + tunable --vad-* parameters (…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-07-01T13:51:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a271f3b479e12ca281358a8be0ac12131c67acac",
          "body": "…AD (#104)\n\nRefs #78. Adds AlignSubtitlesToSpeechWithVad (default off): the early-cue forward-snap (AlignSrtToSpeech) can now run alongside VAD, since native VAD improves transcription but doesn't always correct whisper's slightly-early cue starts. Default off → existing VAD installs unchanged (the gate ShouldAlignToSpeech(align, usesVad, alignWithVad) is algebraically identical when the opt-in is off). Config-page checkbox + README/CLAUDE.md docs + truth-table tests. v3.24.0.0, 632 tests pass.",
          "is_bot": false,
          "headline": "feat(timing): opt-in to run speech-alignment forward-snap on top of V…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-29T09:49:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9d981b85cea3a2b9f27c118eb84e688cd5c52d2f",
          "body": "…ave-with-media-off libraries (#103)\n\nCloses #101. Generated subtitles now save to the item's internal metadata path (item.GetInternalMetadataPath(), e.g. /config/metadata/library/aa/<guid>/) when the library's 'Save subtitles into media folders' is off or the media folder is read-only — mirroring h\n[…]\nata path, so already-generated items aren't reprocessed and status is correct. Writability probed only when save-with-media is on. Lyrics stay media-adjacent (out of scope). v3.23.0.0, 623 tests pass.",
          "is_bot": false,
          "headline": "feat(save): save subtitles to Jellyfin metadata path on read-only / s…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-28T12:56:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "05b74fbc730783ddd819a4d0cfd271960ddb6adc",
          "body": "…ble message (#102)\n\nFollow-up to #94 / v3.22.0.0. The injection-status panel's 'not writable' message now shows the concrete fix with the server's real index.html path — sudo chown root:jellyfin \"<path>\" && sudo chmod 664 \"<path>\" — scoped to install type (package vs Docker PUID/PGID / read-only mount). Pure DescribeInjection gains the path param; tests lock the quoted path, the 664 mode, the spaces-in-path case, and the fallback. v3.22.1.0 (patch). 610 tests pass.",
          "is_bot": false,
          "headline": "fix(integration): copy-paste chown/chmod remediation in the not-writa…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-27T23:39:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d2564868d340f49150ad0058a7a022192ab2745e",
          "body": "…utton (#100)\n\nDiagnosability for #94: the in-page \"Generate Subtitles\" button + menu come from whisperSubs.js injected into Jellyfin's index.html, which silently fails on read-only web roots / no restart / cached pages.\n\n- Config-page 'In-page button & menu' panel shows whether the script is inject\n[…]\nt.\n- whisperSubs.js logs load + admin status at console.log (was hidden console.debug).\n- Pure ComputeInjection/DescribeInjection helpers + ScriptInjectionTests; 608 tests pass.\n- v3.22.0.0 (feature).",
          "is_bot": false,
          "headline": "feat(integration): client-script injection status panel + Re-inject b…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-26T17:49:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7a309eb093dca88e0d86dcf34d0bf6239b3a5550",
          "body": "…p double-VAD (#99)\n\nForced-subtitle follow-ups to #95 (v3.21.3.0):\n- Translate foreign dialogue to English for English libraries (was transcribed in source language into the .eng track).\n- Skip whisper's second VAD pass on already-trimmed forced chunks (was emptying short chunks).\n- Log whisper-cli's normal stderr at Debug, not Warning.\nPure ShouldUseVad/LanguageIsEnglish helpers + ForcedTranslateTests; 595 tests pass.",
          "is_bot": false,
          "headline": "fix(forced): translate foreign dialogue to English, quiet stderr, ski…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-26T15:53:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1effc73745b4dac7cca94fdbc062cf9cec42bd96",
          "body": "…ixes the per-chunk timeout (#98)\n\nThird fix for #95 — the one that targets the actual current failure. Forced-mode per-chunk --detect-language loaded the full ~1 GB transcription model on the CPU under a 120s timeout, so on a no-AVX2 CPU every chunk timed out (TaskCanceledException) and the film ne\n[…]\nore the forced loop gives the background download a head start so the first run is fast too.\n\nMakes per-chunk detection finish in seconds on any hardware, no GPU needed. Release: v3.21.2.0. Fixes #95.",
          "is_bot": false,
          "headline": "fix: small dedicated model for forced-subtitle language detection — f…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-26T10:30:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ce35d6e8f7ed3e31c4e9f0192e594aef7adfcd2e",
          "body": "…t (#97)\n\nFollow-up to #96 / issue #95. Closes two residual gaps for AVX-but-not-AVX2 users:\n\n- Persist the validated binary variant (WhisperBinaryVariant) so the setup page re-offers the user's installed compatibility build instead of silently re-defaulting the dropdown to the GPU recommendation on\n[…]\nrrect Compatibility build no longer shows the misleading red 'will crash' warning (green only when the CPU lacks AVX2; amber 'use the standard variant' otherwise).\n\nRelease: v3.21.1.0. Relates to #95.",
          "is_bot": false,
          "headline": "fix: persist whisper binary variant + correct setup compatibility hin…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-25T20:44:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e00be421f27320f27162fef84a40a2a9dce5c70f",
          "body": "Closes #94, fixes #95.\n\n#94 — Visible \"Generate Subtitles\" button on movie/episode/season/series detail pages (alongside the existing context-menu item), enqueue-time de-duplication (no double-queue on double-clicks / overlapping seasons), and a library-root guard. Admin-only.\n\n#95 — Language detect\n[…]\nhose CPUs to the noavx variant), and the detection path surfaces the precise 'switch to the noavx variant' message on a SIGILL instead of a misleading 'could not detect language'.\n\nRelease: v3.21.0.0.",
          "is_bot": false,
          "headline": "feat: generate subtitles from the item page + AVX2 detection fix (#96)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-25T15:08:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7016ba8fca248981161edb2e13cddae3a90aa208",
          "body": "The whisper-cli build artifacts (incl. 727MB CUDA binaries) are transient\nhand-offs to the release job; the final binaries are published to the\nGitHub Release. They were retained 90 days by default, accumulating ~15GB\nof paid Actions storage. Cap retention at 1 day.\n\nCo-authored-by: GeiserX <drumsergio@gmail.com>",
          "is_bot": false,
          "headline": "ci: cap artifact retention at 1 day to stop storage billing (#92)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-23T10:51:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5a7e2eb7a82479065e90697ea9e5f8a50e3da885",
          "body": "Public repos get free, unlimited standard GitHub-hosted runners. Move\nself-hosted Linux CI jobs to ubuntu-latest: frees the home-lab servers,\nruns PR code in throwaway isolated VMs (removing the fork-PR attack\nsurface), and costs nothing on public repos. The previous self-hosted\nfork-guard is removed as it is no longer needed.\n\nCo-authored-by: GeiserX <drumsergio@gmail.com>",
          "is_bot": false,
          "headline": "ci: use GitHub-hosted ubuntu-latest runners (#93)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-23T10:40:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e312b77f1d12f6794325a3c69d5bcdfbb2edf378",
          "body": "Jobs triggered on pull_request that run on the self-hosted runner could\nexecute untrusted fork PR code on the runner host. Add an if: guard so\nthese jobs run only for same-repo events (push, schedule, workflow_dispatch,\nand PRs from branches in this repo), never for fork PRs. Runner stays\nself-hosted for trusted runs.\n\nCo-authored-by: GeiserX <drumsergio@gmail.com>",
          "is_bot": false,
          "headline": "security: block fork PRs from running on the self-hosted runner (#91)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-22T22:56:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3083a2faf9ab76ad7e6d0c0a9f78d698f794c4bd",
          "body": "…ng, dropdown descriptions (#89)\n\nFollow-up to #88. Adds a CanTranslate capability flag to the model catalog (false for the distilled turbo models, which can't translate; true for full models) and a pure ModelCatalog.IsTranslationCapable helper. SubtitleManager now logs a clear, non-blocking warning\n[…]\nrected the F16 speed/RAM claims. The config UI now shows the selected model's description under the download dropdown, and a catalog-load ordering race is fixed. New ModelCatalogTests; 554 tests pass.",
          "is_bot": false,
          "headline": "feat: translation-aware model catalog — CanTranslate guard, Q5 steeri…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-18T19:19:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e34ed17d3ab9013f2ba0304a17c82b9f98edfc4c",
          "body": "Adds full large-v3 (ggml-large-v3.bin, 3095 MB) and its q5_0 quant (ggml-large-v3-q5_0.bin, 1081 MB) to the model download catalog. These are the only translation-capable large models — large-v3-turbo was distilled without the translate task, so users translating foreign-language titles to English n\n[…]\nv3 (or medium), which the UI previously didn't offer. Both download from the same ggerganov/whisper.cpp HuggingFace repo; sizes verified against Content-Length. Thanks to @hrones for the contribution.",
          "is_bot": false,
          "headline": "feat: add full large-v3 models (F16 + Q5) to the download catalog (#88)",
          "author_name": "hrones",
          "author_login": "hrones",
          "committed_at": "2026-06-18T18:50:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2c4308f47f5b3c09c3ccdfca290fb934670bc477",
          "body": "… --print-progress wiring (#87)\n\nFollow-up to #86. Resets the per-file progress bar inside the single transcription choke point (TranscribeInternalAsync, before process.Start()) so the manual Generate queue and multi-pass items no longer show the previous run's stale 100% and run backwards. Anchors \n[…]\ntderr line can't be misread as progress. Extracts a pure, unit-tested BuildTranscribeArguments (byte-identical arg vector incl. --print-progress) so the flag can't be silently dropped. 538 tests pass.",
          "is_bot": false,
          "headline": "fix: reset per-file progress per run, anchor progress parse, test the…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-18T13:41:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ac2d0b902e2374e1205f97213c70a016a03876b6",
          "body": "…(#86)\n\nwhisper-cli's progress = N% stderr lines are already parsed and forwarded to the per-file progress bar, but the main transcription invocation never passed --print-progress (default off), so whisper emitted nothing and the bar stayed frozen. Add the flag to the transcription argument list. Thanks to @hrones for the fix.",
          "is_bot": false,
          "headline": "fix: add --print-progress so the transcription progress bar advances …",
          "author_name": "hrones",
          "author_login": "hrones",
          "committed_at": "2026-06-18T12:13:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "487260b46fa480e15338a41fafea192a0ce8b8c2",
          "body": "…e-subs option (#83) (#85)\n\nAdds honest controls mirroring what whisper can produce: a single 'Generate original-language subtitles' switch (transcription), a separate 'Translation to English' section (fills the English gap only when absent), and a 'Count image-based subtitles as present' toggle. Replaces a scrapped free-text allow-list. Single source of truth for sidecar extensions; pure, unit-tested gating. 509 tests pass.",
          "is_bot": false,
          "headline": "feat: subtitle generation toggle + English translation section + imag…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-16T18:03:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "24a8422bf5d4c402f2d7103264c8f5ebd6506116",
          "body": "* feat: skip media that already has usable subtitles (#82)\n\nThe auto-generation task transcribed + translated media that already had\nsubtitles (the reporter's 1188-item library wasted ~7h/movie on an iGPU). Two\nroot causes: (1) with EnableTranslation on, the only HasSubtitles skip was\ndisabled so ev\n[…]\ntrip). Full suite 484 green.\n\nDeferred to #83 (out of scope, larger refactor): extracting the ~279-line\nExecuteAsync `alreadyComplete` block — #83 must rework it for desired-languages\nprofiles anyway.",
          "is_bot": false,
          "headline": "feat: skip media that already has usable subtitles (#82) (#84)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-16T14:04:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c0d28a7edd600794c790fe935b16bbd31bd71e23",
          "body": "Bumps Microsoft.Extensions.Http from 9.0.16 to 9.0.17\n\n---\nupdated-dependencies:\n- dependency-name: Microsoft.Extensions.Http\n  dependency-version: 9.0.17\n  dependency-type: direct:production\n  update-type: version-update:semver-patch\n  dependency-group: minor-and-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps: Bump the minor-and-patch group with 1 update (#81)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-16T08:51:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3e9fb6235f0880f4c26c19437461821893d01928",
          "body": "* feat: use native Silero VAD for subtitle speech-onset timing (#78)\n\nThe v3.18.6.0 energy-based silencedetect alignment failed in production — the\nuser re-reported identical \"subtitles appear during the silence before the line\"\nbehavior with a recording. An empirical pilot (whisper-cli on a synthes\n[…]\nles to speech\" as the fallback (used only when VAD is\n  off), drop the misleading \"Recommended\" tag.\n\nAdds 10 tests (UsesVad contract on both providers, VAD tuning-flag denials).\nFull suite 411 green.",
          "is_bot": false,
          "headline": "feat: native Silero VAD for subtitle speech-onset timing (#78) (#80)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-14T22:47:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7b1036363445e084bf7690d65a80ca38fc4dfc8e",
          "body": "… (#78) (#79)\n\n* feat: align subtitle timing to speech, compensate audio start offset (#78)\n\nIssue #78: subtitles appear during the silence before their line is spoken.\nwhisper.cpp emits gapless segments (next.start == prev.end), and the plugin\npassed its SRT through verbatim, so the next subtitle s\n[…]\niling-bare-number, round-trip) and serialized the\nSubtitleService-singleton-mutating test classes into a non-parallel collection\nto kill a pre-existing flaky race. Full suite 391 green, deterministic.",
          "is_bot": false,
          "headline": "feat: align subtitle timing to speech + compensate audio start offset…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-13T20:20:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f13a51a957c6a988ff9f3354872ab943307e64e5",
          "body": "Bumps the github-actions group with 11 updates:\n\n| Package | From | To |\n| --- | --- | --- |\n| [actions/cache](https://github.com/actions/cache) | `4` | `5` |\n| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4` | `7` |\n| [actions/checkout](https://github.com/actions/checkou\n[…]\nsion-update:semver-major\n  dependency-group: github-actions\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "ci: bump the github-actions group with 11 updates (#77)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-07T17:21:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "27701ce8fe3e38541b94e84cc3659d3a1fa60a83",
          "body": "Remove the semver-major ignore from the github-actions ecosystem so action major upgrades (Node-runtime bumps) get PRs. npm/docker majors stay gated.",
          "is_bot": false,
          "headline": "ci(dependabot): allow github-actions major bumps (#76)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-07T16:30:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3306435c4ce70c137b124dcd03fe2ebfb5d25b6b",
          "body": "- actions/configure-pages: v4→v5\n- actions/stale: v9→v10\n- softprops/action-gh-release: v1→v2",
          "is_bot": false,
          "headline": "ci(deps): bump deprecated GitHub Actions to current majors (#75)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-07T15:46:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "027b5525983cccd33dd9a0981e174260ddf6d3c9",
          "body": "…SIGILL (#74)\n\nReported on #70: after the libgomp fix, a TrueNAS user's transcription failed\nwith exit 132 (SIGILL). Their CPU lacks AVX, but our cpu/cuda12/vulkan binaries\nare compiled with AVX/AVX2, so they crash on launch. The auto-fallback didn't\nhelp because (a) validation runs `whisper-cli --h\n[…]\nAVX-capable users to the slower build; the runtime\nSIGILL handler remains the backstop.\n\nTests: CpuInfoHasAvx parser (avx present/absent/avx512-only/empty) and\nVariantRequiresAvx mapping. 367 passing.",
          "is_bot": false,
          "headline": "fix: handle CPUs without AVX — detect, recommend noavx, fall back on …",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-07T13:38:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2c6960f8892fb9e458c25d8ed871a070e02512e5",
          "body": "…(#73)\n\nReview hardening for the #70/#72 auto-fallback:\n\n- DownloadBinaryAsync: replace recursive fallback with an iterative walk over\n  the fallback chain. The recursive version had the inner frame release the\n  _isRunning lock mid-chain (safe only by accident of an unconditional return);\n  the loo\n[…]\nurns null for CPU\" — cpu now maps to noavx).\n- Tests: cover unknown/empty/null/case-sensitive inputs and add a chain-\n  termination/no-cycle property test guarding against an accidental fallback loop.",
          "is_bot": false,
          "headline": "refactor: harden binary fallback (iterative walk, cycle-guard tests) …",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-06T22:45:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e56f8ec4c643d276ba74d6dd3ef9f9a6d8c01336",
          "body": "…missing (#72)\n\nv3.18.2.0 disabled OpenMP on all variants to fix the libgomp.so.1 failure in\nminimal containers — but that slowed CPU transcription for everyone to rescue a\nminority, and still didn't route the affected user anywhere.\n\nBetter approach: keep the fast OpenMP-linked builds for cpu/cuda1\n[…]\n: cpu -> noavx (arm64 asset resolved by platform)\n- Bump cache keys v10->v11, rocm v3->v4 so OpenMP-on binaries rebuild\n- README: libgomp1 required for cpu/gpu again, documents the noavx auto-fallback",
          "is_bot": false,
          "headline": "fix: keep OpenMP for performance, auto-fall back to noavx if libgomp …",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-06T21:08:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8afd3d5283de78845aebefe3b3e6ebf49620e9e5",
          "body": "… (#71)\n\n* fix: self-contained CPU binary + surface transcription failures (#70)\n\nTwo bugs from #70:\n\n1. whisper-cli failed at transcribe time in minimal TrueNAS containers with\n   \"libgomp.so.1: cannot open shared object file\". The binaries dynamically\n   linked the GNU OpenMP runtime. Disable Open\n[…]\nrstError is preserved and the queue/UI shows the actionable cause.\n- Clarify that libgomp/OpenMP detection is informational only (binaries are now\n  built with -DGGML_OPENMP=OFF), matching the README.",
          "is_bot": false,
          "headline": "fix: self-contained CPU binary + surface transcription failures (#70)…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-06-06T16:16:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5df9f8a12745fbbef2fd657131de58753d3a62a2",
          "body": "…g (#69)\n\nThe semicolons in CMAKE_CUDA_ARCHITECTURES were interpreted as shell\ncommand separators when expanded via ${{ matrix.cmake_flags }}.",
          "is_bot": false,
          "headline": "fix(ci): quote CUDA architectures to prevent shell semicolon splittin…",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-25T17:33:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d16d8b6b56d47fcd51d2cd7678af2cac00cf6ab7",
          "body": "- Remove non-existent cudart-static sub-package (static lib included in cudart-dev)\n- Remove non-existent libcublas-static-12-6 (static lib included in libcublas-dev)\n- Replace vulkan-headers + shaderc with glslc (correct package names on Noble)",
          "is_bot": false,
          "headline": "fix(ci): correct CUDA and Vulkan package names for Ubuntu 24.04 (#68)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-25T17:23:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bc42c14ff3313f30d96aec2df67536592c4db698",
          "body": "Add -DGGML_STATIC=ON to both CUDA matrix entries, which statically\nlinks cudart, cublas, and cublasLt into the binary. The only remaining\nruntime dependency is libcuda.so.1 (driver API), which\nnvidia-container-toolkit always provides.\n\nAlso adds -DCMAKE_CUDA_ARCHITECTURES=61;70;75;80;86;89;90 to ens\n[…]\n-and-suspenders measure, adds auto-fallback: if a GPU binary\nfails validation (missing shared libs), automatically downloads the\ncorresponding CPU variant instead of leaving the user stuck.\n\nFixes #66",
          "is_bot": false,
          "headline": "fix: statically link CUDA runtime to eliminate container deps (#67)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-25T17:11:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c16ea15632218cfd7b9ded19b0a2afc6afba56a8",
          "body": null,
          "is_bot": false,
          "headline": "chore: remove AGENTS.md (migrated to CLAUDE.md)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-25T13:44:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4333e17defb8922a285c610bd62d10312188eaa6",
          "body": null,
          "is_bot": false,
          "headline": "chore: merge AGENTS.md into CLAUDE.md",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-25T13:44:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "46b08ec4662dd2e614f32c2f56c2702d203d8a03",
          "body": null,
          "is_bot": false,
          "headline": "chore: add CLAUDE.md",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-25T13:29:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "506c3b0e59eba2916011ff83ba740ff5671d9697",
          "body": "* fix(ci): add vulkan-headers package for Vulkan builds\n\nLunarG's libvulkan-dev on 22.04 doesn't include vulkan.h — it's in\nthe separate vulkan-headers package.\n\n* feat: add custom whisper-cli arguments field\n\nAdd a \"Custom Whisper Arguments\" text input in Advanced settings that\nappends user-provide\n[…]\n.\n\nAlso makes AppendCustomArgs internal for testability and adds 10 unit\ntests covering: empty input, valid args, denied flags, equals-style,\ncase insensitivity, mixed valid+denied, and null handling.",
          "is_bot": false,
          "headline": "feat: custom whisper-cli arguments (#65)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-19T09:22:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e1b3a44ad43c31955399d7c4f6464913ee1f13da",
          "body": "Bumps Microsoft.Extensions.Http from 9.0.15 to 9.0.16\n\n---\nupdated-dependencies:\n- dependency-name: Microsoft.Extensions.Http\n  dependency-version: 9.0.16\n  dependency-type: direct:production\n  update-type: version-update:semver-patch\n  dependency-group: minor-and-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "deps: Bump the minor-and-patch group with 1 update (#63)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-05-19T09:00:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f13709090f5a3dce48064c8c4cea01fcd9067f41",
          "body": "LunarG's libvulkan-dev on 22.04 doesn't include vulkan.h — it's in\nthe separate vulkan-headers package.",
          "is_bot": false,
          "headline": "fix(ci): add vulkan-headers package for Vulkan builds (#62)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-15T19:01:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a65fbf6023b0d5506a1152b712b0fa4dd3545fa2",
          "body": "The self-hosted runner (Ubuntu 22.04) has the LunarG repo configured\nwhich provides the shaderc package containing glslc.",
          "is_bot": false,
          "headline": "fix(ci): use shaderc package for glslc on Ubuntu 22.04 (#61)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-15T16:25:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7c1c462bdc4c23f991d560fa02c2fe3c828002e",
          "body": "- Add software-properties-common + wget (needed by CUDA toolkit action)\n- Add LunarG Vulkan SDK repo for glslc (not in base Ubuntu 22.04)\n- Clean /tmp before clone (self-hosted runners persist /tmp across jobs)",
          "is_bot": false,
          "headline": "fix(ci): resolve self-hosted runner dependency issues (#60)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-15T15:43:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cb94afd50d3fe3b1d4e5b335837aa4d95188279c",
          "body": "- Use matrix.os for runs-on (was hardcoded, causing scheduling issues)\n- Bump cache key v7→v8 to force fresh builds on self-hosted runners\n  (old cache from GitHub-hosted runners had wrong paths)\n- Fetch live manifest from Pages instead of committing back to main\n  (branch protection blocks direct pushes from Actions)\n- Deduplicate versions when prepending to manifest",
          "is_bot": false,
          "headline": "fix(ci): resolve self-hosted runner build failures (#59)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-15T15:28:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b894dc0e268f5d5255c1d93d1658fbb0db97b75b",
          "body": "- Manifest now preserves version history (last 5 releases) using jq\n  instead of overwriting with only the latest\n- Seed manifest.json with actual checksums for v3.14.1–v3.17.0\n- Pages artifact deploys only manifest.json, not entire workspace\n- Commit manifest back to repo so versions accumulate across releases\n- Add arm64-noavx build variant to matrix and release assets",
          "is_bot": false,
          "headline": "ci: improve release workflow and fix manifest deployment (#58)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-15T15:04:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "289dd25d983af984f877062d353f83850263f286",
          "body": null,
          "is_bot": false,
          "headline": "ci: add ARM64 cross-compilation toolchain for linux-arm64 build",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-15T12:10:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "272ecd22efcb6398ffa684a8b6d7f46d57cde905",
          "body": null,
          "is_bot": false,
          "headline": "ci: migrate build-whisper to self-hosted runners",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-05-15T09:09:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4cebaeac63b61c1f890dcc5a865a522d55d8b7f9",
          "body": null,
          "is_bot": false,
          "headline": "ci: migrate to self-hosted runners",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-14T08:37:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6704c696dd2ded1ee29bc98de7b9975e684dfb92",
          "body": null,
          "is_bot": false,
          "headline": "ci: migrate to self-hosted runners",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-14T08:34:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "89153867be9f0bf68203f7236f9dd14616e9ab93",
          "body": "* fix: interrupt transcription when playback starts mid-process\n\nPreviously, pause-on-playback only checked between items. Once whisper\nstarted transcribing a file (which can take hours for long content), it\nwould run to completion regardless of active playback.\n\nNow monitors sessions during transcr\n[…]\nk starts. The partial SRT is saved automatically, and after\nplayback ends the item is retried with resume-from-partial logic.\n\nCloses #49\n\n* fix: await monitorTask to prevent unobserved task exception",
          "is_bot": false,
          "headline": "fix: interrupt transcription when playback starts mid-process (#56)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-13T13:48:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "13ecc658027189d7eeecfc3669d7aa585f562b3c",
          "body": "* feat: add search/filter box in Subtitle Management\n\nAdds a text search input between the library selector and items table.\nFilters by item name or filename with 300ms debounce. Server-side\nfiltering via new searchTerm query parameter on the Items endpoint.\n\nCloses #54\n\n* refactor: push search filtering to database layer\n\nUse InternalItemsQuery.SearchTerm instead of loading all items into\nmemory then filtering. Also adds maxlength=200 on the search input.",
          "is_bot": false,
          "headline": "feat: add search/filter box in Subtitle Management (#55)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-12T09:13:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3db3dc59b2d410c6cb288b48690ab47284f55f86",
          "body": "* feat: add GPU compatibility variants for older CPUs\n\nAdd cuda12-noavx and vulkan-noavx build variants for users with\nolder CPUs (no AVX support) that have a dedicated GPU. Fixes the\nillegal instruction crash when using CUDA/Vulkan on old CPUs\n(e.g. TrueNAS Scale with GTX 1050 Ti).\n\nAlso pins expli\n[…]\n assets and update test assertions\n\nAdd cuda12-noavx and vulkan-noavx to the GitHub Release files list\nso users can actually download them. Update BinaryCatalogTests to\nexpect 7 variants instead of 5.",
          "is_bot": false,
          "headline": "feat: add GPU compatibility variants for older CPUs (#53)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-11T09:54:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f72b3b52dbf4d1e97ba525f5176d5f8427507017",
          "body": "Ubuntu 22.04 lacks glslc (CMake FindVulkan requires it). Vulkan users\nrun modern distros so glibc 2.35 compat isn't needed for this variant.\nCPU builds remain on 22.04 for maximum container compatibility.",
          "is_bot": false,
          "headline": "fix(ci): build Vulkan variant on Ubuntu 24.04",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-05-11T09:31:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5d2d86de73c32d467f53af6ed7b97bb7265848a2",
          "body": "glslc is not a standalone package on Ubuntu 22.04 — it's provided by\nglslang-tools. This fixes the Vulkan binary build step that broke after\nthe glibc compatibility migration from Ubuntu 24.04 to 22.04.",
          "is_bot": false,
          "headline": "fix(ci): use glslang-tools for Vulkan build on Ubuntu 22.04",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-05-11T09:29:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "efc3fdff35f3ed61a9c8fad4a22fdc43e8b25c17",
          "body": "* feat: pause subtitle generation during active playback\n\nAdds a \"Pause generation during playback\" checkbox. When enabled, the\nscheduled task polls ISessionManager.Sessions between items and waits\nuntil no user is actively playing media before processing the next file.\n\nCloses #49\n\n* review: add 4-\n[…]\n, immediate return on idle\nsessions, waiting until playback stops, cancellation during wait, and\nempty session list. Also reports \"Waiting for playback to stop\" phase\nto the Queue API during the wait.",
          "is_bot": false,
          "headline": "feat: pause subtitle generation during active playback (#52)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-11T09:15:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6222d7003b7388faf137762158d1f9801ecf1d45",
          "body": "Binaries built on Ubuntu 24.04 require glibc 2.38 which isn't available\non Debian 12 (glibc 2.36) or older distros. Building on 22.04 targets\nglibc 2.35, covering Debian 12+, Ubuntu 22.04+, and all current distros.\n\nFixes #50",
          "is_bot": false,
          "headline": "fix: build whisper binaries on Ubuntu 22.04 for glibc 2.35 compat (#51)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-11T08:52:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "39b6521c51bb6b6558427656aeca00110c95569f",
          "body": "Users on minimal containers (TrueNAS Scale, barebones Docker) couldn't\nfind the noavx binary in the UI — it existed in releases but had no\ncatalog entry. Now shows as \"CPU (Compatibility)\" with appropriate hint.\n\nFixes #46",
          "is_bot": false,
          "headline": "fix: add noavx variant to Setup tab binary dropdown (#48)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-07T22:58:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "81ff1f2549009c59a2e058b2113e31ea2f6a8e17",
          "body": "The noavx binary is meant to run on minimal environments (e.g. TrueNAS\nScale Jellyfin containers) that don't ship libgomp.so.1. whisper.cpp\nfalls back to pthreads threading when OpenMP is disabled.\n\nFixes #46",
          "is_bot": false,
          "headline": "fix: disable OpenMP in noavx build to remove libgomp dependency (#47)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-07T21:38:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9439e334de4acdb02862ac839d37f40070d67143",
          "body": "Bug reports now require plugin/Jellyfin version, engine type, model,\nSetup/Status endpoint output, filtered logs, and Docker config.\nBlank issues disabled in favor of structured forms.",
          "is_bot": false,
          "headline": "Add issue templates requiring diagnostic info",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-05-07T08:41:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1d6c20ea896040a7dd5564685a4bcbc116c3c7e5",
          "body": "* feat: add TranslationOnly subtitle mode (#44)\n\nAdds a new SubtitleMode (TranslationOnly=3) that skips native-language\ntranscription entirely and only produces English translated subtitles\nin a single whisper pass. Halves processing time for users who only\nneed English subs from foreign-language me\n[…]\nteTranslationVisibility() into loadConfiguration callback to\neliminate race condition, normalize EnableTranslation on save to prevent\nstate pollution, and remove racy setTimeout from pageshow handler.",
          "is_bot": false,
          "headline": "feat: add TranslationOnly subtitle mode (#45)",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-05-05T10:57:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "26fcc006bcd09937a904f53c4a684934ccb7a270",
          "body": "The default whisper-cli-linux-x64 stays fully optimized (AVX2/FMA/BMI2)\nfor the majority of users. A separate whisper-cli-linux-x64-noavx binary\n(SSE4.2 only) is provided for Celeron/Atom/older CPUs lacking AVX.\n\nRef #43",
          "is_bot": false,
          "headline": "Keep default x64 binary optimized (AVX2), add -noavx variant",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-05-04T23:12:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "612aa159b84bcd1567991507ada60a27c07796fb",
          "body": "GGML_BMI2 defaults to ON and was not explicitly disabled in the generic\nbuild. J4125 (Goldmont Plus) lacks BMI2 — pdep/pext instructions cause\nSIGILL even with AVX/FMA/F16C already disabled.\n\nRef #43",
          "is_bot": false,
          "headline": "Fix generic x64 build: disable BMI2 for Celeron/Atom CPUs",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-05-04T23:08:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f0ac4fe23e7c5286f7d1d8874ff2232b295bf084",
          "body": "The default whisper-cli-linux-x64 was built with -march=native on GHA\nrunners, baking in AVX2/FMA/F16C. This crashes with SIGILL (exit 132)\non Intel Celeron J4125, Atom, and other Goldmont/Tremont CPUs that only\nsupport SSE4.2.\n\nNow ships two x64 CPU binaries:\n- whisper-cli-linux-x64: generic SSE4.2-only (works everywhere)\n- whisper-cli-linux-x64-avx2: optimized for Haswell+ (~30-40% faster)\n\nFixes #43",
          "is_bot": false,
          "headline": "Ship generic x86_64 binary for CPUs without AVX (Celeron/Atom)",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-05-04T17:38:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "60b00d0d48554903fe24283fdb1c2687d4fc1e92",
          "body": "Releases the remote Whisper API key authentication support merged in PR #42.",
          "is_bot": false,
          "headline": "Bump version to 3.12.2.0 for API key auth feature",
          "author_name": "GeiserX",
          "author_login": "GeiserX",
          "committed_at": "2026-04-29T19:28:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de720959514cc3363f3be80a3834aaa5b37c51ca",
          "body": "feat(remote): support API key auth for remote Whisper API",
          "is_bot": false,
          "headline": "Merge pull request #42 from mvanhorn/osc/40-api-key-auth",
          "author_name": "Sergio Fernández",
          "author_login": "GeiserX",
          "committed_at": "2026-04-29T19:27:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "919cffdb631448f773265accf9fa41b16be53d43",
          "body": "…caps, defensive trim\n\n- RemoteWhisperProvider: log a warning when API key is configured with a\n  non-HTTPS URL, and trim the key defensively in the constructor.\n- configPage.html: maxlength=256, autocomplete=new-password, spellcheck=false\n  on the API key input.\n- Capitalize 'Speaches' (the product\n[…]\nuration suggestion -- the\n  factory takes config as a DI argument intentionally, switching to the\n  singleton would couple unit tests to global Plugin.Instance state and\n  ripple through 3 call sites.",
          "is_bot": false,
          "headline": "Address review feedback: cleartext warning, HTML hardening, Speaches …",
          "author_name": "Matt Van Horn",
          "author_login": "mvanhorn",
          "committed_at": "2026-04-29T17:23:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        }
      ],
      "releases_count": 91,
      "commits_last_year": 249,
      "latest_release_at": "2026-07-13T21:26:45Z",
      "latest_release_tag": "v4.3.1.0",
      "releases_from_tags": false,
      "days_since_last_push": 3,
      "active_weeks_last_year": 20,
      "days_since_latest_release": 10,
      "mean_days_between_releases": 1.2
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 57,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": []
    },
    "popularity": {
      "forks": 6,
      "stars": 81,
      "watchers": 1,
      "fork_history": {
        "days": [
          {
            "date": "2026-04-29",
            "count": 1
          },
          {
            "date": "2026-05-10",
            "count": 1
          },
          {
            "date": "2026-05-21",
            "count": 1
          },
          {
            "date": "2026-06-18",
            "count": 1
          },
          {
            "date": "2026-06-20",
            "count": 1
          },
          {
            "date": "2026-07-22",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 6,
        "total_forks": 6
      },
      "star_history": null,
      "open_issues_and_prs": 2
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "WhisperSubs.Tests/WhisperSubs.Tests.csproj",
        "WhisperSubs.csproj"
      ],
      "largest_source_bytes": 105363,
      "source_files_sampled": 107,
      "oversized_source_files": 1,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 41683
    },
    "dependencies": {
      "manifests": [
        "WhisperSubs.Tests/WhisperSubs.Tests.csproj",
        "WhisperSubs.csproj"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 3,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 5,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "nuget"
      ],
      "dependencies": [
        {
          "name": "Microsoft.NET.Test.Sdk",
          "manifest": "WhisperSubs.Tests/WhisperSubs.Tests.csproj",
          "ecosystem": "nuget",
          "version_constraint": "17.*"
        },
        {
          "name": "xunit",
          "manifest": "WhisperSubs.Tests/WhisperSubs.Tests.csproj",
          "ecosystem": "nuget",
          "version_constraint": "2.*"
        },
        {
          "name": "xunit.runner.visualstudio",
          "manifest": "WhisperSubs.Tests/WhisperSubs.Tests.csproj",
          "ecosystem": "nuget",
          "version_constraint": "2.*"
        },
        {
          "name": "Moq",
          "manifest": "WhisperSubs.Tests/WhisperSubs.Tests.csproj",
          "ecosystem": "nuget",
          "version_constraint": "4.*"
        },
        {
          "name": "coverlet.collector",
          "manifest": "WhisperSubs.Tests/WhisperSubs.Tests.csproj",
          "ecosystem": "nuget",
          "version_constraint": "6.*"
        },
        {
          "name": "Jellyfin.Model",
          "manifest": "WhisperSubs.csproj",
          "ecosystem": "nuget",
          "version_constraint": "10.11.0"
        },
        {
          "name": "Jellyfin.Controller",
          "manifest": "WhisperSubs.csproj",
          "ecosystem": "nuget",
          "version_constraint": "10.11.0"
        },
        {
          "name": "Microsoft.Extensions.Http",
          "manifest": "WhisperSubs.csproj",
          "ecosystem": "nuget",
          "version_constraint": "9.0.18"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "coverlet.collector",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Jellyfin.Controller",
            "direct": true,
            "version": "10.11.0",
            "ecosystem": "nuget"
          },
          {
            "name": "Jellyfin.Model",
            "direct": true,
            "version": "10.11.0",
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.Extensions.Http",
            "direct": true,
            "version": "9.0.18",
            "ecosystem": "nuget"
          },
          {
            "name": "Microsoft.NET.Test.Sdk",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "Moq",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "xunit",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          },
          {
            "name": "xunit.runner.visualstudio",
            "direct": true,
            "version": null,
            "ecosystem": "nuget"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 8,
        "direct_count": 8,
        "indirect_count": 0
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 102,
        "open_issues": 2,
        "closed_ratio": 0.941,
        "closed_issues": 32,
        "closed_unmerged_prs": 1
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "GeiserX",
          "commits": 235,
          "avatar_url": "https://avatars.githubusercontent.com/u/9169332?v=4"
        },
        {
          "type": "User",
          "login": "mvanhorn",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/455140?v=4"
        },
        {
          "type": "User",
          "login": "hrones",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/235208089?v=4"
        }
      ],
      "contributors_sampled": 3,
      "top_contributor_share": 0.983
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "build-release.yml",
        "ci.yml",
        "stale.yml",
        "worker-image.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 3,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "19 out of 19 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/18 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 23 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 4,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "129503878cd479d1068694641a2ec0eb20ac9781",
        "ran_at": "2026-07-24T07:55:28Z",
        "aggregate_score": 5.2,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-24T01:51:39Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-20T23:25:40Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 5,
          "created_at": "2026-04-06T22:42:18Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 41,
          "created_at": "2026-04-29T07:34:23Z",
          "last_comment_at": "2026-04-29T08:07:36Z",
          "last_comment_author": "GeiserX"
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/GeiserX/whisper-subs",
    "host": "github.com",
    "name": "whisper-subs",
    "owner": "GeiserX"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 63,
      "inputs": {
        "security": 62,
        "vitality": 83,
        "community": 43,
        "governance": 50,
        "engineering": 75
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 83,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 78,
            "inputs": {
              "commits_last_year": 249,
              "human_commit_share": 0.95,
              "days_since_last_push": 3,
              "active_weeks_last_year": 20
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 3 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "20/52 weeks with commits",
                "points": 13.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 20
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "249 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 249
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 23 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 91,
              "latest_release_tag": "v4.3.1.0",
              "releases_from_tags": false,
              "days_since_latest_release": 10,
              "mean_days_between_releases": 1.2
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "91 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 91
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 10 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 10
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~1.2 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 1.2
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 10,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 10 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 10
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 43,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 37,
            "inputs": {
              "forks": 6,
              "stars": 81,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "81 stars",
                "points": 30.9,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 81
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "6 forks",
                "points": 5.8,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 6
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "1 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (GPL-3.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "GPL-3.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 50,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 14,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 3,
              "top_contributor_share": 0.983
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 98% of commits",
                "points": 0.4,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 98
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "3 contributors",
                "points": 4.1,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "merged_prs": 102,
              "open_issues": 2,
              "closed_issues": 32,
              "issue_closed_ratio": 0.941,
              "closed_unmerged_prs": 1
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "94% of issues closed",
                "points": 44,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 94
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "102/103 decided PRs merged",
                "points": 37.9,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 102,
                      "decided": 103
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/18 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 62,
            "inputs": {
              "followers": 113,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "GeiserX",
              "public_repos": 186,
              "account_age_days": 4302
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "113 followers of GeiserX",
                "points": 14.8,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 113,
                      "login": "GeiserX"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "186 public repos, account ~11 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 186
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 11
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 75,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "4 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "19 out of 19 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "topics": [
                "accessibility",
                "ai",
                "automation",
                "csharp",
                "dotnet",
                "hacktoberfest",
                "homelab",
                "jellyfin",
                "jellyfin-plugin",
                "media-management",
                "media-server",
                "open-source",
                "parakeet",
                "self-hosted",
                "speech-to-text",
                "stt",
                "subtitles",
                "transcription",
                "whisper",
                "whisper-cpp"
              ],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "20 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 20
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 62,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": null,
            "notes": [],
            "value": 52,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 18,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 0,
              "scorecard_aggregate": 5.2
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "19 out of 19 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/18 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 23 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 2,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 3 resolved dependencies against OSV; 5 could not be assessed (no resolved version, an unsupported ecosystem, or beyond the reported package list). This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories",
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 3
                }
              },
              {
                "code": "advisories_unassessed",
                "params": {
                  "count": 5
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 0,
              "affected_packages": 0,
              "assessed_packages": 3,
              "unassessed_packages": 5,
              "affected_by_severity": "none",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "transitive set not separable from development and test dependencies in this scope",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_scope_not_separable",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 3,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 78,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.979,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 41683
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "93 of 95 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 93,
                      "sampled": 95
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 64,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0,
              "toolchain_manifests": [
                "WhisperSubs.Tests/WhisperSubs.Tests.csproj",
                "WhisperSubs.csproj"
              ],
              "dependency_bot_commit_share": 0.05
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "WhisperSubs.Tests/WhisperSubs.Tests.csproj, WhisperSubs.csproj (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "WhisperSubs.Tests/WhisperSubs.Tests.csproj, WhisperSubs.csproj"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "C# (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "C#"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "5 of the last 100 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 5,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "C#",
              "largest_source_bytes": 105363,
              "source_files_sampled": 107,
              "oversized_source_files": 1
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "C# (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "C#"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "1/107 source files over 60KB",
                "points": 54.5,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 107,
                      "oversized": 1
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "Could not fetch nuget package 'WhisperSubs' from its registry"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-24T07:55:45.588282Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/g/GeiserX/whisper-subs.svg",
  "full_name": "GeiserX/whisper-subs",
  "license_state": "standard",
  "license_spdx": "GPL-3.0"
}

评分是信号,而非担保。 评分反映的是 GitHub 上公开可见的实践——不是代码审计,也不是安全保证。

缺失数据将被剔除并重新归一化权重,绝不按零分计。方法论已版本化并公开:指标 v1.13.0、模式 v0.27.0—— 完整方法论 · 指标知识库.

单项结果在整体记录中的位置: 汇总统计.