公开记录
软件健康报告模式 0.26.0 · 指标 1.13.0 · 2026-07-22 09:13 UTC

compgenlab / batchq

GoMIT★ 0 星标⑂ 0 复刻始于 2025年4月在 GitHub 上查看 ↗

compgenlab/batchq 的健康指数为 100 分中的 57 分,处于「中等」区间。 其得分最高的类别是AI Readiness(81/100),最低的是Community & Adoption(24/100)。 最近一次更新在 1 天前。 近期的大部分工作由 1 位贡献者完成。

57
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

0 关注者12 个公开仓库始于 2025年4月

该仓库由组织支持——共同承担、可问责的托管责任,可延续于任何单一维护者之后。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
Gogithub.com/compgenlab/batchqv0.4.0-171 天前

按类别列示的指标

活力

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

80良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 1 天前
9.7/36提交节奏 — 52 周中有 14 周有提交
18/18提交量 — 最近一年 211 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year211
human_commit_share1
days_since_last_push1
active_weeks_last_year14

发布纪律

90优秀
评分方式
27/27有发布版本 — 已发布 17 个发布版本
36/36发布时效 — 最近一次发布版本于 1 天前
27/27发布节奏 — 约每 5 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — Project has not signed or included provenance with any releases.
所用输入
releases_count17
latest_release_tagv0.4.0
releases_from_tags
days_since_latest_release1
mean_days_between_releases5

社区与采用

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

24危急 · 占总体的 18%
评分方式
0/60星标 — 0 个星标
0/25复刻 — 0 个复刻
0/15关注者 — 1 位关注者
所用输入
forks0
stars0
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

50中等
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(MIT)
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

可持续性与治理

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

57中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 3 contributing companies or organizations -- score normalized to 10
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
46.8/46.8议题解决 — 100% 的议题已关闭
35.2/38.3PR 接受 — 已裁定的 PR 中 58/63 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/14 approved changesets -- score normalized to 0
所用输入
merged_prs58
open_issues0
closed_issues1
issue_closed_ratio1
closed_unmerged_prs5
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
0/25所有者影响力 — compgenlab 有 0 位关注者
10.6/25既往记录 — 12 个公开仓库,账户约 1 年
所用输入
followers0
owner_typeOrganization
is_verified
owner_logincompgenlab
public_repos12
account_age_days460
评分方式
25/25已发布且可解析 — go 上有 1 个软件包
35/35发布时效 — 最近一次发布于 1 天前
20/20版本历史 — 17 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesgithub.com/compgenlab/batchq
ecosystemsgo
any_deprecated
min_days_since_publish1

工程质量

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

67中等 · 占总体的 20%

工程实践

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

文档

65中等
评分方式
30/30README
25/25文档目录
0/15文档 / 主页站点
0/10仓库描述
0/10主题标签
10/10Wiki
所用输入
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

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

49存在风险 · 占总体的 16%

安全态势

39存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.5/2.5CI-Tests — 14 out of 14 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/14 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 3 contributing companies or organizations -- score normalized to 10
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — 无数据
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
0/5Security-Policy — security policy file not 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
6.8/7.5Vulnerabilities — 1 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate3.9
已排除计分(无数据或不适用):packaging。 其余权重已重新归一化。
评分方式
26.6/35直接依赖不含已知公告 — 1 个受影响:golang.org/x/sys v0.22.0 (unknown)
0/25间接依赖不含已知公告 — 在此范围内,传递依赖集合无法与开发和测试依赖区分
40/40没有长期未处理的公告 — 没有公告公开超过 90 天
所用输入
sourceosv
advisories1
affected_packages1
assessed_packages14
unassessed_packages0
affected_by_severityunknown 1
direct_affected_packages1
已排除计分(无数据或不适用):间接依赖不含已知公告。 其余权重已重新归一化。 已将 14 个已解析依赖与 OSV 比对。 该仓库未发布任何索引可解析的软件包,因此改为评估仓库依赖图。该图将开发与测试版本固定同交付的依赖混在一起,因此仅对声明的运行时依赖计分;传递性发现仅作为背景信息列出,不计入评分。 未对可达性进行分析。

AI 就绪度

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

81良好 · 占总体的 0%
评分方式
45/45代理指令 — CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 100 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share1
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes46,907
评分方式
18/18一条命令的引导启动 — Makefile
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — Go(静态类型)
10/10可复现环境 — devcontainer, Dockerfile, lockfile
10/10已体现的代理实践 — 最近 100 次提交中有 62 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
所用输入
has_nix
has_tests
lockfilesgo.sum
has_dockerfile
typed_language
bootstrap_filesMakefile
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0.62
toolchain_manifestsgo.mod
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — Go(静态类型)
54.5/55可控的文件大小 — 采样的 109 个源文件中有 1 个超过 60KB
所用输入
primary_languageGo
largest_source_bytes79,814
source_files_sampled109
oversized_source_files1

关键数据

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

更多细节

OpenSSF Scorecard 3.9 / 10
3.9综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
10CI-Tests14 out of 14 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/14 approved changesets -- score normalized to 0
10Contributorsproject has 3 contributing companies or organizations -- score normalized to 10
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
不适用Packagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
9Vulnerabilities1 existing vulnerabilities detected
直接依赖 5
注册表软件包版本约束清单文件
Gogithub.com/spf13/cobrav1.9.1go.mod
Gogithub.com/BurntSushi/tomlv1.6.0go.mod
Gogithub.com/google/uuidv1.6.0go.mod
Gogolang.org/x/sysv0.22.0go.mod
Gomodernc.org/sqlitev1.34.5go.mod
全部依赖 14

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

注册表软件包版本关系
Gogithub.com/burntsushi/tomlv1.6.0直接
Gogithub.com/google/uuidv1.6.0直接
Gogithub.com/spf13/cobrav1.9.1直接
Gogolang.org/x/sysv0.22.0直接
Gomodernc.org/sqlitev1.34.5直接
Gogithub.com/dustin/go-humanizev1.0.1间接
Gogithub.com/inconshreveable/mousetrapv1.1.0间接
Gogithub.com/mattn/go-isattyv0.0.20间接
Gogithub.com/ncruces/go-strftimev0.1.9间接
Gogithub.com/remyoudompheng/bigfftv0.0.0-20230129092748-24d4a6f8daec间接
Gogithub.com/spf13/pflagv1.0.6间接
Gomodernc.org/libcv1.55.3间接
Gomodernc.org/mathutilv1.6.0间接
Gomodernc.org/memoryv1.8.0间接
依赖安全公告 1

该仓库未发布可被索引解析的包,因此评估的是其自身的依赖图——共 14 个包,其中也包含从不交付的开发与测试版本固定:1 个存在已知公告,1 个为直接依赖。

软件包版本关系严重程度公告数修复版本
golang.org/x/sysv0.22.0直接未知10.44.0

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 1065,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Go": 810107,
        "HTML": 50829,
        "Shell": 2292,
        "Makefile": 1901,
        "Dockerfile": 603
      },
      "pushed_at": "2026-07-21T01:30:04Z",
      "created_at": "2025-04-22T03:30:48Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-21T01:28:34Z",
      "description": null,
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Computational Genomics @IndianaU",
      "type": "Organization",
      "login": "compgenlab",
      "company": null,
      "location": "United States of America",
      "followers": 0,
      "avatar_url": "https://avatars.githubusercontent.com/u/208039369?v=4",
      "created_at": "2025-04-17T14:43:35Z",
      "is_verified": null,
      "public_repos": 12,
      "account_age_days": 460
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-07-21T01:32:12Z"
        },
        {
          "tag": "v0.3.8",
          "kind": "patch",
          "published_at": "2026-07-12T13:10:55Z"
        },
        {
          "tag": "v0.3.7",
          "kind": "patch",
          "published_at": "2026-07-08T19:26:46Z"
        },
        {
          "tag": "v0.3.6",
          "kind": "patch",
          "published_at": "2026-07-08T16:14:16Z"
        },
        {
          "tag": "v0.3.5",
          "kind": "patch",
          "published_at": "2026-07-02T03:07:37Z"
        },
        {
          "tag": "v0.3.4",
          "kind": "patch",
          "published_at": "2026-07-01T13:16:33Z"
        },
        {
          "tag": "v0.3.3",
          "kind": "patch",
          "published_at": "2026-06-11T17:21:22Z"
        },
        {
          "tag": "v0.3.2",
          "kind": "patch",
          "published_at": "2026-06-10T07:59:41Z"
        },
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2026-06-10T05:06:04Z"
        },
        {
          "tag": "v0.2.8",
          "kind": "patch",
          "published_at": "2026-06-05T17:11:07Z"
        },
        {
          "tag": "v0.2.7",
          "kind": "patch",
          "published_at": "2026-06-05T16:41:41Z"
        },
        {
          "tag": "v0.2.6",
          "kind": "patch",
          "published_at": "2026-06-05T03:53:07Z"
        },
        {
          "tag": "v0.2.5",
          "kind": "patch",
          "published_at": "2026-06-04T08:50:39Z"
        },
        {
          "tag": "v0.2.4",
          "kind": "patch",
          "published_at": "2026-06-04T03:11:38Z"
        },
        {
          "tag": "v0.2.3",
          "kind": "patch",
          "published_at": "2026-06-03T15:35:52Z"
        },
        {
          "tag": "v0.2.2",
          "kind": "patch",
          "published_at": "2026-05-17T16:44:57Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2026-05-17T01:52:20Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "661b9ee06db3f16cd5e39286f60fa902d6c88bce",
          "body": "fix(queue): single proxied jobs show SLURM status too",
          "is_bot": false,
          "headline": "Merge pull request #64 from compgenlab/fix/queue-single-slurm-status",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-21T01:28:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fe114dcc768d5814af7bec9c3b12b2d7ad19412a",
          "body": "…QUEUED)\n\nFollow-up to the collapsed-array change: a non-array SLURM job still showed\nPROXYQUEUED in the status column while array rows showed the SLURM state. Use\neffectiveStatus for the single-job row's status column too, so a proxied job\ndisplays its slurm_status (PENDING/RUNNING/…). The batchq s\n[…]\ne trailing SLURM cell now shows just the id (the status moved\nto the status column).\n\nTest: TestEffectiveStatus. Full suite green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(queue): single proxied jobs show SLURM status too (not just PROXY…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-21T01:21:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "053aa2b64af5ec024f222b063fbe6f750654752c",
          "body": "fix(queue): collapsed array row shows SLURM state, not just PROXYQUEUED",
          "is_bot": false,
          "headline": "Merge pull request #63 from compgenlab/fix/queue-array-slurm-status",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-21T01:06:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "45171b697c0a4b7f3054e9fe52626d748b725a75",
          "body": "A proxied array whose tasks SLURM is actively running still read as PROXYQUEUED\nin the collapsed queue row, because the aggregate/breakdown counted the batchq\nstatus. Use an effectiveStatus that, for a PROXYQUEUED task, surfaces its\nrecorded slurm_status (PENDING/RUNNING/…) — so e.g. 2/33 tasks RUNN\n[…]\nus in their\ntrailing column; this only affects the collapsed array row.\n\nTest: TestArrayProgressUsesSlurmStatus. Full suite green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(queue): collapsed array row shows SLURM state, not just PROXYQUEUED",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-20T19:12:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "92d3b3ad1bdf87f38287f59f2650dd69f142a62d",
          "body": "feat(queue): collapse arrays to one row + PENDING status for array tasks",
          "is_bot": false,
          "headline": "Merge pull request #62 from compgenlab/feat/queue-collapse-arrays",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-20T17:43:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "263ae70f54693236fe3db910abd9f50e795f2368",
          "body": "…r array tasks\n\nTwo array-display improvements for `batchq queue`:\n\n- Collapse each array into a single summary row by default (array id, aggregate\n  status via aggregateArrayStatus, the template's procs/mem/walltime, and an\n  \"array <done>/<total> · <status counts>\" breakdown), so a large array no\n\n[…]\n.\n\nTests: arrayProgress, plus the earlier normalizeStates/slurmDisplayID. Full\nsuite green; verified collapse/expand/array-id e2e.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(queue): collapse arrays to one row; seed slurm_status=PENDING fo…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-20T17:28:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ee57d55443706853324656813e79995ffaee1358",
          "body": "…ray-slurm-id\n\nfeat(queue): --state/-s filter, and show SLURM array ids",
          "is_bot": false,
          "headline": "Merge pull request #61 from compgenlab/feat/queue-state-filter-and-ar…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-20T17:06:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ecb1d284630fad1c957d0ca1c0aef3970062f844",
          "body": "- `batchq queue --state/-s <states>` filters to specific job states\n  (case-insensitive, comma-separated, e.g. `-s RUNNING,QUEUED`). When set it\n  routes through the /jobs listing (which filters by status) instead of the\n  fast queue path; unknown states get a clear error listing the valid ones.\n- T\n[…]\ntes (case/whitespace/blank/invalid), slurmDisplayID (plain,\narray task, array-id-only, job_id-precedence, none). Full suite green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(queue): --state/-s filter, and show SLURM array ids",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-20T17:00:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8c4affece94c48388f9bdd192117296282d06804",
          "body": "fix(slurm-runner): resilient handoff write + #SBATCH --comment back-reference for rescue",
          "is_bot": false,
          "headline": "Merge pull request #60 from compgenlab/fix/slurm-proxy-write-resilience",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-20T16:40:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1be1a0bd91020468d97df9248789f1100d7cbd54",
          "body": "…scue\n\nsbatch is irreversible, so pair the resilient handoff-write with a durable\nback-reference FROM SLURM to batchq: every generated script now carries\n`#SBATCH --comment=\"{\\\"batchq_id\\\":\\\"<uuid>\\\"}\"` (arrays use \"batchq_array_id\":\nthe array uuid). The comment lives on the SLURM job RECORD — reada\n[…]\nective marshals the JSON and escapes it so sbatch keeps it as one\ndirective token. Test: round-trips the directive back to the id.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(slurm-runner): stamp the batchq id into #SBATCH --comment for re…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-20T16:33:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "deb7ff8ed8270706c9018e0b6e5337e131c3c13b",
          "body": "…lls on Lustre\n\nArray (and single) jobs were landing stuck at RUNNING with a host but no\nslurm_array_id/slurm_job_id: the runner claims the batch (RUNNING + host), runs\nsbatch (SLURM now has it), then records the id via MarkJobProxied — and on\nLustre that DB write can SQLITE_BUSY/stall. MarkJobProxi\n[…]\nidempotent + wrong-state still\nconflicts), client (MarkJobProxied retries a transient even for a remote runner).\nFull suite green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(slurm-runner): don't lose the SLURM id when the handoff write sta…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-20T16:28:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "681049ac4097bcfde1a146bdf804c99d35f368cd",
          "body": "feat(submit): idempotent submit so it survives Lustre/NFS transients",
          "is_bot": false,
          "headline": "Merge pull request #59 from compgenlab/feat/idempotent-submit",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-19T19:46:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57000fb93d4fe0f85d85e0f90c03936a66f8b76a",
          "body": "On the Lustre-backed cluster a single `batchq submit` occasionally times out\n(\"Client.Timeout exceeded while awaiting headers\") when a filesystem latency\nspike stalls that job's InsertJob past the 30s cap — cgp then reports a hard\njob failure. We can't speed up the FS, but we can make submit retry s\n[…]\ns\non a transient / does NOT retry keyless), support (IsUUID). Full suite green;\nsubmit_compat unchanged (printed id == client id).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(submit): idempotent submit so it survives Lustre/NFS transients",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-19T06:50:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6957a628544449a354db61faf367df1968032eee",
          "body": "fix(cleanup): reword 'kept back' message — dependency-tree preservation, not active deps",
          "is_bot": false,
          "headline": "Merge pull request #58 from compgenlab/fix/cleanup-blocked-message",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-18T21:27:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "798251721ed02878569309c6b37cc7a42469e370",
          "body": "…, not active deps\n\nThe old text said \"N not eligible (a dependent is still active)\", which is\nmisleading: the blocking is structural (foreign-key / dependency-tree), not a\nlive dependency — the dependent job is usually already finished (e.g. a newer\njob that completed within the --older-than window\n[…]\ndency trees intact\n    (a job that depends on them is being kept)\n\nMessage-only change; the (safe) blocking behavior is unchanged.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cleanup): reword the \"kept back\" message — it's tree preservation…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-18T20:44:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c7c4ef48e99b665357ae697a5f389038fb9a6108",
          "body": "fix(cleanup): output text polish + stop WriteTimeout killing the progress stream",
          "is_bot": false,
          "headline": "Merge pull request #57 from compgenlab/fix/cleanup-output-text",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-18T19:54:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cbf0b3030c51e2e0b78f1e7be3dbb7ba4486649e",
          "body": "A cleanup that streams for longer than the server's WriteTimeout (default 2m)\nhad its connection closed mid-stream — the client saw\n\"read cleanup stream: unexpected EOF\" while the server kept working (decoupled),\nso the DB still shrank but the run looked like it failed. This is the\nintermittent EOF \n[…]\n/cleanup_stream_test.go reproduces the exact EOF with a\n1ms WriteTimeout when the deadline isn't cleared, and passes with the fix.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cleanup): don't let WriteTimeout kill the progress stream",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-18T18:42:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "81ccc4fbdfffc20fa8d2061955975d03a81b6271",
          "body": "Per feedback on the live output:\n- Pluralize job/jobs internally (\"1 job\", \"2368 jobs\") instead of \"job(s)\".\n- Drop the separate \"Found N …\" line: the action line (\"Archiving N jobs…\" /\n  \"Deleting N jobs…\") is the whole story unless some matched jobs can't be\n  removed. The Found line now appears O\n[…]\nctive), which is the only case where matched != removed.\n- The action verb is already Archiving vs Deleting per the chosen action.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cleanup): tidy progress text — plurals, drop redundant Found line",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-18T16:34:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f73d62602cdd392a0a4ae22583db7e7a8efabef3",
          "body": "fix(cleanup): make it usable on a large NFS DB — bulk archive, streaming, index, guard",
          "is_bot": false,
          "headline": "Merge pull request #56 from compgenlab/feat/cleanup-stream-flush-index",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-18T16:16:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b3c96dad1e81e5f023081dca5726a04fe33e09d9",
          "body": "The h2 field data showed a single --archive cleanup running ~8 HOURS server-side:\nthe archive path was per-job (GetJob + RestoreJob + CleanupJob = ~18 fsync'd\nstatements per job over NFS). Because cancellation is decoupled, that op kept\nrunning long after the client gave up and blocked every retry (\n[…]\npendencyChain. Full suite green; verified end-to-end\nvia the CLI (bulk archive of a dependency chain + independents, then vacuum).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cleanup): bulk archive + concurrency guard",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-18T09:31:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5a137b660005e6a0958405994a3a0b38ec6571fd",
          "body": "…onger watch\n\nRunning the real cleanup on the 608 MB NFS DB on h2 surfaced three issues once\nread_pool_size was set to 1 (which fixed the SQLITE_BUSY):\n\n1. The client got `POST /admin/cleanup: context deadline exceeded` with no\n   progress ever shown. Cause: the handler didn't emit/flush until AFTER\n[…]\ne TestSchemaHasCleanupIndex; full suite green; verified live via the\nCLI (Scanning… → Found N → Archiving x/N → Vacuuming → done).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cleanup): stream headers immediately, index the candidate scan, l…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-18T08:40:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c29954ec1168df4a65204ab35f98626138c43ffa",
          "body": "feat(cleanup): stream live progress from the server",
          "is_bot": false,
          "headline": "Merge pull request #55 from compgenlab/feat/cleanup-progress-stream",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-17T23:02:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4b09f0c7c193dc88e30662fb3973ac649b6d448d",
          "body": "A bulk cleanup on a large DB could run for minutes returning nothing until\ndone. Stream progress instead: POST /admin/cleanup now emits newline-delimited\nJSON (api.CleanupEvent) as it works — candidate selection, per-batch\ndelete/archive progress, and the vacuum step — ending with a \"done\" (or\n\"erro\n[…]\nstCleanupBulkEmitsProgress; existing CleanupBulk tests updated\nfor the new signature. Full suite green; verified live via the CLI.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cleanup): stream live progress from the server",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-17T22:56:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "603882e6d05a51b4344c94b30e729529b94881e1",
          "body": "feat(cleanup): server-side bulk cleanup + no-timeout client fix + --archive UX",
          "is_bot": false,
          "headline": "Merge pull request #54 from compgenlab/feat/cleanup-scale-and-timeout",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-17T22:51:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b849518f016585b210c7d713cc1e3b4c246c0a6b",
          "body": "… --archive UX\n\nFollow-ups after the archive/vacuum work exposed real gaps on the 608 MB\nNFS-backed DB on h2.\n\n1. Timeout contract (the reason cleanup still died at 30s on the new binary):\n   DialWithOptions overrode Timeout:0 -> 30s, so mustDialClientLongRunning was\n   still 30s-capped. Add Options\n[…]\nst.go. Ported the old cmd planner tests\nto the service. Full suite green; verified end-to-end via the real CLI. CLAUDE.md\nupdated.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cleanup): server-side bulk cleanup; fix no-timeout client; clean…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-17T22:38:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "be150d91a71414e107727cbbe9422f2644ad6f0b",
          "body": "feat(cleanup): archive to read-only DBs, auto-vacuum, archive fallback lookup",
          "is_bot": false,
          "headline": "Merge pull request #53 from compgenlab/feat/cleanup-archive-vacuum",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-17T22:08:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "757576f0c0a2f6764920277f00bddd3d07d9d4ed",
          "body": "…k lookup\n\nRework `cleanup` to require an explicit action and add an offline archive:\n\n- `cleanup --delete | --archive[=NAME]` — no default action; --archive moves the\n  selected terminal jobs into a NEW, read-only (0440) archive SQLite DB under\n  `[server] archive_dir` (default $BATCHQ_HOME/archive\n[…]\nerns) via\nmustDialClientLongRunning + cmdContextLong.\n\nTests: storage/archive_test.go, service/archive_test.go. CLAUDE.md updated.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cleanup): archive to read-only DBs, auto-vacuum, archive fallbac…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-17T17:52:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b931a22257602a8b06fee4f4c928341f333cf5ef",
          "body": "feat(slurm): emit --gres/--constraint/--nodelist from job resources",
          "is_bot": false,
          "headline": "Merge pull request #52 from compgenlab/feat/slurm-resource-directives",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-14T12:36:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1fbdf2d5bfb71e1c79e5dec83b4f9fc3ed42a9ee",
          "body": "The SLURM runner claimed jobs by matching resource.* requirements but never\nforwarded them to sbatch, so a job requesting a GPU (resource.gpu=2, whether\nfrom --resource, #BATCHQ -resource, or #SBATCH --gres) was submitted with no\n--gres and SLURM allocated no GPU.\n\nslurmResourceDirectives now transl\n[…]\n value as a --constraint feature; nodelist_resources emits as\n--nodelist (e.g. host -> a specific node). Surfaced in batchq debug.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(slurm): emit --gres/--constraint/--nodelist from job resources",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-14T12:30:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4d7d35300bbd924bad6e67b59357e49f955eb175",
          "body": "feat(submit): generic per-job scheduler passthrough (--custom key=value)",
          "is_bot": false,
          "headline": "Merge pull request #51 from compgenlab/feat/custom-scheduler-passthrough",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-14T12:16:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5d877c853fb79ef2b91f5f6eb8cc231dbd00cf83",
          "body": "The spec described batchq status/details --json, which shipped in f28cc63\n(merged to main). The handoff doc has served its purpose.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: remove completed status --json handoff spec",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-14T12:11:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "308b571ba94f62ffcedb42586bbdf439618cc2a5",
          "body": "Account and partition could previously only be set on the SLURM runner\n(--slurm-account/--slurm-partition), applying uniformly to every job. A\n#SBATCH -A/-p in a submitted script was silently dropped.\n\nAdd a generic, scheduler-agnostic passthrough stored under a new custom.\ndetail prefix (mirroring \n[…]\n are rejected. batchq's core does not interpret\ncustom.* values; a future PBS/SGE proxy can map the same details to its own\nflags.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(submit): generic per-job scheduler passthrough (--custom key=value)",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-14T12:09:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a48c459f69d8866c0c95aa2de7adece1c68a3506",
          "body": "feat(status): add --json to status and details",
          "is_bot": false,
          "headline": "Merge pull request #50 from compgenlab/feat/status-json",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-12T13:07:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f28cc63db3daefc50d7fa6ba85f60412f4ced9da",
          "body": "Emit a JSON array of api.JobDTO from `batchq status --json` and\n`batchq details --json`, one element per resolved job (array ids\ncontribute all member tasks, index-sorted). Unknown ids are omitted\nand exit 0, matching --porcelain. The DTO is emitted as-is, so cgp's\n`cgp status --json` can populate p\n[…]\netails) for batchq-backed jobs instead of\nscraping --porcelain/-e.\n\nSee docs/cgp-status-json-handoff.md for the consumer contract.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(status): add --json to status and details",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-12T12:30:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "de137f4471d0245b6d68d08fdddb626bcfdc88a7",
          "body": "feat(priority): apply top/nice across a whole array",
          "is_bot": false,
          "headline": "Merge pull request #49 from compgenlab/feat/web-api-gateway",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T16:23:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "354d6cd062e608328f3153201dbc40fc2f08d516",
          "body": "Extend the priority commands to accept an array id: top/nice now dispatch\nwhole arrays to a new atomic POST /arrays/{array_id}/priority endpoint\n(one UPDATE over every eligible QUEUED/WAITING/USERHOLD task), while single\njobs/tasks continue through the per-job endpoint. Mirrors the existing\narray cancel/hold/release vertical slice across api/client/server/service/storage.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(priority): apply top/nice across a whole array",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T16:19:21Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0079fca7c12bc2439f304ed98305d0249e897890",
          "body": "feat(slurm): store submitted sbatch script on array tasks",
          "is_bot": false,
          "headline": "Merge pull request #48 from compgenlab/feat/web-api-gateway",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T16:11:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b44cb032a3cea44f3f5b2372e5851613c0dbdaf2",
          "body": "Array tasks now record slurm_script in their running details, so\n`batchq details <array-task-id>` shows the exact `--array=<indices>%N`\nscript the task was submitted with (matching single-job behavior),\ninstead of falling back to the raw job body. A drip-fed array is\nsubmitted as several batches (e.\n[…]\npt belongs with the task, not the\nlogical array. Duplication is bounded by the batch size (live-queue\nbudget), not the array size.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(slurm): store submitted sbatch script on array tasks",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T16:02:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c296104d812cd0b7ca9c43ccc2598f182a3aec63",
          "body": "feat(web): combined UI + REST API gateway (batchq web --api)",
          "is_bot": false,
          "headline": "Merge pull request #47 from compgenlab/feat/web-api-gateway",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T14:15:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "14c9d0e8a38ef58a5892af6895d560547a51e8d4",
          "body": "JobDef.Print() iterated Details/RunningDetails in insertion order, so\n`batchq details` showed the keys in a different order each time. Print a\nkey-sorted copy of each (the model itself is left untouched; \"script\" and\n\"slurm_script\" are still extracted and printed last).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(details): sort job detail keys alphabetically",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T14:01:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "302cab6c8c79c0d6a07919cd78e332cd78c619f8",
          "body": "On a TCP listener, instead of serving an unauthenticated surface, `batchq web`\nnow generates any missing credential, prints it to stderr, and persists it to\nthe config file so restarts reuse it:\n\n- missing UI password -> random 16-char password (user \"admin\")\n- --api with no token  -> random \"sk-\"+2\n[…]\nsecure-by-default behavior.\n\nTests: RandomString/RandomToken, SaveConfig round-trip + minimality + 0600 +\npreserves existing keys.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(web): generate & persist missing gateway credentials",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T13:30:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bef20cd201730fe0f2f45d1418340a661a660104",
          "body": "`batchq web --api` now serves both surfaces on one listener: the browser UI at\n/ (HTTP Basic, admin + [web] password/BATCHQ_PASSWORD) and the REST API\nreverse-proxied under /api/ (bearer [batchq] token/BATCHQ_TOKEN). The web\nprocess stays a REST client and forwards /api/* to the backend it's connect\n[…]\n gateway auth (both surfaces), reverse-proxy token injection, transport\nprecedence, array-details line. Docs updated in CLAUDE.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(web): combined UI + REST API gateway (batchq web --api)",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T13:15:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f6c692bb10af945f1e4cf511a8725b3dd689de49",
          "body": "fix(list): defer hydration on detail-filtered listings",
          "is_bot": false,
          "headline": "Merge pull request #46 from compgenlab/fix/detail-filter-defer-hydration",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T00:57:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9ee2e9854371c90db2b24fbd72b9b34c2fffec9a",
          "body": "`batchq details <array_id>` (and any --array-id/--run-id/--output/--input\nfilter) went through Service.ListJobs, which listed every job row in the DB,\nhydrated all of them (loadJobRelations = 5 SELECTs per job, serialized on the\nsingle SQLite connection), then filtered down to the matching set in me\n[…]\nordering are preserved; only the wasted\nhydration is removed. The slurm runner's PROXYQUEUED path still passes\nloadRelations=true.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(list): defer hydration on detail-filtered listings",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-08T00:33:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cdf37571ee3771477a8064166df1847c7ad81f4f",
          "body": "fix(queue): bound --since/--before in SQL, not in memory",
          "is_bot": false,
          "headline": "Merge pull request #45 from compgenlab/fix/queue-since-sql-bound",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-02T03:04:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ee4dc2de4b6f67ca3a914a74110d76e331a09ed6",
          "body": "`batchq queue --since ... --all` timed out (context deadline exceeded)\nbecause adding a time filter rerouted the queue view from the fast\n/queue endpoint (one JOIN query) to the general /jobs endpoint, which\nloads full relations (5 queries per job) and then filtered since/before\nin Go — O(5N) round-\n[…]\ns, still use /jobs.\n\nAdd TestGetQueueJobsFiltersBySubmitTime; existing\nTestListJobsFiltersBySubmitTime now exercises the SQL path.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(queue): bound --since/--before in SQL, not in memory",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-02T03:01:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "90a9a208fa381b3913a9937d9c900cec746710d3",
          "body": "chore(ci): bump artifact/release actions off deprecated Node 20",
          "is_bot": false,
          "headline": "Merge pull request #44 from compgenlab/chore/bump-ci-actions",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-01T14:17:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6fdebd6c0b9725c21b8dd90b3c4dccf8b1dd0531",
          "body": "actions/upload-artifact@v4, actions/download-artifact@v4, and\nsoftprops/action-gh-release@v2 were being force-run on Node 24 with a\ndeprecation warning. Bump to the current Node 24-native majors (v7 / v8\n/ v3). Usage is limited to stable inputs (name+path uploads/downloads,\nfiles + GITHUB_TOKEN for the release), so no config changes are needed.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_013JLuEtYbQqJ5iUzJGQPRT4",
          "is_bot": false,
          "headline": "chore(ci): bump artifact/release actions off deprecated Node 20",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-01T14:12:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "09b3f9a35a92e2aca999c95b4fb0632ed8da650e",
          "body": "feat(queue): add --since/--before submit-time filters",
          "is_bot": false,
          "headline": "Merge pull request #43 from compgenlab/feat/queue-since-before",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-01T13:14:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cbfd9f25e4f6013f457a68ad47d783100300d40d",
          "body": "`batchq queue` can now be restricted to a submit-time window, e.g.\n`batchq queue --all --since 2026-06-30 --before 2026-07-01` (yesterday)\nor `batchq queue --all --since 1d` (last 24h).\n\nBoth flags accept absolute dates (2006-01-02, local midnight), local\ndatetimes, RFC3339, and relative age-ago dur\n[…]\n-array-id\nintersect pattern (no storage-interface change).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_013JLuEtYbQqJ5iUzJGQPRT4",
          "is_bot": false,
          "headline": "feat(queue): add --since/--before submit-time filters",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-07-01T13:11:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f6214b8285d2dc0b0a6b7622a3caa4066506d4e4",
          "body": "docs: update cgpipe repo URL to compgenlab org",
          "is_bot": false,
          "headline": "Merge pull request #42 from compgenlab/docs/cgpipe-repo-url",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-18T06:13:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3f741566f5e77dba1a352139c1f10d266bbb3ca9",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: update cgpipe repo URL to compgenlab org",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-18T06:11:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8ad37aea201e001356a63f46140265c40c002779",
          "body": "chore: rename Go module to github.com/compgenlab/batchq",
          "is_bot": false,
          "headline": "Merge pull request #41 from compgenlab/chore/rename-module-compgenlab",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-18T04:21:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7730ed88bc4725b824978509562c6e1cbeea410b",
          "body": "Repo moved from the mbreese user to the compgenlab org on GitHub.\nMechanical rewrite of github.com/mbreese/batchq -> github.com/compgenlab/batchq\nacross all import paths, go.mod, Makefile ldflags, and docs. The unrelated\ngithub.com/mbreese/cgpipe link in docs/overview.md is left intact.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: rename Go module to github.com/compgenlab/batchq",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-18T04:08:49Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "007097068880b0e94ba4d1db57490aa4bb320a0c",
          "body": "fix(slurm): submit gather jobs that depend on arrays",
          "is_bot": false,
          "headline": "Merge pull request #40 from mbreese/fix/slurm-array-gather-deps",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-16T16:34:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "66b5fec233fa66e2938188f58505dd79378e4a4b",
          "body": "A gather submitted with `--deps afterok:<array_id>` was canceled the moment\nthe SLURM runner tried to submit it, with \"missing slurm_job_id\". The afterok\ndeps fan out to array tasks, which record slurm_array_id + slurm_task_index\n(never slurm_job_id), but slurmAfterOkDirective only read slurm_job_id\n[…]\nt.\n\nAdds regression tests for whole-array collapse, multi-sub-array collapse,\npartial per-element fallback, and proxied-promotion.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(slurm): submit gather jobs that depend on arrays",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-16T11:34:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7c8f000dff99354ab4f39cc3a6a5ac4b5193d961",
          "body": "feat(deps): resolve <arrayid>_<index> task addresses in dependency specs",
          "is_bot": false,
          "headline": "Merge pull request #39 from mbreese/fix/task-address-deps",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-15T20:13:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4511a762887b48feb0db161ff2faa1e1861556fc",
          "body": "The service layer resolved whole-array ids and plain job UUIDs in afterok/\naftercorr specs, but not SLURM-style `<arrayid>_<index>` task addresses — only\nthe CLI resolved those, client-side. So a dependency on a single array task\n(e.g. a gather wired per-task) failed submission with\n`storage: dep <a\n[…]\nine per id (queried token echoed in field 0; arrays\ncollapse to one aggregate status) for external tools that parse status output.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(deps): resolve <arrayid>_<index> task addresses in dependency specs",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-15T19:26:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ede96293f6b9575f36ec898260508667f9912d6f",
          "body": "Normalize job names so SLURM submission can't break",
          "is_bot": false,
          "headline": "Merge pull request #38 from mbreese/fix-slurm-jobname-spaces",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-11T17:19:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4f3676f407d3d9cc5f906d5fa156dc2f270cbf9a",
          "body": "A job named \"Count reads per sample (extended walltime)\" was rejected by\nsbatch with \"Invalid directive found in batch script: reads\": the SLURM\nrunner interpolated the name into `#SBATCH -J` unquoted, so the second\nword was parsed as a stray directive.\n\nAdd jobs.NormalizeName: every character outsi\n[…]\n) so batchq never stores a name\nwith whitespace; the SLURM runner reuses it as an idempotent guard when\nbuilding the -J directive.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Normalize job names so SLURM submission can't break",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-11T17:14:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d4da4571c70c8618f5fcf4e8f2a210c3bff471de",
          "body": "status: add -s/-b/-e/-t timestamp flags",
          "is_bot": false,
          "headline": "Merge pull request #37 from mbreese/status-time-flags",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-10T21:49:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fcfbbd397d7c7b0b25e7d6c5c625b61de467fb57",
          "body": "Add opt-in boolean flags to `batchq status` to append lifecycle\ntimestamps to the status line, combinable in any order (e.g. -sbet):\n\n  -s/--submit    SubmitTime\n  -b/--begin     StartTime\n  -e/--end       EndTime\n  -t/--walltime  WallTime (end-start; now-start while RUNNING)\n\nTimes are RFC3339 UTC \n[…]\nseable). Default output (no flags) is unchanged\nso downstream parsers are unaffected. Reuses timeOrZero and\njobs.WalltimeToString.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "status: add -s/-b/-e/-t timestamp flags",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-10T21:45:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "71819469accbf51ab86304704e1e08e303c5a49d",
          "body": "Add `batchq backup` command (VACUUM INTO snapshot)",
          "is_bot": false,
          "headline": "Merge pull request #36 from mbreese/backup-command",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-10T07:56:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f6cebf822d5337ca6229633801a40bd7b71ca3dd",
          "body": "Snapshot the SQLite DB via the running server's own connection, so no\nsecond process ever opens the live file — the safe way to back up a DB on\nNFS/Lustre, where running `sqlite3 .backup`/`.dump` externally would open a\nsecond connection (the cross-process case the single-server model avoids).\n\nThre\n[…]\ntegrity_check; refuses an\nexisting destination) and service (default-path resolution; explicit and\nexisting-destination handling).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add `batchq backup` command (VACUUM INTO snapshot)",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-10T07:52:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "93cfb6a913b33895591915af55ada3ea0c323033",
          "body": "slurm runner: --slurm-min-array and --slurm-full-array batch gates",
          "is_bot": false,
          "headline": "Merge pull request #35 from mbreese/slurm-array-batch-gates",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-10T05:02:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "23302fc978d622e7093c073cc28adf0ed7af0f07",
          "body": "…unners)\n\nDocument the three runtime roles and how to invoke each: the server (and\nautospawn / batchq stop), the client subcommands (submit/queue/status/\nhold/cancel/web), and the two runners — the long-lived simple runner and\nthe one-shot cron'd SLURM proxy runner, including the new array-batch\ngate flags. Also lists the global client flags (--remote/--token/\n--no-autospawn/--restart-server/--log).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add a \"Running batchq\" section to CLAUDE.md (server, clients, r…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-10T04:56:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "071d4f6af7cbf87fb47d48821a98d830d1090c93",
          "body": "The SLURM proxy runner drip-feeds a large array across passes, bounded by\nmax_slurm_jobs/max_jobs. Once an array is mostly through, each freed slot\ntriggers a tiny `sbatch --array`, which is wasteful and noisy.\n\nAdd two array-batch gates to ClaimNextArrayBatch (decided before claiming,\nsince claims \n[…]\nases (claim/defer/tail/fall-through, full-array), runner\nclampMinArray. Docs: CLAUDE.md, docs/configuration.md, batchq debug rows.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "slurm runner: --slurm-min-array and --slurm-full-array batch gates",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-10T04:45:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7f8e715f6157ec6d9e7901e4856604370c2623aa",
          "body": "Close the idle-handoff SQLITE_BUSY window: release the socket after the DB",
          "is_bot": false,
          "headline": "Merge pull request #34 from mbreese/fix-idle-cull-handoff-race",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-09T04:00:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cb7b5523b16c2aa32c093332618cb809261c8e96",
          "body": "…l_size)\n\nAll DB access went through one connection (SetMaxOpenConns(1)), serializing\nreads behind reads and behind writes — under cgpipe's status-poll bursts a\nsingle slow NFS read/write blocked everything. SQLite's rollback-journal\nlocking allows concurrent readers (each takes a SHARED lock; reade\n[…]\nConsistent (distinct pool of N; reads see committed\nwrites; 20 concurrent reads succeed during a write). Full suite + -race green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "storage: optional concurrent reads via a read pool ([server] read_poo…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T23:56:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4890cea88f12cabd70d74e7e320920d797e005b0",
          "body": "…ingle-server SQLITE_BUSY)\n\nField diagnosis (via --log): SQLITE_BUSY fires with a SINGLE server running.\nThe failing POST waited exactly busy_timeout (5.0s) then failed, and the server\nserved nothing else meanwhile — so another *connection* held a write lock, even\nthough only one server exists.\n\nRoo\n[…]\npagated context.Canceled).\n\nIf churn ever recurs, the heavier follow-up is pinning a dedicated *sql.Conn for\nthe process lifetime.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "storage: decouple ALL DB access from request cancellation (the real s…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T23:15:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1bde55fc4fd4b44eb4d39f621b84bea757c04208",
          "body": "…e spawned server)\n\nThe lifecycle log path from [batchq] log / --log now resolves a leading ~ to\nthe user's home dir. OpenDebugLog already ran it through ExpandPathAbs; this\nalso expands it to an absolute path in the client BEFORE passing --log to the\nautospawned server, so the child opens the exact\n[…]\n [server] db and [job_defaults] wd/stdout/stderr.)\n\nTest: TestOpenDebugLogExpandsTilde asserts ~/logs/debug.log lands under $HOME.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "debug log: expand ~ in the config log path (and when handing it to th…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T22:47:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3429d9ebe9d276441e8896af2e462b3eda207372",
          "body": "…rrors) with PIDs+timestamps\n\nStop guessing at \"too many servers\"/SQLITE_BUSY — instrument it. A new\nopt-in lifecycle log records, with a timestamp and PID on every line, what\nthe client and the servers it autospawns are doing, to one shared file so\noverlapping server PIDs are obvious.\n\nEnable with \n[…]\nwith a short idle timeout) the\nordered \"db closed\" appearing before \"serve exit\" — confirming the socket is\nreleased after the DB.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "debug: add --log lifecycle log (client/server spawns, shutdowns, DB e…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T22:26:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9aea104d5edadc4857259f3d3c9f1f1fdba659b2",
          "body": "…ased after DB)\n\nA 500 SQLITE_BUSY from a *running* server means two server processes had\nthe DB open and in a transaction at once. On a single host with autospawn\nthe remaining way that happened was the idle-cull -> respawn handoff, and\nthe bug was an ordering inversion: the unix socket — which *is\n[…]\nhe gate.\n- client: a draining handoff is transparently retried to success; disabled\n  autospawn surfaces the 503 without retrying.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "server/client: close the idle-handoff SQLITE_BUSY window (socket rele…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T20:01:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ae2841bbf45775c0c7c2d1d0e96f42ab7572f0fd",
          "body": "server: win single-instance election before opening the DB",
          "is_bot": false,
          "headline": "Merge pull request #33 from mbreese/fix-sqlite-busy-startup-race",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T06:18:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ce742637525f888257678b947e3438f2f8dde26",
          "body": "…_BUSY fix)\n\nRemove the DB flock added earlier — it was a backstop that masked the\nproblem. On a single host the unix socket is already a correct\nsingle-instance lock and one server (MaxOpenConns(1)) serializes all\naccess, so it can never report SQLITE_BUSY. The error means a SECOND\nserver got start\n[…]\nurrent cold-start\nsubmits, idle-restart loop, and kill -9 stale-socket recovery all yield\nexactly one server and zero SQLITE_BUSY.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "server/client: prevent duplicate servers on one host (the real SQLITE…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T06:04:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4442d832022f2596fef9b5bae29de5d2ca96241d",
          "body": "Even with election-before-open, SQLITE_BUSY can still occur when two\nprocesses open the same DB file via DIFFERENT election tokens — the\nclassic HPC case where unix sockets are host-local but $BATCHQ_HOME/the\nDB sit on a shared (NFS/Lustre) filesystem, so a client on another node\ncan't reach the one\n[…]\nn SQLITE_BUSY — /healthz is\nauth-exempt so the probe finds a server regardless of token, and a token\nmismatch is a 401, not a 500.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "storage: take an exclusive DB lock so a second opener fails clearly",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T05:37:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f74afb81d795a0fd63752dbd1dd793698d22a7f9",
          "body": "Fixes \"database is locked (5) (SQLITE_BUSY)\" on submit. The server opened\nthe SQLite DB (storage.Open -> Ping + schema apply, taking locks) BEFORE\nthe socket-bind election. When many `batchq submit` clients autospawn a\nserver from a cold start, N servers all opened the same DB concurrently:\neach tak\n[…]\neout(5000ms),\nwhich covers it (single idle old server, simple lock wait, DB closed\nwithin ms by the existing defer store.Close()).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "server: win single-instance election before opening the DB",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T04:52:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "507ab01411a34e1a6b997562db02a831db96f9d2",
          "body": "Fix sticky SQLite tx-poisoning on submit; add server status to `batchq debug`",
          "is_bot": false,
          "headline": "Merge pull request #32 from mbreese/fix-sqlite-tx-poisoning",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T04:27:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80433997fe89348ec9b453fd0d183ff36c66eac7",
          "body": "`batchq debug` now ends with a server-status section that probes the\nconfigured endpoint (no autospawn) and reports whether a server is\nrunning, its PID, and instance id -- i.e. can it be reached / PINGed.\nFor an unresponsive local unix socket it distinguishes a down server\nfrom a stale leftover soc\n[…]\nincludes its os.Getpid() in the /healthz response\n(api.HealthResponse.PID); add client.HealthStatus to return the parsed\nresponse.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "debug: report server status (running / PID / pingable)",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T04:23:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "20d4eea5792ae4a03d4feb4b6a0a096dee1d5184",
          "body": "A canceled request context racing a BEGIN leaves modernc/sqlite's\nconnection inside a transaction when database/sql returns it to the pool.\nWith SetMaxOpenConns(1) that single poisoned connection then fails every\nlater BeginTx with \"cannot start a transaction within a transaction\"\nuntil the server r\n[…]\n through it.\n\nAdd regression tests: recovery from a poisoned connection, and a write\ncompleting under an already-canceled context.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "storage: fix sticky \"cannot start a transaction within a transaction\"",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-08T04:18:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4a45711a6fff8aacb63d7e75618baa0c6e596b9b",
          "body": "Captures the \"root identity proxy → SLURM-free multi-user HPC\" idea:\na root-owned batchq proxy on login/submit nodes captures kernel-attested\nuid/gid and forwards a trusted identity assertion to a remote\nbatchq-server, so a remote deployment can verify who submitted a job\nwithout a local root socket\n[…]\n\napplyPeerIdentity override, and uid-based ownership authz.\n\nInternal note, intentionally not wired into the published docs index.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add internal PLAN.md for future-direction notes",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-05T21:40:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "381822e345ec45013e8b820a0399bc7b45f35436",
          "body": "…, backfill PR #30 unit coverage (#31)\n\nFollow-up to the PR #30 robustness review.\n\n- runner/simple.go: a job whose stdout/stderr file (or its dir) can't be\n  created now fails loudly via failClaimedJob instead of running with\n  discarded output and reporting SUCCESS. cleanup() releases anything\n  a\n[…]\nomDef round-trip + ParseStatus, FindArrayMembers.\n\ngo build/vet/test ./... pass; go test -race ./runner ./storage ./service clean.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "runner/tests: fix silent output-file failures, remove inert WaitDelay…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-05T17:06:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "000b2695bbcd6a165328624849178813c7d19a4d",
          "body": "… leaks (#30)\n\n* chore: add test-race target, restore smoke runner, drop stray files\n\n- Makefile: add a CGO-enabled test-race target (race detector needs CGO,\n  which the pure-Go default build disables).\n- test.sh: restore the documented end-to-end smoke runner (it had been\n  overwritten by a user j\n[…]\njects reserved/whitespace names like submit does.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Runner robustness: fix data race, daemon-killing panics, and resource…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-05T16:38:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "84ebf75b43bd06f11732975f6f8b156c7933145b",
          "body": "Runner host cluster",
          "is_bot": false,
          "headline": "Merge pull request #29 from mbreese/runner-host-cluster",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-05T03:49:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "97fc6ec438b61931ba3c3591ef688d897247d568",
          "body": "Routing a job to the right cluster/host needs BOTH sides set: the runner\nadvertises, the job requires. The runner side existed; this adds the submit\nside so a user configures their cluster once instead of typing --resource\nevery time.\n\n- `batchq submit` gains --cluster / --host shorthands and [job_d\n[…]\nnner knobs.\n\nTests: submit --cluster/--host + config default + precedence; withResource;\nrunner advertises host alongside cluster.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "submit: default required cluster/host resources (multi-cluster routing)",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-05T03:42:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "92a350e2424d453cd89d587889dccee301c6ba06",
          "body": "Previously every `batchq run` generated a fresh UUID runner id, so the\nserver's Runners view accumulated a new row per invocation. The id is now\nstable by default so a runner shows as one row that updates in place.\n\n- Runner id resolution: --runner-id flag > [*_runner] runner_id config >\n  hostname \n[…]\nsimple_runner.resources] / [slurm_runner.resources]; the\n--cluster convenience and these remain the way to advertise capabilities.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "runner: stable runner id (defaults to hostname) + simple max_jobs",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-05T03:35:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "45595ae4a817d525e3df0046d8ada81483ad74b2",
          "body": "A runner connecting to a (remote) server now advertises which machine it\nruns on and, optionally, the cluster it belongs to, so the server's Runners\nview can show the host and route cluster-tagged jobs.\n\n- api.ClaimJobRequest/ClaimArrayRequest gain a Host field; client.ClaimNextJob\n  /ClaimNextArray\n[…]\nter knobs.\n\nThe server treats Host as advisory metadata; an older server simply ignores\nthe field, so this is backward-compatible.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "runner: advertise hostname + cluster on claim",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-05T01:25:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cf2cc9781f052bde70565c8b6a97fd9c2a1dd596",
          "body": "docs: reconcile how-it-works/security/transport wording after the token + TCP merges",
          "is_bot": false,
          "headline": "Merge pull request #28 from mbreese/docs-post-merge-sync",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-05T00:41:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f8e92348ceb9587b0b7e7744a32dbb342107132a",
          "body": "Accuracy nits in the \"how the system works\" walkthrough:\n- the client diagram listed a `show` box (no such command) -> `queue`\n- the job-lifecycle step cited POST /jobs/{id}/status, but runners report\n  via the runner endpoints (/runners/{id}/jobs/{id}/end) -> corrected\n- the server/ layout line said \"unix-socket listener\" only -> listener\n  is unix socket or TCP, plus the shared-token auth middleware\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: tighten the architecture how-it-works explanation",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-05T00:38:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "aa28267ba135c4e7912bedc02e89b45a0c12bc57",
          "body": "…atures\n\nThe arrays/resources docs branch and the shared-token/TCP branch landed\nin parallel, so the security and transport prose written on the docs\nbranch predated those features and went stale on merge. Fix:\n\n- \"bearer-token auth not yet implemented\" / \"isn't implemented yet\"\n  (overview, running\n[…]\nA couple of leftover `show`-as-command references (README client list,\n  configuration multiuser row, CLAUDE.md) -> real commands.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: reconcile security/transport wording with merged token + TCP fe…",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T23:12:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c7f49a3bf6483fe142d64bc414f4fcaf39ed631e",
          "body": "docs: document job arrays, generic resources, and the full command set",
          "is_bot": false,
          "headline": "Merge pull request #26 from mbreese/docs-arrays-resources",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T23:06:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f3b9c466f1779c11b23f2809c260d06fa92df136",
          "body": "server: shared-token auth + optional TCP listener",
          "is_bot": false,
          "headline": "Merge pull request #27 from mbreese/server-shared-token",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T23:06:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4d05acada0dbe11df68efcd885d1449c27b7395e",
          "body": "The API server could only bind a unix socket, which is awkward in\ncontainers/orchestrators. Add an opt-in `tcp://host:port` listen form.\n\n- server: listen() handles tcp:// via listenTCP (plain HTTP; EADDRINUSE\n  -> ErrAlreadyRunning; no socket election/cleanup/ownership monitor,\n  which are unix-onl\n[…]\n; relaxed CLAUDE.md from \"never binds TCP\" to \"never\n  terminates TLS\".\n\nDefault is unchanged (unix socket); TCP is purely opt-in.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "server: support binding a plain-HTTP TCP port (tcp://host:port)",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T23:02:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dc84ec574aeb8a153d15c0af14a8a9eb29ce4d21",
          "body": "Adds a single-shared-secret bearer-token gate so a user can run their\nown network-exposed batchq server \"secure-enough\" without standing up\nthe managed multi-tenant server. Real per-user identity stays the\nmanaged server's job.\n\n- support/config: `[server] token` knob + `BATCHQ_SERVER_TOKEN` env\n  o\n[…]\nrver = per-user); update CLAUDE.md.\n\nBackward compatible: with no token configured the server enforces\nnothing, exactly as before.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "server: add shared-token auth for self-hosted remote servers",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T22:28:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f7a7130b96a096e98f8a776ecf6d1df9948a09b7",
          "body": "Found during a prose-accuracy audit of the remaining pages:\n\n- overview.md listed `show` as a client subcommand (no such command);\n  replaced with the real read commands. Also corrected the \"no per-user\n  authentication today\" claim: the server always derives unix-socket\n  client identity from kerne\n[…]\nb.md: documented the array UI the arrays change added — the queue\n  array column / `?array_id=` filter and the job-page Array tab.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: fix accuracy gaps in overview, running-jobs, and web pages",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T21:41:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1ca6e79f2d8afdd2ce4b5ea0694f546d70a2b9c5",
          "body": "Several user-facing commands had no real documentation: summary, top,\nnice, and license had none at all, and cleanup/hold/stop only appeared\nas one-line mentions. Add docs/managing-jobs.md documenting the full\ninspection and management surface:\n\n- queue (every filter/sort flag), summary, search, sta\n[…]\nersion/debug/license\n\nWire it into the docs index and cross-link from submitting-jobs.md,\njob-arrays.md, and the top-level README.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add a Managing jobs page covering the remaining commands",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T21:31:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6451ba144bac89f233eb13dcfd6ce221b79b0df7",
          "body": "- `--slurm-acct` is not a real flag; the runner flag is `--slurm-account`.\n- The `[slurm_runner]` quick example used `max_jobs = 200` with a\n  \"concurrent jobs visible to SLURM\" comment — that's `max_slurm_jobs`\n  (live SLURM-queue cap), matching the `--slurm-max-jobs 200` line above.\n  `max_jobs` is the per-invocation submit cap.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: fix wrong SLURM runner flag and config key in README",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T21:19:30Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d7b619af5e29cddde3ab641f779958266b12d137",
          "body": "There is no `batchq show` parent command — queue/details/status are\ntop-level — and the queue file-tag filters are `--output`/`--input`,\nnot `--produces`/`--consumes`. Correct every occurrence across the\ndocs and the top-level README:\n\n- `batchq show queue|details|status` -> `batchq queue|details|status`\n- generic `batchq show` stand-ins -> `batchq queue`\n- `batchq queue --produces/--consumes PATH` -> `--output/--input PATH`\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: fix stale command/flag references",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T20:11:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5cb10c9459b55baaa8e32eaa2afc0d0c4b327304",
          "body": "Document two features that shipped but were undocumented:\n\n- docs/job-arrays.md (new): --array spec forms, %A/%a per-task output\n  placeholders, the per-task env vars (BATCHQ_/SLURM_/PBS_/SGE_ task\n  index), batch management (hold/release/cancel on an array id and the\n  <array_id>_<index> task addre\n[…]\nURM translation/array\nreconciliation note (slurm.md), the docs index (docs/README.md), and\nquick examples in the top-level README.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add job-arrays and generic-resources guides",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T20:08:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "81b4a81bb357e4abddae8e95becfa129841cdb55",
          "body": "Add job arrays with batch management, SLURM proxy, and web view",
          "is_bot": false,
          "headline": "Merge pull request #25 from mbreese/job-arrays",
          "author_name": "Marcus Breese",
          "author_login": "mbreese",
          "committed_at": "2026-06-04T18:12:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 17,
      "commits_last_year": 211,
      "latest_release_at": "2026-07-21T01:32:12Z",
      "latest_release_tag": "v0.4.0",
      "releases_from_tags": false,
      "days_since_last_push": 1,
      "active_weeks_last_year": 14,
      "days_since_latest_release": 1,
      "mean_days_between_releases": 5
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": false,
      "has_contributing": false,
      "health_percentage": 25,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/compgenlab/batchq",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/compgenlab/batchq",
          "is_deprecated": false,
          "latest_version": "v0.4.0",
          "repository_url": "https://github.com/compgenlab/batchq",
          "versions_count": 17,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-21T01:28:30Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 1
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 1,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": true,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 79814,
      "source_files_sampled": 109,
      "oversized_source_files": 1,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 46907
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "golang.org/x/sys",
            "direct": true,
            "version": "v0.22.0",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5024"
            ],
            "fixed_version": "0.44.0",
            "advisory_count": 1,
            "oldest_advisory_days": 60
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "unknown": 1
        },
        "advisory_count": 1,
        "affected_count": 1,
        "assessed_count": 14,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 1
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.9.1"
        },
        {
          "name": "github.com/BurntSushi/toml",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.0"
        },
        {
          "name": "github.com/google/uuid",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.0"
        },
        {
          "name": "golang.org/x/sys",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.22.0"
        },
        {
          "name": "modernc.org/sqlite",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.34.5"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "github.com/burntsushi/toml",
            "direct": true,
            "version": "v1.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/google/uuid",
            "direct": true,
            "version": "v1.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/spf13/cobra",
            "direct": true,
            "version": "v1.9.1",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/sys",
            "direct": true,
            "version": "v0.22.0",
            "ecosystem": "go"
          },
          {
            "name": "modernc.org/sqlite",
            "direct": true,
            "version": "v1.34.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/dustin/go-humanize",
            "direct": false,
            "version": "v1.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/inconshreveable/mousetrap",
            "direct": false,
            "version": "v1.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/mattn/go-isatty",
            "direct": false,
            "version": "v0.0.20",
            "ecosystem": "go"
          },
          {
            "name": "github.com/ncruces/go-strftime",
            "direct": false,
            "version": "v0.1.9",
            "ecosystem": "go"
          },
          {
            "name": "github.com/remyoudompheng/bigfft",
            "direct": false,
            "version": "v0.0.0-20230129092748-24d4a6f8daec",
            "ecosystem": "go"
          },
          {
            "name": "github.com/spf13/pflag",
            "direct": false,
            "version": "v1.0.6",
            "ecosystem": "go"
          },
          {
            "name": "modernc.org/libc",
            "direct": false,
            "version": "v1.55.3",
            "ecosystem": "go"
          },
          {
            "name": "modernc.org/mathutil",
            "direct": false,
            "version": "v1.6.0",
            "ecosystem": "go"
          },
          {
            "name": "modernc.org/memory",
            "direct": false,
            "version": "v1.8.0",
            "ecosystem": "go"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 14,
        "direct_count": 5,
        "indirect_count": 9
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 58,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 1,
        "closed_unmerged_prs": 5
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "mbreese",
          "commits": 283,
          "avatar_url": "https://avatars.githubusercontent.com/u/98979?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "go.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum"
      ],
      "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": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "14 out of 14 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/14 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 3 contributing companies or organizations -- score normalized to 10",
            "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": 0,
            "reason": "no 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 0 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": null,
            "reason": "packaging workflow not 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": 0,
            "reason": "security policy file not 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": 9,
            "reason": "1 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "661b9ee06db3f16cd5e39286f60fa902d6c88bce",
        "ran_at": "2026-07-22T09:13:18Z",
        "aggregate_score": 3.9,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-21T01:32:14Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-21T01:28:30Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/compgenlab/batchq",
    "host": "github.com",
    "name": "batchq",
    "owner": "compgenlab"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 57,
      "inputs": {
        "security": 49,
        "vitality": 80,
        "community": 24,
        "governance": 57,
        "engineering": 67
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 80,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 74,
            "inputs": {
              "commits_last_year": 211,
              "human_commit_share": 1,
              "days_since_last_push": 1,
              "active_weeks_last_year": 14
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "14/52 weeks with commits",
                "points": 9.7,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 14
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "211 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 211
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 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": 17,
              "latest_release_tag": "v0.4.0",
              "releases_from_tags": false,
              "days_since_latest_release": 1,
              "mean_days_between_releases": 5
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "17 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 17
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~5 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 5
                    }
                  }
                ],
                "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": 1,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 1 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 24,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "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 (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "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": 57,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "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 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "merged_prs": 58,
              "open_issues": 0,
              "closed_issues": 1,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 5
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "58/63 decided PRs merged",
                "points": 35.2,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 58,
                      "decided": 63
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/14 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 41,
            "inputs": {
              "followers": 0,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "compgenlab",
              "public_repos": 12,
              "account_age_days": 460
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "0 followers of compgenlab",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 0,
                      "login": "compgenlab"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "12 public repos, account ~1 yr old",
                "points": 10.6,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 12
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 1
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/compgenlab/batchq"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 1
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on go",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "go"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 1 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "17 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 17
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 67,
        "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": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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": "14 out of 14 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": false
            },
            "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "at_risk",
        "name": "Security",
        "value": 49,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 39,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 3.9
            },
            "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 not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "14 out of 14 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/14 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "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": "no update tool detected",
                "points": 0,
                "status": "missed",
                "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 0 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 not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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 not detected",
                "points": 0,
                "status": "missed",
                "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": "1 existing vulnerabilities detected",
                "points": 6.8,
                "status": "partial",
                "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. Remaining weights renormalized. Matched 14 resolved dependencies against OSV. 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"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 14
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 89,
            "inputs": {
              "source": "osv",
              "advisories": 1,
              "affected_packages": 1,
              "assessed_packages": 14,
              "unassessed_packages": 0,
              "affected_by_severity": "unknown 1",
              "direct_affected_packages": 1
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "1 affected: golang.org/x/sys v0.22.0 (unknown)",
                "points": 26.6,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "golang.org/x/sys v0.22.0 (unknown)"
                    }
                  }
                ],
                "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 has been public longer than 90 days",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "advisories_none_stale",
                    "params": {
                      "days": 90
                    }
                  }
                ],
                "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": 14,
              "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": 81,
        "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": 1,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 46907
            },
            "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": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 71,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": true,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.62,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "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": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "devcontainer, Dockerfile, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "devcontainer, Dockerfile, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "62 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 62,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "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": "Go",
              "largest_source_bytes": 79814,
              "source_files_sampled": 109,
              "oversized_source_files": 1
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "1/109 source files over 60KB",
                "points": 54.5,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 109,
                      "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": [],
  "report_type": "repository",
  "generated_at": "2026-07-22T09:13:34.334261Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/c/compgenlab/batchq.svg",
  "full_name": "compgenlab/batchq",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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