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

claymore666 / docker-net-dhcp

Docker network plugin: containers get DHCP leases from the LAN. Modernized fork of devplayer0/docker-net-dhcp with macvlan attachment mode.

GoGPL-3.0★ 9 星标⑂ 1 复刻始于 2026年5月在 GitHub 上查看 ↗

claymore666/docker-net-dhcp 的健康指数为 100 分中的 62 分,处于「中等」区间。 其得分最高的类别是Vitality(74/100),最低的是Community & Adoption(42/100)。 最近一次更新在 2 天前。 近期的大部分工作由 1 位贡献者完成。

62
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

Chris个人账户
4 关注者23 个公开仓库始于 2015年2月

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布
Gogithub.com/devplayer0/docker-net-dhcp指向其他仓库——不计分v0.1.4-51833 天前

按类别列示的指标

活力

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

74良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 2 天前
3.5/36提交节奏 — 52 周中有 5 周有提交
18/18提交量 — 最近一年 323 次提交
0/10OpenSSF Scorecard:Maintained — project was created within the last 90 days. Please review its contents carefully
所用输入
commits_last_year323
human_commit_share0.97
days_since_last_push2
active_weeks_last_year5

发布纪律

98优秀
评分方式
27/27有发布版本 — 已发布 28 个发布版本
36/36发布时效 — 最近一次发布版本于 16 天前
27/27发布节奏 — 约每 2.2 天发布一次
8/10OpenSSF Scorecard:Signed-Releases — 5 out of the last 5 releases have a total of 5 signed artifacts.
所用输入
releases_count28
latest_release_tagv1.3.3
releases_from_tags
days_since_latest_release16
mean_days_between_releases2.2

社区与采用

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

42存在风险 · 占总体的 18%
评分方式
14.6/60星标 — 9 个星标
0/25复刻 — 1 个复刻
0/15关注者 — 1 位关注者
所用输入
forks1
stars9
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

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

可持续性与治理

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

51中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
7.6/22.5提交分布 — 头号贡献者编写了 66% 的提交
4.1/13.5贡献者广度 — 3 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 3 contributing companies or organizations -- score normalized to 10
所用输入
bus_factor1
contributors_sampled3
top_contributor_share0.661
评分方式
43.4/46.8议题解决 — 93% 的议题已关闭
36/38.3PR 接受 — 已裁定的 PR 中 147/156 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/25 approved changesets -- score normalized to 0
所用输入
merged_prs147
open_issues12
closed_issues155
issue_closed_ratio0.928
closed_unmerged_prs9
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
5/25所有者影响力 — claymore666 有 4 位关注者
22.1/25既往记录 — 23 个公开仓库,账户约 11 年
所用输入
followers4
owner_typeUser
is_verified
owner_loginclaymore666
public_repos23
account_age_days4,162
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。

工程质量

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

71良好 · 占总体的 20%

工程实践

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

文档

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

安全

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

71良好 · 占总体的 16%

安全态势

74良好
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 28 out of 28 merged PRs checked by a CI test -- score normalized to 10
1.2/2.5CII-Best-Practices — badge detected: Passing
0/7.5Code-Review — Found 0/25 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
7.5/7.5Dependency-Update-Tool — update tool detected
5/5Fuzzing — project is fuzzed
2.5/2.5许可证 — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
5/5Packaging — packaging workflow detected
5/5Pinned-Dependencies — all dependencies are pinned
5/5SAST — SAST tool is run on all commits
5/5Security-Policy — security policy file detected
6/7.5Signed-Releases — 5 out of the last 5 releases have a total of 5 signed artifacts.
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
3.8/7.5Vulnerabilities — 5 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated18
scorecard_versionv5.5.0
checks_inconclusive0
scorecard_aggregate7.5
评分方式
10.4/35直接依赖不含已知公告 — 1 个受影响:github.com/docker/docker v28.5.2+incompatible (high 8.8)
0/25间接依赖不含已知公告 — 在此范围内,传递依赖集合无法与开发和测试依赖区分
32.8/40没有长期未处理的公告 — 1 个携带公告的软件包超过 90 天未处理;最早一条发布于 117 天前
所用输入
sourceosv
advisories10
affected_packages1
assessed_packages65
unassessed_packages2
affected_by_severityhigh 1
direct_affected_packages1
已排除计分(无数据或不适用):间接依赖不含已知公告。 其余权重已重新归一化。 已将 65 个已解析依赖与 OSV 比对。 有 2 项无法评估——没有已解析的版本、生态系统不受支持,或超出所报告的软件包清单。 该仓库未发布任何索引可解析的软件包,因此改为评估仓库依赖图。该图将开发与测试版本固定同交付的依赖混在一起,因此仅对声明的运行时依赖计分;传递性发现仅作为背景信息列出,不计入评分。 未对可达性进行分析。

AI 就绪度

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

69中等 · 占总体的 0%
评分方式
0/45代理指令 — 没有 CLAUDE.md / AGENTS.md / 编辑器规则
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 97 次人类提交中有 97 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
评分方式
18/18一条命令的引导启动 — Makefile
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — Go(静态类型)
10/10可复现环境 — Dockerfile, lockfile
0/10已体现的代理实践 — 最近 100 次提交中没有代理编写的提交
8/8自动化维护 — 最近 100 次提交中有 3 次为自动依赖更新
10/10OpenSSF Scorecard:Pinned-Dependencies — all dependencies are pinned
所用输入
has_nix
has_tests
lockfilesgo.sum
has_dockerfile
typed_language
bootstrap_filesMakefile
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0
toolchain_manifestsgo.mod
dependency_bot_commit_share0.03
评分方式
45/45可类型检查的代码 — Go(静态类型)
55/55可控的文件大小 — 采样的 86 个源文件中有 0 个超过 60KB
所用输入
primary_languageGo
largest_source_bytes41,827
source_files_sampled86
oversized_source_files0

关键数据

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

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • go package 'github.com/devplayer0/docker-net-dhcp' points at a different repository (https://github.com/devplayer0/docker-net-dhcp); excluded from ecosystem scoring

更多细节

OpenSSF Scorecard 7.5 / 10
7.5综合

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

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests28 out of 28 merged PRs checked by a CI test -- score normalized to 10
5CII-Best-Practicesbadge detected: Passing
0Code-ReviewFound 0/25 approved changesets -- score normalized to 0
10Contributorsproject has 3 contributing companies or organizations -- score normalized to 10
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
10Fuzzingproject is fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
10Packagingpackaging workflow detected
10Pinned-Dependenciesall dependencies are pinned
10SASTSAST tool is run on all commits
10Security-Policysecurity policy file detected
8Signed-Releases5 out of the last 5 releases have a total of 5 signed artifacts.
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
5Vulnerabilities5 existing vulnerabilities detected
直接依赖 7
注册表软件包版本约束清单文件
Gogithub.com/docker/dockerv28.5.2+incompatiblego.mod
Gogithub.com/gorilla/handlersv1.5.2go.mod
Gogithub.com/mitchellh/mapstructurev1.5.0go.mod
Gogithub.com/sirupsen/logrusv1.9.4go.mod
Gogithub.com/vishvananda/netlinkv1.3.1go.mod
Gogithub.com/vishvananda/netnsv0.0.5go.mod
Gogolang.org/x/sysv0.46.0go.mod
全部依赖 67

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

注册表软件包版本关系
Gogithub.com/docker/dockerv28.5.2+incompatible直接
Gogithub.com/gorilla/handlersv1.5.2直接
Gogithub.com/mitchellh/mapstructurev1.5.0直接
Gogithub.com/sirupsen/logrusv1.9.4直接
Gogithub.com/vishvananda/netlinkv1.3.1直接
Gogithub.com/vishvananda/netnsv0.0.5直接
Gogolang.org/x/sysv0.46.0直接
Gogithub.com/cespare/xxhash/v2v2.3.0间接
Gogithub.com/containerd/errdefsv1.0.0间接
Gogithub.com/containerd/errdefs/pkgv0.3.0间接
Gogithub.com/containerd/logv0.1.0间接
Gogithub.com/distribution/referencev0.6.0间接
Gogithub.com/docker/go-connectionsv0.7.0间接
Gogithub.com/docker/go-unitsv0.5.0间接
Gogithub.com/felixge/httpsnoopv1.0.4间接
Gogithub.com/go-logr/logrv1.4.3间接
Gogithub.com/go-logr/stdrv1.2.2间接
Gogithub.com/microsoft/go-winiov0.6.2间接
Gogithub.com/moby/docker-image-specv1.3.1间接
Gogithub.com/moby/sys/atomicwriterv0.1.0间接
Gogithub.com/moby/termv0.5.2间接
Gogithub.com/morikuni/aecv1.1.0间接
Gogithub.com/opencontainers/go-digestv1.0.0间接
Gogithub.com/opencontainers/image-specv1.1.1间接
Gogithub.com/pkg/errorsv0.9.1间接
Gogo.opentelemetry.io/auto/sdkv1.2.1间接
Gogo.opentelemetry.io/contrib/instrumentation/net/http/otelhttpv0.68.0间接
Gogo.opentelemetry.io/otelv1.43.0间接
Gogo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttpv1.43.0间接
Gogo.opentelemetry.io/otel/metricv1.43.0间接
Gogo.opentelemetry.io/otel/tracev1.43.0间接
Gogolang.org/x/timev0.15.0间接
Gogotest.tools/v3v3.5.2间接
PyPIbabel2.18.0间接
PyPIbackrefs7.0间接
PyPIcertifi2026.5.20间接
PyPIcharset-normalizer3.4.7间接
PyPIclick8.4.1间接
PyPIcolorama0.4.6间接
PyPIdocker-image-py间接
PyPIghp-import2.1.0间接
PyPIidna3.18间接
PyPIjinja23.1.6间接
PyPImarkdown3.10.2间接
PyPImarkupsafe3.0.3间接
PyPImergedeep1.3.4间接
PyPImike2.2.0间接
PyPImkdocs1.6.1间接
PyPImkdocs-get-deps0.2.2间接
PyPImkdocs-material9.7.6间接
PyPImkdocs-material-extensions1.3.1间接
PyPIpackaging26.2间接
PyPIpaginate0.5.7间接
PyPIpathspec1.1.1间接
PyPIplatformdirs4.10.0间接
PyPIpygments2.20.0间接
PyPIpymdown-extensions10.21.3间接
PyPIpyparsing3.3.2间接
PyPIpython-dateutil2.9.0.post0间接
PyPIpython-dxf间接
PyPIpyyaml6.0.3间接
PyPIpyyaml-env-tag1.1间接
PyPIrequests2.34.2间接
PyPIsix1.17.0间接
PyPIurllib32.7.0间接
PyPIverspec0.1.0间接
PyPIwatchdog6.0.0间接
依赖安全公告 1

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

软件包版本关系严重程度公告数修复版本
github.com/docker/dockerv28.5.2+incompatible直接1029.3.1

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 2258,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Go": 617745,
        "Shell": 62878,
        "Python": 7946,
        "Makefile": 4517,
        "Dockerfile": 7163
      },
      "pushed_at": "2026-07-19T23:06:05Z",
      "created_at": "2026-05-02T12:19:50Z",
      "owner_type": "User",
      "updated_at": "2026-07-20T13:13:03Z",
      "description": "Docker network plugin: containers get DHCP leases from the LAN. Modernized fork of devplayer0/docker-net-dhcp with macvlan attachment mode.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "GPL-3.0",
      "default_branch": "main",
      "license_spdx_raw": "GPL-3.0",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Chris",
      "type": "User",
      "login": "claymore666",
      "company": null,
      "location": "Germany, Mainz-Bingen",
      "followers": 4,
      "avatar_url": "https://avatars.githubusercontent.com/u/11246284?v=4",
      "created_at": "2015-02-28T15:32:11Z",
      "is_verified": null,
      "public_repos": 23,
      "account_age_days": 4162
    },
    "license": {
      "state": "standard",
      "spdx_id": "GPL-3.0",
      "raw_spdx": "GPL-3.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v1.3.3",
          "kind": "patch",
          "published_at": "2026-07-06T00:55:50Z"
        },
        {
          "tag": "v1.3.3-rc1",
          "kind": "prerelease",
          "published_at": "2026-07-06T00:52:46Z"
        },
        {
          "tag": "v1.3.2",
          "kind": "patch",
          "published_at": "2026-07-05T12:02:15Z"
        },
        {
          "tag": "v1.3.2-rc1",
          "kind": "prerelease",
          "published_at": "2026-07-05T11:59:11Z"
        },
        {
          "tag": "v1.3.1",
          "kind": "patch",
          "published_at": "2026-07-05T08:09:05Z"
        },
        {
          "tag": "v1.3.1-rc1",
          "kind": "prerelease",
          "published_at": "2026-07-05T08:05:40Z"
        },
        {
          "tag": "v1.3.0",
          "kind": "minor",
          "published_at": "2026-07-04T05:59:44Z"
        },
        {
          "tag": "v1.3.0-rc1",
          "kind": "prerelease",
          "published_at": "2026-07-04T05:55:49Z"
        },
        {
          "tag": "v1.2.0",
          "kind": "minor",
          "published_at": "2026-06-16T08:20:01Z"
        },
        {
          "tag": "v1.2.0-rc2",
          "kind": "prerelease",
          "published_at": "2026-06-16T08:11:19Z"
        },
        {
          "tag": "v1.1.1",
          "kind": "patch",
          "published_at": "2026-06-14T15:30:39Z"
        },
        {
          "tag": "v1.1.1-rc1",
          "kind": "prerelease",
          "published_at": "2026-06-14T14:53:20Z"
        },
        {
          "tag": "v1.1.0",
          "kind": "minor",
          "published_at": "2026-06-14T10:51:11Z"
        },
        {
          "tag": "v1.1.0-rc1",
          "kind": "prerelease",
          "published_at": "2026-06-14T10:46:28Z"
        },
        {
          "tag": "v1.0.0",
          "kind": "major",
          "published_at": "2026-06-13T08:45:07Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2026-05-05T22:39:38Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-05-05T13:10:26Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-05-05T08:32:29Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2026-05-04T22:39:03Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-05-04T22:24:27Z"
        },
        {
          "tag": "v0.5.3",
          "kind": "patch",
          "published_at": "2026-05-04T17:23:06Z"
        },
        {
          "tag": "v0.5.2",
          "kind": "patch",
          "published_at": "2026-05-03T01:14:30Z"
        },
        {
          "tag": "v0.5.1",
          "kind": "patch",
          "published_at": "2026-05-03T00:05:25Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-05-02T21:03:13Z"
        },
        {
          "tag": "v0.4.1",
          "kind": "patch",
          "published_at": "2026-05-02T17:20:15Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-05-02T14:14:23Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-05-02T14:03:10Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-05-02T14:02:54Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "c2baff17ebabee144c0d182945c58a22ba84639e",
          "body": "Release v1.3.3",
          "is_bot": false,
          "headline": "Merge pull request #322 from claymore666/dev",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-06T00:50:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e634d192854fa0f30ffff42728b31cd3e845cce4",
          "body": "…te (#317) (#323)\n\nPR #320 patched config.json only; the coverage workflow builds its\ninstrumented plugin from config-cover.json, so the release-PR coverage\nrun failed TestNonRootContainer_PersistentClientStarts against an\nunfixed manifest (the new test doing its job, and the improved await\nerror su\n[…]\n  (capabilities, network.type, pidhost, interface.types) must agree\n  between the two manifests; cover-only extras stay unchecked\n- meta-test + wired into test.yaml (gate self-tests + a required step)",
          "is_bot": false,
          "headline": "fix(ci): CAP_SYS_PTRACE in config-cover.json too + manifest parity ga…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-05T20:13:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "916679a9682221016ce028832c7d112f77309d7c",
          "body": "- bump install pins v1.3.2 -> v1.3.3\n- document CAP_SYS_PTRACE in the requested-privileges lists (README,\n  docs/index.md, docs/reference.md)\n- RELEASE_NOTES: v1.3.3 section (#317 fix + counter, #318 badge)",
          "is_bot": false,
          "headline": "Prepare v1.3.3 release (#321)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-05T19:07:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d6525195051fff84ce514b1952883dca9396651f",
          "body": "…non-root containers' netns (#317) (#320)\n\nThe persistent DHCP client opens /proc/<pid>/ns/net at Join; the kernel\ngates that with a PTRACE_MODE_READ check (same uid or CAP_SYS_PTRACE).\nThe manifest granted only NET_ADMIN+SYS_ADMIN, so for any container\nrunning as a non-root USER the open failed EAC\n[…]\ntStarts (user\n  65534:65534, short T1 via option 58, asserts a renewal ACK from the\n  non-root netns and a flat join_start_failures delta); harness gains\n  RunContainerUser and the health-mirror field",
          "is_bot": false,
          "headline": "fix(plugin): grant CAP_SYS_PTRACE so the persistent client can enter …",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-05T18:24:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d924227856cb2de3c99af5e67ccf1472eb4bc7b2",
          "body": "… (#318) (#319)",
          "is_bot": false,
          "headline": "docs: drop the Go Report Card badge — goreportcard.com is end-of-life…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-05T18:24:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1f82a32aaaa25ac215b9b945eb098b3e4b01390a",
          "body": "Release v1.3.2",
          "is_bot": false,
          "headline": "Merge pull request #316 from claymore666/dev",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-05T11:57:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1da580468ad244fb5dff6b1945b40565c45ab9ec",
          "body": "* Prepare v1.3.2 release\n\n- bump install pins v1.3.1 -> v1.3.2 (scripts/bump-version.sh)\n- README: note the docs-only fast-skip on the integration check\n- RELEASE_NOTES: v1.3.2 section (CI-only release, #311/#312 gate)\n\n* fix(ci): gate script uses curl+jq — the runner image has no gh CLI (#311, #312\n[…]\nf too large to see fully fails\n  open instead of judging a truncated view\n- meta-test: stub curl instead of gh; new cases for pagination\n  (full-page continuation both ways) and missing-tool fail-open",
          "is_bot": false,
          "headline": "Prepare v1.3.2 release (#315)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-05T11:09:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4cbce2a4077865ad8bcdbe1be1aa0ce330d92caa",
          "body": "…s exit early (#311, #312) (#314)\n\nA first job step decides whether the event needs the suite:\n- pull_request: all changed paths *.md -> skip (#311). Allowlist is\n  deliberately just *.md; workflows, scripts, Dockerfile, comment-only\n  code changes all still run.\n- push: the commit's tree matches a \n[…]\nuns. Gate logic lives in\nscripts/integration-run-gate.sh with a 15-case meta-test wired into\ntest.yaml's gate-script step (mixed diffs must never classify as\ndocs-only; novel trees must never dedupe).",
          "is_bot": false,
          "headline": "ci(integration): suite-needed gate — docs-only PRs and duplicate tree…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-05T10:23:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f459fee277a88eee280795f4fe1b46f351bd9de9",
          "body": "Release v1.3.1",
          "is_bot": false,
          "headline": "Merge pull request #313 from claymore666/dev",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-05T08:02:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a9a69648bbb1ce3557f3b925db3e0e17435e34b",
          "body": "- bump install pins v1.3.0 -> v1.3.1 (scripts/bump-version.sh)\n- add v1.3.1 section to RELEASE_NOTES.md\n- docs reviewed PR-by-PR against the milestone: #308 is the only\n  user-visible change and its doc updates shipped in-PR (verified,\n  no stale probe-timing references); #301/#302/#304/#306/#309 are\n  CI/test-internal",
          "is_bot": false,
          "headline": "Prepare v1.3.1 release (#310)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T23:09:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1dd4ef601985898f67fd48836d0986beba12fde3",
          "body": "The milestone was renamed: the cycle carries one bug fix (#307) plus\nCI/test hardening — a patch release by semver, not a minor.",
          "is_bot": false,
          "headline": "docs(ci): v1.4.0 -> v1.3.1 in coverage-baseline decision notes (#309)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T22:25:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4b1b1029a6dc0160fb08116ad2d077ee1540e32e",
          "body": "…307) (#308)\n\n5s -> 8s. The probe interface is a freshly-created macvlan child that\nsolicits immediately; the first broadcast DISCOVER is not reliably\ndelivered, and dhcpcd's jittered ~4s retransmit plus 1-2s startup on\nslow/virtualized hosts exceeded the old budget — a live DHCP server\ngot reported\n[…]\nxtra 3s.\n\nPinned by TestPreflightProbeBudget_CoversOneLostDiscover (startup +\nretry + response floor; verified failing at the old 5s value).\nDocs and the failure-test's elapsed bound updated to match.",
          "is_bot": false,
          "headline": "fix(plugin): size preflight probe budget for a lost first DISCOVER (#…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T21:07:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4c1cd5a0b7fd07bae847424d692aaf82374c2ac0",
          "body": "…tence (#305) (#306)\n\n* tests(plugin): cover CreateTemp and Rename error arms of state persistence (#305)\n\nFour tests in the existing failure-injection style: read-only state\ndir for the CreateTemp arm (root-skipped like the other DAC tests),\nand a non-empty directory occupying the final path for th\n[…]\nm tests (#305)\n\nMeasured merged 84.1 on this PR's coverage dispatch (run #26); all\nother packages identical to the decimal across four runs, so the\n+0.3 is attributable to the new tests, not variance.",
          "is_bot": false,
          "headline": "tests(plugin): cover CreateTemp and Rename error arms of state persis…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T19:58:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dc7d05680ac1420aafd8352e0abd8217609fa0ed",
          "body": "…03) (#304)\n\npkg/dhcp 85.5 -> 89.5, cmd/dhcp-handler 50.0 -> 74.0, pkg/plugin\n82.0 -> 83.5. The first two were still udhcpc-era carry-overs; the\ndhcpcd migration and v1.3.0 test work earned coverage no PR ratcheted\nin, leaving up to 25 points of silent-regression headroom. Measured\nagainst Coverage \n[…]\n its rules.\n\nVerified locally: ratchet passes on measured numbers, fails on a\nsynthetic 0.6-point pkg/dhcp regression the old floor would have\npassed, and scripts/test-coverage-ratchet.sh stays green.",
          "is_bot": false,
          "headline": "tests(ci): ratchet coverage floors to post-dhcpcd measured levels (#3…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T18:25:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5df1b428eb7fb3cdec335f12b798c778860b48ab",
          "body": "The #207 workflow audit found two comments in coverage.yml that\npredate #127 wiring the pull_request->main trigger:\n\n- the header claimed only workflow_dispatch is wired so forks can't\n  trigger the workflow at all — a forked PR into main does trigger it;\n  the outside-collaborator approval requirem\n[…]\now runs only on manual\n  dispatch — it also runs on every release PR.\n\nComment-only; no behavior change. Audit verdict on the issue: all 12\nworkflows earn their place, nothing redundant or superseded.",
          "is_bot": false,
          "headline": "docs(ci): fix stale coverage.yml trigger comments (#207) (#302)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T16:55:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3b15dc1f3f34cb220078e9bdc9d1ff8287fdc528",
          "body": "…p (#296) (#301)\n\nThe cutover to the ephemeral runner pool dropped the gpu1-era\nselfhosted-docker concurrency group on the grounds that the runners\nisolate all Docker state. State, yes — but they still share one host's\nCPU/IO, and the suite carries real-time DHCP timing: on the v1.3.0\nrelease PR, co\n[…]\n.yml,\ncancel-in-progress: false. Documented caveat: GitHub keeps at most one\npending run per group, so a third concurrent run cancels the queued\none (manual re-run) — acceptable at this repo's volume.",
          "is_bot": false,
          "headline": "ci: serialize privileged self-hosted jobs via shared concurrency grou…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T16:55:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8bf19622175f744b205e0f1e16c8a68c8950ccda",
          "body": "Release v1.3.0",
          "is_bot": false,
          "headline": "Merge pull request #295 from claymore666/dev",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T05:53:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a94fb3148437cb90b8af3608fc3e945398190150",
          "body": "The tee'd test steps ran under the implicit Actions shell (bash -e,\nno pipefail), so tee's exit 0 masked go-test failures since #277 —\nthe comment claiming the default shell has pipefail was wrong. Declare\nshell: bash explicitly (bash -eo pipefail) on both steps.\n\nExpected effect: this PR's own integration run goes red on the\nalready-failing TestStableLease_IPvlanSameIPAcrossRecreate (#298) —\nthat red is the fix working.",
          "is_bot": false,
          "headline": "ci(integration): fail the gate on piped test failures (#297) (#299)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T01:56:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "30f1d1298122d6427a94646ba65f2a41b65465fe",
          "body": "* Revert \"feat(ipvlan): stable DHCP client-id for lease stability across recreate (#219) (#285)\"\n\nThis reverts commit c4b4f95e4ff9276568381931ee2daa889a47fc1f.\n\n* docs(release): drop stable_lease from v1.3.0 notes and option docs (#298)\n\nThe #286 release prep documented stable_lease/lease_seed; with #285\nreverted they are no longer in the release. The option-61 paragraph now\nstates the recreate-stability gap plainly and points at the\ndeterministic-MAC track (#218/#219) that closes it.",
          "is_bot": false,
          "headline": "revert: de-scope stable_lease (#219) from v1.3.0 (#300)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-04T01:34:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "23b5c651dd0da8ef7b348ef10659db999ca1e7e4",
          "body": "* docs: prepare v1.3.0 release (pins, notes, doc reconciliation)\n\n- bump published-image pins v1.2.0 -> v1.3.0 (README, docs/)\n- add RELEASE_NOTES v1.3.0 section with option-121 compatibility note\n- reconcile docs/parent-attached-modes.md against the milestone:\n  document stable_lease / lease_seed /\n[…]\n(GO-2026-5746, GO-2026-5617, and the newly published GO-2026-5668),\nso govulncheck reports them via init-chain traces; they are now accepted\nin .github/vuln-allowlist.txt (#292). Assessment unchanged.",
          "is_bot": false,
          "headline": "Prepare v1.3.0 release (#286)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-03T21:17:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dd211f53eda3664bbc532a222cc7b379972f53bf",
          "body": "…check allowlist (#291) (#294)\n\nThe config claimed govulncheck was green on the accepted docker/docker\nadvisories and declared any govulncheck report as voiding an\nacceptance. Since the Go vuln DB imported the docker cp/archive\nadvisories (2026-06-28), govulncheck reports them through init-chain\nsym\n[…]\ny instead, map each GHSA to its GO- ID,\nand record why the two medium-severity advisories are absent from\nallow-ghsas (below fail-on-severity). No functional change: the\nallow-ghsas list is unchanged.",
          "is_bot": false,
          "headline": "docs(ci): reconcile dependency-review config comments with the govuln…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-03T21:17:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "519c815e7274846b3dbd1a9ee708adb95d9ad14e",
          "body": "… (#293)\n\nBumps the actions group with 8 updates in the / directory:\n\n| Package | From | To |\n| --- | --- | --- |\n| [actions/checkout](https://github.com/actions/checkout) | `6.0.3` | `7.0.0` |\n| [actions/setup-go](https://github.com/actions/setup-go) | `6.4.0` | `6.5.0` |\n| [github/codeql-action/in\n[…]\npe: version-update:semver-patch\n  dependency-group: actions\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps): bump the actions group across 1 directory with 8 updates…",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-03T21:17:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "173c1eee9ae2bc1b21b5604e1647515338ddca37",
          "body": "…s (#289)\n\nBumps the docker group with 1 update in the / directory: golang.\nBumps the docker group with 1 update in the /ci/runner-image directory: debian.\n\n\nUpdates `golang` from `f1ddd9f` to `3ad5730`\n\nUpdates `debian` from `4e401d9` to `28de087`\n\n---\nupdated-dependencies:\n- dependency-name: debia\n[…]\npendency-type: direct:production\n  dependency-group: docker\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps): bump the docker group across 2 directories with 2 update…",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-03T21:10:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "67deee0b2f119371e0b1aa978a8d1f5216d09f5c",
          "body": "… (#291) (#292)\n\nGO-2026-5617, GO-2026-5668 and GO-2026-5746 all live in dockerd's\ndocker cp / container archive handling; this plugin only uses the\nclient API. No fixed release exists for the legacy\ngithub.com/docker/docker module line (fix is only in\ngithub.com/moby/moby/v2@v2.0.0-beta.14), so per the allowlist rules\nthese are accepted with justification until a fixed release ships.",
          "is_bot": false,
          "headline": "ci(govulncheck): allowlist three daemon-side docker/docker advisories…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-07-03T20:43:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c4b4f95e4ff9276568381931ee2daa889a47fc1f",
          "body": "…te (#219) (#285)\n\nipvlan children share the parent NIC's MAC on the wire, so a DHCP server\nkeying on MAC cannot tell them apart, and the default per-endpoint\nclient-id is derived from the random Docker endpoint ID, which changes on\nevery recreate. Add an opt-in stable_lease mode (ipvlan only) that \n[…]\nivation, the full\nresolve precedence, and the bridge/macvlan rejection; integration coverage\nfor same-IP-across-recreate (headline), distinct-identities-distinct-IPs\n(control), and the mode rejection.",
          "is_bot": false,
          "headline": "feat(ipvlan): stable DHCP client-id for lease stability across recrea…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-17T14:38:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "22f64910091d415bbade6deb55a19ac45b363209",
          "body": "…(#274)\n\nBumps the docker group with 2 updates in the / directory: golang and alpine.\n\n\nUpdates `golang` from `7a3e500` to `f1ddd9f`\n\nUpdates `alpine` from 3.24.0 to 3.24.1\n\n---\nupdated-dependencies:\n- dependency-name: golang\n  dependency-version: 1.26-alpine\n  dependency-type: direct:production\n  d\n[…]\nype: version-update:semver-patch\n  dependency-group: docker\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "build(deps): bump the docker group across 1 directory with 2 updates …",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-06-17T09:09:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "17f099b434fce7718186b8c5982be12272161841",
          "body": "refactor: rename pkg/udhcpc → pkg/dhcp, cmd/udhcpc-handler → cmd/dhcp-handler (#245)",
          "is_bot": false,
          "headline": "Merge pull request #284 from claymore666/feature/245-rename-dhcp-pkg",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T20:30:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9c6aa0280251b0bf84ed102295c1496766d06d55",
          "body": "…-handler (#245)\n\nPost-#152 (busybox→dhcpcd) the udhcpc names are misnomers. Rename to\nclient-agnostic names so the package isn't tied to a concrete client\nagain:\n\n- pkg/udhcpc → pkg/dhcp (package, import paths, qualifiers)\n- cmd/udhcpc-handler → cmd/dhcp-handler (dir, built binary,\n  /usr/lib/net-d\n[…]\nhistorical \"busybox udhcpc/udhcpc6\" comments (accurate\nhistory) and RELEASE_NOTES.md (frozen per-release changelog).\n\nPure internal refactor — no wire, manifest, state, or upgrade impact.\n\nCloses #245",
          "is_bot": false,
          "headline": "refactor: rename pkg/udhcpc → pkg/dhcp, cmd/udhcpc-handler → cmd/dhcp…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T19:49:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb5fb6fe9c0925e7bbdffe8caea9a747f914ddf3",
          "body": "feat(dhcp): surface WPAD + timezone DHCP options (observe-only) (#262)",
          "is_bot": false,
          "headline": "Merge pull request #283 from claymore666/feature/262-wpad-timezone",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T19:45:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2d0c22f8d4394f4df3c42ece9af3a5caf71bb7cf",
          "body": "Parse and log four more server-supplied informational options, the same\nobserve-only way as NTP/TFTP (no container injection — the no-plumbing\nbar):\n- WPAD URL (option 252)\n- RFC 4833 timezone PCode/TCode (options 100/101)\n- legacy time offset (option 2)\n\ndhcpcd option names verified against the ima\n[…]\ndefine; integration (fixture advertises 252/100/101/2,\nasserts the plugin log surfaces them) — which also pins the dhcpcd option\nnames end-to-end. Docs: parent-attached-modes.md observed-options list.",
          "is_bot": false,
          "headline": "feat(dhcp): surface WPAD + timezone DHCP options (observe-only) (#262)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T19:23:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e26f8fc6e05121ecf3be090e0e46294c25b1da0b",
          "body": "A container on a `-o register_dns=true` network now asks the DHCP server\nto register its name in DNS: it becomes resolvable by name on the LAN,\nnot just reachable by its leased IP — the on-mission completion of the\nhostname hint we already send (no per-container plumbing).\n\n- dhcpcd config: new `fqd\n[…]\nter_dns=true container resolves <hostname>.<domain> to its leased\n  IP. The resolving itself proves opt 81 (not the bare hostname) landed.\n\nDocs: reference.md option table row + a dynamic-DNS section.",
          "is_bot": false,
          "headline": "feat(dhcp): opt-in DHCP FQDN registration (option 81/39) (#261) (#282)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T18:38:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "38976f13d704fd3794da7c02f75f81cc31f1224e",
          "body": "…m) (#281)\n\nREADME and docs/index.md said \"MIT — see LICENSE.md\", but LICENSE.md is\nand has always been the GPL-3.0 text, and GitHub detects the repo as\nGPL-3.0. Upstream (devplayer0/docker-net-dhcp) is GPL-3.0, so this fork —\na derivative work — must remain GPL-3.0; it was never MIT and could not\nb\n[…]\no MIT LICENSE file ever\nexisted and there are no MIT/SPDX headers in source. Correct the stated\nlicense to GPL-3.0 in both places and note the upstream inheritance so\nthe same confusion doesn't recur.",
          "is_bot": false,
          "headline": "docs: correct stated license to GPL-3.0 (matches LICENSE.md + upstrea…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T18:22:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c6ca90386b3e5e9f49a094b2291d33db88d2c958",
          "body": "…(#280)\n\nDHCP servers that hand out classless static routes (option 121, RFC 3442)\nwere ignored: dhcpcd was asked for the option, but the event builder never\nread new_classless_static_routes back and nothing applied it. Containers\nonly got routes copied from the host parent link, never DHCP-pushed o\n[…]\n option 121 to a\nvendor-class-tagged client and asserts the route lands in the container\n(and is absent without the opt-in). Docs: option-121 behaviour and the\nskip_routes interaction in reference.md.",
          "is_bot": false,
          "headline": "feat(routes): honor DHCP classless static routes (option 121) (#260) …",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T17:55:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "80c16bd4e9a5f3ba2315f21f85f81610e1441b30",
          "body": "The integration suite is ~20 min of mostly deliberate DHCP-protocol\nwaits, but where that wall-clock goes was only visible by grepping the\nverbose go-test output. Add a summary so every run self-documents its\nslowest tests.\n\n- scripts/integration-timing.sh: parse one or more 'go test -v' logs,\n  pri\n[…]\ny' step (pipefail keeps a test failure fatal despite\n  the tee).\n\nThis is the tooling that made the #253 renewal target obvious and points\nat the next ones (the failure suite and the v6 renewal test).",
          "is_bot": false,
          "headline": "ci(integration): surface a per-test timing summary (#277)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T16:53:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ae1fd5be848731c5d86c644ed70237c441658c2f",
          "body": "…255) (#273)\n\nThe plugin image was rebuilt from scratch every integration run (~43s):\nthe COPY of cmd/ and pkg/ invalidates the build layer on any code\nchange, so 'go build ./cmd/...' recompiled every package each PR with no\nincremental build cache, and 'go mod download' re-fetched modules.\n\nAdd Bui\n[…]\nakefile: export DOCKER_BUILDKIT=1 on build / build-cover so the\n  classic builder can't be picked up and choke on the mount flags\n  (Docker >= 23 defaults to BuildKit anyway; this is belt-and-braces).",
          "is_bot": false,
          "headline": "ci(integration): cache the plugin build's Go module + build caches (#…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T15:06:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c2ff5c87a0732e880b1fdc99e31bdae234c280de",
          "body": "… lease (#253) (#272)\n\nThe lease_renew test was the single longest case in the suite: it rode\nthe shared 2m fixture lease and waited ~70s for T1 (half-lease) to fire.\ndnsmasq's minimum lease is a hard 2m, so the lease can't be shortened —\nbut a server may advertise DHCP option 58 (T1, renewal) / 59 \n[…]\nn top of the bind, IP unchanged). The\nmechanism is self-validating — if the advertised T1 is not honoured, no\nrenewal ACK lands in the shortened window and the test fails rather than\nsilently passing.",
          "is_bot": false,
          "headline": "test(integration): drive lease renewal via advertised T1, not a short…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T14:04:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cf9117802796348479a7cc09932877369b0793b0",
          "body": "The failure-injection suite and two v6 recovery polls slept at 1–2s in\npure poll-until-condition loops, overshooting the moment each bounded\ncondition was actually met. Drop them to a 250ms floor (500ms for the\nre-acquisition loop, which polls via docker exec) so the loops return\nsooner. Deadline bu\n[…]\ns floor honours the caution in #254: keep extra CPU off the\ntiming-sensitive preflight probe. Sleeps already at 100–500ms and the\nreal protocol-timing waits (the ~30s outage ticks) are left untouched.",
          "is_bot": false,
          "headline": "test(integration): tighten coarse poll intervals (#254) (#271)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T13:26:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b76ca5faf1716be52070215b841bd350e9162e79",
          "body": "… (#267) (#270)\n\n:latest was published by a SECOND `make push`, which re-ran\n`docker plugin create` and re-tarred the rootfs non-reproducibly — so\n:latest got its own digest, distinct from :vX.Y.Z and uncovered by the\ncosign signature (cosign signs by digest). Confirmed live: :v1.1.1 and\n:latest car\n[…]\nr diverges again\n\nThe retag is :latest-only (off for rc), so the rc dry-run does not\nexercise the wiring; the mechanism is validated manually on the issue,\nand the assertion guards every real release.",
          "is_bot": false,
          "headline": "fix(release): retag :latest onto the signed version digest with crane…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T10:58:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6c45ed5fa06936d74a3f0c85157ff81ab33f7996",
          "body": "Closes #268. Split intent (docs/requirements.in) from a pip-compile --generate-hashes lock (docs/requirements.txt); both pip installs use --require-hashes. Clears the two Scorecard PinnedDependencies alerts. Dependabot bumps versions+hashes together.",
          "is_bot": false,
          "headline": "ci(pages): hash-pin the Python doc toolchain (#269)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T10:35:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4819317c39cee3d726f56b21c88ff230af04c85c",
          "body": "Release v1.2.0 — cosign v3 signing fix",
          "is_bot": false,
          "headline": "Merge pull request #266 from claymore666/dev",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T08:08:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e39fd9b48826138556121476ce0fe8c30614c0f4",
          "body": "…#265)\n\nThe cosign-installer bump (#196) moved the installed cosign binary from\nv2 to v3.0.6. cosign v3 removed sign-blob's --output-signature /\n--output-certificate pair in favour of a single Sigstore bundle, so the\n\"Package and sign release artifact\" step failed:\n\n    Error: signing checksums.txt:\n[…]\nhcp:v1.1.1\n  placeholder in parent-attached-modes.md to v1.2.0\n- generalise bump-version.sh to match the image at any namespace so\n  placeholder examples bump too (the v1.1.1 drift above was this gap)",
          "is_bot": false,
          "headline": "fix(release): migrate cosign sign-blob/verify-blob to the v3 bundle (…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T07:43:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "26d5f1e30fd49880c332abced97489341816bc51",
          "body": "Release v1.2.0",
          "is_bot": false,
          "headline": "Merge pull request #257 from claymore666/dev",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-16T07:13:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "63ce96eb7792d1e6d7df03f75310b315764de085",
          "body": "…tays measured (#259)\n\nThe dhcpcd migration (#152) silently dropped cmd/udhcpc-handler out of\nthe coverage ratchet: the cover build sets GOCOVERDIR in the plugin env\nand the handler (a separate process) used to inherit it, but dhcpcd\nscrubs the environment before exec'ing its hook — the same reason \n[…]\n it set. Production never sets GOCOVERDIR, so this emits\nnothing there; only the -cover build (config-cover.json sets\nGOCOVERDIR=/coverage) is affected, restoring the handler's counters.\n\nCloses #258.",
          "is_bot": false,
          "headline": "fix(coverage): forward GOCOVERDIR to the dhcpcd hook so the handler s…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T23:16:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "273e9d93e19ce002923df199bd65258179fe581b",
          "body": "…s (#256)\n\n- Bump every published-image install pin v1.1.1 → v1.2.0 across README\n  and docs/ via scripts/bump-version.sh (#251's first real use; it\n  caught pins in bridge-mode.md and index.md that the manual list\n  missed).\n- Add the ## v1.2.0 RELEASE_NOTES section: dhcpcd replaces busybox\n  (#152\n[…]\ns a\n  \"future enhancement\" — both shipped in this release via the dhcpcd\n  migration. Also corrected the capability list (the manifest grants\n  CAP_NET_ADMIN + CAP_SYS_ADMIN only, not CAP_SYS_PTRACE).",
          "is_bot": false,
          "headline": "docs: v1.2.0 release prep — bump pins, RELEASE_NOTES, doc-review fixe…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T22:26:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b4c49513402dbfd0b3971e5d0ae251c606bba91b",
          "body": "…252)\n\nThe release version-pin bump (runbook step 2) was a manual hand-edit of\nevery published-image snippet in README/docs — mechanical and easy to\ndo partially, which ships docs that install the previous version.\n\nAdd scripts/bump-version.sh vX.Y.Z, which rewrites only the image-ref\npins (ghcr.io/\n[…]\nt breaking the release branch where pins lead the latest tag.\nscripts/test-check-version-pins.sh self-tests both, per the gates-are-\ntested rule. Runbook step 2 now points at the script.\n\nCloses #251.",
          "is_bot": false,
          "headline": "ci: automate release version-pin bump + add a pin-consistency gate (#…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T21:56:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "599a74fe0034914295955f85738a85c83e619ce7",
          "body": "* ci(integration): add opt-in hosted cross-check lane (#238)\n\nAdd integration-hosted.yml: runs the live integration + failure-injection\nsuites on a stock ubuntu-latest runner via workflow_dispatch and a weekly\nschedule. It is explicitly non-gating and not a required check — a\nportability probe that \n[…]\nld pending it is now live (it starts firing once the file\nreaches the default branch). Refresh the security note: schedule, like\nworkflow_dispatch, runs repo-owned code only — no fork-PR-as-root path.",
          "is_bot": false,
          "headline": "ci(integration): opt-in hosted cross-check lane (#238) (#241)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T21:56:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7b3fb7d73f2aad5c39c0cecd9ce153a3d06857dd",
          "body": "…only proc (#250)\n\ndhcpcd writes net/ipv4/conf/<if>/promote_secondaries (and, for v6,\nautoconf/accept_ra) during if_init regardless of --noconfigure. On a\nread-only /proc/sys — the managed-plugin rootfs, and stock Docker\ncontainers where runc remounts it ro — the v4 write returns EROFS,\ndhcpcd abort\n[…]\n-hosted runner).\n\nAlso tee dhcpcd's stderr into a bounded tail buffer and fold it into the\nnon-zero-exit error, so a future failure surfaces dhcpcd's real\ndiagnostic instead of a bare \"exit status 1\".",
          "is_bot": false,
          "headline": "fix(dhcpcd): remount /proc/sys rw so interface setup survives a read-…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T19:03:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "892bdbc261691b00d6e9b4035df7719fa217782a",
          "body": "* fix(ipvlan): wire the dhcpcd broadcast directive (#243)\n\nipvlan-L2 slaves share the parent NIC's MAC, so a unicast OFFER/ACK to\nthat MAC during initial acquisition can't be demuxed to the right slave.\nbusybox set the DHCP BROADCAST flag for this via 'udhcpc -B'; the dhcpcd\nport (#223) declared DHC\n[…]\ns it robust regardless of whether the server unicasts to an\nunconfigured client. All five lifecycle tests (incl. ipvlan without the\nfixture crutch) already passed; this fixes the remaining probe test.",
          "is_bot": false,
          "headline": "fix(ipvlan): wire the dhcpcd broadcast directive (#243) (#249)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T18:37:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "74a8b5a6da735091d151a23df60b99b7efcb8e4b",
          "body": "…gration (#242) (#244)\n\nThe busybox->dhcpcd migration (#152) and v6 work (#213) shipped, but many\ncode comments still described the old busybox udhcpc/udhcpc6 client and\nits mechanisms. Update comments (and a couple of log/string texts) to the\ndhcpcd reality across pkg/plugin, pkg/udhcpc, pkg/util, \n[…]\n' own busybox tooling (genuinely busybox, not the plugin\nclient).\n\nFlagged a real latent gap found during the sweep: the ipvlan\nDHCPClientOptions.Broadcast field is a no-op in the dhcpcd port -> #243.",
          "is_bot": false,
          "headline": "chore: refresh stale udhcpc/busybox code comments after the dhcpcd mi…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T11:56:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "35ba85e152517e50c4d698d3ab59da08641c3c31",
          "body": "…stone (#239) (#240)\n\nThe doc review (step 3) was a memory-based top-to-bottom read, with the\nrc dry-run (step 8) as the last checkpoint. That let the #205<->#152\ndrift through: a behaviour change shipped while the docs were restructured\nin the same milestone, and the prose still described the old c\n[…]\nsignal to look harder. The full top-to-\nbottom read stays as the catch-all. Reframe the rc window (step 8) as the\nenforcement gate: no real tag until every milestone PR is ticked off\nagainst the docs.",
          "is_bot": false,
          "headline": "docs(runbook): make the release doc review PR-driven against the mile…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T11:55:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1023dcf1c8cbbc4bda05f521b92b23f8d646b599",
          "body": "* docs: correct client references for the dhcpcd migration (#234)\n\nThe README/docs restructure (#205) and the busybox->dhcpcd client\nmigration (#152) landed in the same milestone, leaving the restructured\ndocs describing the old busybox udhcpc/udhcpc6 client. Bring every\nclient-behaviour description\n[…]\nys state by interface name with no runtime override. Kept at\nthe conceptual altitude: no argv flags or wire-format specifics (those\nlive in code comments, which can drift with the code they describe).",
          "is_bot": false,
          "headline": "docs: correct client references for the dhcpcd migration (#234) (#237)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T11:55:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9a87bf5b4c65baaf279bf5e4e5f17b246a07737b",
          "body": "…t) (#213) (#236)\n\nTwo IPv6 inputs were captured but dropped because busybox udhcpc6 had\nno v6 equivalent of -r: a static --ip6 (Interface.AddressIPv6) and the\nprior endpoint's v6 address preserved through the tombstone. v6 was\ntherefore non-sticky exactly where v4 was sticky.\n\nNow that #152 moved t\n[…]\nack container keeps its v6\naddress across docker restart (the v6 sibling of the v4 tombstone\ntest). Docs (reference, parent-attached-modes) corrected — they\npreviously stated v6 requests were ignored.",
          "is_bot": false,
          "headline": "feat(dhcpv6): request a preferred IPv6 address (--ip6 + tombstone hin…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T10:22:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "af82874bdd2ddb832e30327aa68d31aa19a4fbaf",
          "body": "The /Plugin.Health wire counters (leases_obtained, leases_renewed,\ndhcp_timeouts, naks_received, lease_changed) were family-agnostic:\nhandleEvent/renew already receive a v6 bool but bumped the same atom\nfor v4 and v6. On a dual-stack host that hides the v6-specific failure\nsignal — exactly what we n\n[…]\nvent leaves the v6 sibling at zero (and vice versa), plus that the\nnew fields serialize under their snake_case keys on /Plugin.Health.\nDocs Health sections (reference + parent-attached-modes) updated.",
          "is_bot": false,
          "headline": "feat(health): split DHCP wire counters by address family (#212) (#235)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T09:40:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c305403016e67a4a2409cdfa88ef72fbb8e40f00",
          "body": "* refactor(udhcpc): parse dhcpcd hook events instead of busybox (#152)\n\nbusybox udhcpc6 fills the DHCPv6 IAID with rand() per process and offers\nno override, so the CreateEndpoint one-shot and the persistent client\nalways land in different identity associations and the server hands out\ntwo addresses\n[…]\nllowlist (1–15 chars, alphanumeric-led, [A-Za-z0-9._-])\nbefore it can reach the command — closing the taint flow and rejecting\nany flag-shaped or shell-meaningful value as the simple correct contract.",
          "is_bot": false,
          "headline": "DHCPv6: replace busybox with dhcpcd to unify the IA (#152) (#223)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T09:15:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7d804151432a185f536b69bb06dfd13a43b540bb",
          "body": "…) (#233)\n\nCodeQL go/path-injection (CWE-22): the per-network options helpers\ninterpolate networkID — which originates from the libnetwork driver\nrequest — into filesystem paths without validation\n(stateFilePath -> filepath.Join; saveOptions -> os.CreateTemp pattern).\nA network ID containing path se\n[…]\nqueness), removing that taint sink entirely.\n- Unit tests cover the rejection paths and that nothing is written\n  out of bounds.\n\nPre-existing; surfaced as the only red, non-required check on PR #223.",
          "is_bot": false,
          "headline": "fix(state): validate networkID before building state-file paths (#232…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T08:30:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "52d5cf62b1cfde91cf052c403259bd12e3384227",
          "body": "apk-pin-check signals when a newer busybox-extras/iproute2 is available\nbut not whether the pinned versions carry CVEs. Add a Trivy scan of the\nbuilt runtime rootfs scoped to OS packages (--pkg-types os), so it\ncomplements rather than overlaps govulncheck (Go, reachability-gated).\n\nInformational lik\n[…]\nr the same discipline as the govulncheck\nallowlist: justification + review date, never a bare ID.\n\nRuns weekly, on dispatch, on push to dev, and on PRs that touch the\nDockerfile or this scan's config.",
          "is_bot": false,
          "headline": "ci: scan plugin rootfs for OS-package CVEs with Trivy (#143) (#231)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-15T00:29:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "db537f846d020b96d34854278c978e5d3b1e15c9",
          "body": "ci: bump alpine to 3.24.0 + re-pin apk packages (#195)",
          "is_bot": false,
          "headline": "Merge pull request #230 from claymore666/ci/195-alpine-3.24",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T23:43:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eea3dc3864dc9f166055664714e723f07d913139",
          "body": "Dependabot #195 bumped only the FROM digest, which breaks the build: the\napk pins (busybox-extras, iproute2) reference 3.20 package versions that\ndon't exist in 3.24's repos. Re-pin both to their 3.24.0 versions so the\nruntime stage installs cleanly:\n\n- busybox-extras 1.36.1-r31 -> 1.37.0-r31 (suppl\n[…]\n.9.0-r0    -> 7.0.0-r0\n\nVerified: image builds on alpine:3.24.0; udhcpc, udhcpc6, and ip present\nin the runtime image; scripts/check-apk-pins.sh --strict reports all pins\ncurrent against the new base.",
          "is_bot": false,
          "headline": "ci: bump alpine to 3.24.0 and re-pin apk packages (#195)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T23:25:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d25947b87e14b6e1c4803191d436dfd323221a28",
          "body": "ci: bump cosign-installer to v4.1.2, hold download-artifact at v7 (#196)",
          "is_bot": false,
          "headline": "Merge pull request #227 from claymore666/ci/196-split-deps",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T23:22:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f873cc2bd44e6d65de7e1f319c98eb0b8db819a7",
          "body": "ci: bump pages.yml setup-python to v6.2.0 (Node 24) (#225)",
          "is_bot": false,
          "headline": "Merge pull request #226 from claymore666/fix/225-setup-python-node24",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T23:10:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d7df9ea27d08b7960c1e012d62bb9d7ab149b9cc",
          "body": "Splits Dependabot's grouped actions PR (#196) so the two bumps can be\nhandled on their own risk profiles:\n\n- sigstore/cosign-installer 3.9.2 -> 4.1.2 (default cosign 2.x -> 3.x).\n  Release-path only (release.yml signing step); not exercised by PR CI,\n  so it must ride an rc-tag dry-run before the ne\n[…]\nad-artifact has no v8 yet, so\n  pairing upload v7 with download v8 would mix majors on the release\n  artifacts. Added a Dependabot ignore (>= 8) until upload-artifact v8\n  ships so both bump together.",
          "is_bot": false,
          "headline": "ci: bump cosign-installer to v4.1.2, hold download-artifact at v7 (#196)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T23:05:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3693fce69118eb0113e908c86e0fc721d7fb8a20",
          "body": "actions/setup-python v5 runs on Node 20, which GitHub forces off on\n2026-06-16. v6.2.0 declares using: node24. Bump both the build and deploy\njobs; the rest of the repo's actions are already on node24-capable majors.",
          "is_bot": false,
          "headline": "ci: bump pages.yml setup-python to v6.2.0 (Node 24) (#225)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T22:53:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eb56239bdd708f61ec5c89563191042d2e2eec05",
          "body": "docs: versioned documentation site via GitHub Pages (#133)",
          "is_bot": false,
          "headline": "Merge pull request #224 from claymore666/docs/133-pages-site",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T22:44:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ffe332a56bb94059ee2dc59251732881a0a9cdc7",
          "body": "Add a project documentation site built from the in-repo docs/ tree with\nmkdocs-material and versioned with mike, mirroring the registry tagging\nscheme: each release publishes its vX.Y.Z docs and moves the latest\nalias; rc tags publish a preview without moving latest; dev pushes\nrefresh a moving dev \n[…]\ntracked).\n- runbook: one-time Pages enablement + per-release behavior; the docs\n  review now is the site review.\n- README: docs-site badge + link; reference.md cross-link repointed to\n  the site home.",
          "is_bot": false,
          "headline": "docs: versioned mkdocs-material site published to GitHub Pages (#133)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T22:27:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "085bd392d33af4a0b2bb8bdbe1458d6fa58c4770",
          "body": "docs: restructure README into a concise landing page + docs/ split (#205)",
          "is_bot": false,
          "headline": "Merge pull request #222 from claymore666/docs/205-readme-restructure",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T22:01:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4910e566ab7a5873d860243ea8e6f70eae67cdcd",
          "body": "The README had grown to ~300 lines doing four jobs at once (marketing,\nquick start, deep how-to, internals). Split it into a ~150-line landing\npage that routes to docs/:\n\n- New docs/bridge-mode.md: the manual host-bridge setup + network/\n  container walkthrough moved out of the README.\n- New docs/in\n[…]\nserved (linked from\nSECURITY.md, GOVERNANCE.md, RELEASE_NOTES.md, reference.md, and the\nOpenSSF badge/Scorecard evidence). All internal links verified.\n\nPrecursor to #133 (Pages docs site).\n\nRefs #205",
          "is_bot": false,
          "headline": "docs: restructure README into a concise landing page + docs/ split",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T21:43:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "46fe075b6a14875078e9bb976bed4d31537ceb29",
          "body": "tests: unit-level error-path coverage via docker + netlink seams (#206)",
          "is_bot": false,
          "headline": "Merge pull request #220 from claymore666/tests/206-coverage-ratchet",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T21:38:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dfbc2b6fd4cce96932be4233f209221f0c6f205c",
          "body": "Lock in the error-path coverage from this PR. Merged unit+integration\non the Coverage workflow measured pkg/plugin 82.3% (restoring the\npre-v1.0.0 ~82 level the v1.0.0 decision intended to ratchet back to)\nand pkg/util 88.7%. Floors set with epsilon headroom.\n\npkg/udhcpc and cmd/net-dhcp are left at their floors: their small bumps\nthis run are integration run-to-run variance, not earned by this PR.\n\nRefs #206",
          "is_bot": false,
          "headline": "ci: ratchet coverage floors — pkg/plugin 77.5->82.0, pkg/util 87.0->88.0",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T18:11:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1f83b832a39aad3102cdafc508a43bae4df6edec",
          "body": "…quire arm\n\nPush the docker/netlink seams further now that they're in place:\n\n- findLinkByMAC takes a linkLister interface (*netlink.Handle satisfies\n  it), so the MAC-walk logic is unit-tested for list-error/no-match/found\n  without a live netns handle.\n- addRoutes: add v6 default-gateway, skip_rou\n[…]\nl-route-skip and\n  on-link (no-gateway) cases -> 100%.\n- reacquireEndpoint: cover the docker MAC-lookup error arm via the fake\n  client; the CreateEndpoint replay stays integration-covered.\n\nRefs #206",
          "is_bot": false,
          "headline": "tests: extend seam coverage — findLinkByMAC, addRoutes branches, reac…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T17:50:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c57f3e5256998e33220a1e812f9eecccaa8b2aea",
          "body": "Introduce two narrow test seams so the failure arms that previously\nonly ran (or never ran) under integration become unit-testable:\n\n- dockerClient interface (Close/ContainerInspect/NetworkInspect/\n  NetworkList) replaces the concrete *client.Client on Plugin and\n  dhcpManager; util.AwaitContainerIn\n[…]\nerver/non-error log classes.\n\nNo behavioural change to production code — each seam var is the netlink\nfunction it replaces, and the concrete docker client satisfies the new\ninterface as-is.\n\nRefs #206",
          "is_bot": false,
          "headline": "tests: add unit-level error-path coverage via docker + netlink seams",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T17:38:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0730c6d27c3ce5b764c5cfe5d3237163a134d63a",
          "body": "docs: governance, code of conduct, security assurance (OpenSSF silver)",
          "is_bot": false,
          "headline": "Merge pull request #217 from claymore666/docs/silver-governance-coc",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T17:02:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ef45cd93d2bea507eba6a0bbb287aedf108ba88b",
          "body": "Adds project-oversight and security documentation for OpenSSF Best\nPractices silver:\n- GOVERNANCE.md: maintainer model, roles/responsibilities, decision\n  process, path to additional maintainers.\n- CODE_OF_CONDUCT.md: adopts Contributor Covenant 2.1 by reference with\n  a conduct-report contact.\n- SE\n[…]\nurance case (goals, threats,\n  mitigations, residual risk).\n\nHonest note: silver's access_continuity (MUST) and bus_factor remain\nunmet while solo-maintained; these address the documentation criteria.",
          "is_bot": false,
          "headline": "docs: add governance, code of conduct, security assurance case",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T15:13:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8ced2aff606fc270dbc666abade79dba759597b7",
          "body": "Release v1.1.1",
          "is_bot": false,
          "headline": "Merge pull request #211 from claymore666/dev",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T14:51:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "26513c7b329ecfc26320b63e0bedf9566195a086",
          "body": "Bump install/usage pins v1.1.0 -> v1.1.1 in README and docs (historical\n'v1.1.0 onward'/'v1.1.0+' signing references left intact), and add the\nv1.1.1 RELEASE_NOTES section (compliance/hygiene release, no functional\nplugin changes).",
          "is_bot": false,
          "headline": "docs: v1.1.1 release prep — bump install pins, add RELEASE_NOTES (#210)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T14:19:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f9ef48aac0608755c5378ab9deae2dd182a3d9e5",
          "body": "New step 11: after the dev fast-forward, delete the release branch and\nsweep for any other branch already merged into dev. Notes that\nauto-delete-on-merge (now enabled) covers PR head branches, and that\nopen-PR / Dependabot / upstream-remote branches are left alone.",
          "is_bot": false,
          "headline": "docs: add post-release branch-prune step to runbook (#209)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T13:54:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6339488d9eade5dd1948273e52f2357fdcfa9d0d",
          "body": "Project earned the OpenSSF Best Practices passing badge\n(bestpractices.dev project 13229). Add it to the README badge row;\nalso feeds the Scorecard CII-Best-Practices check.",
          "is_bot": false,
          "headline": "docs: add OpenSSF Best Practices passing badge (#204)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T13:38:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dbdb1dc8e1cd806a8901c05656ebe58a0032196f",
          "body": "* docs: add Contributing section to README\n\nDocuments how to interact (issues), how to contribute (PRs against dev +\nrequired CI checks + tests-with-changes policy), and points to SECURITY.md\nfor vulnerability reports. Satisfies the human-readable interaction/\ncontribution documentation expected by \n[…]\niccheck, plus\nshellcheck/actionlint) and the tests/green-CI requirements, so the\ncontribution requirements are documented for contributors (OpenSSF Best\nPractices contribution_requirements criterion).",
          "is_bot": false,
          "headline": "docs: add Contributing section to README (#200)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T13:38:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "265d6c286c728e7ed648b3571804f1aa22c72454",
          "body": "Adds GitHub issue forms (bug report, feature request), an ISSUE_TEMPLATE\nconfig that disables blank issues and links the private security-advisory\nprocess, and a PR template with a contributor checklist (targets dev,\ntests added, docs updated, no secrets). Aligns the contribution surface\nwith OpenSSF Best Practices report/contribution criteria.",
          "is_bot": false,
          "headline": "ci: add issue forms and PR template (#202)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T13:32:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "865e62c5b6bd24da62c0882823cb1fd9bef7f919",
          "body": "The default GITHUB_TOKEN cannot read branch-protection settings, so the\nBranch-Protection check scored -1 (inconclusive) despite protection being\nconfigured. Wire a single-repo, read-only fine-grained PAT (Administration:\nread) via the SCORECARD_TOKEN secret as scorecard-action's repo_token.",
          "is_bot": false,
          "headline": "ci: give Scorecard a read-only admin token for Branch-Protection (#198)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T13:32:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a7a214033b85f43f9317ebdf95bb78d29956979d",
          "body": "Release v1.1.0",
          "is_bot": false,
          "headline": "Merge pull request #192 from claymore666/dev",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T10:44:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0b821e114d2da7c184f90ad25eb5dfd136d4123c",
          "body": "…isories\n\nci: allowlist unreachable docker/docker advisories in dependency-review (#193)",
          "is_bot": false,
          "headline": "Merge pull request #194 from claymore666/ci/193-dep-review-docker-adv…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T02:03:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c7feef57c6e86b7917f33b445b3e5f6dc4261b33",
          "body": "…endency-review (#193)\n\ndependency-review flags three high docker/docker advisories on the\ndev->main release PR (the go-deps bump moves the module 28.4.0->28.5.2).\nAll three are daemon-side / docker-cp-side Moby paths; this plugin uses\nthe module only as a client (NetworkList/NetworkInspect/Containe\n[…]\nor the three GHSAs, mirroring vuln-allowlist.txt\n(justification + 2026-06-14 review date, reachability as arbiter).\nDocument the two newer advisories in RELEASE_NOTES acknowledged-findings.\n\nRefs #193",
          "is_bot": false,
          "headline": "ci: allowlist unreachable daemon-side docker/docker advisories in dep…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T01:46:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2c827da5ef6f9294bfafb39061c9d685b9461f41",
          "body": "docs: v1.1.0 release prep (version bumps, verification docs, release notes)",
          "is_bot": false,
          "headline": "Merge pull request #191 from claymore666/release/v1.1.0",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T01:36:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c0cba7cc1c4bdb6b03f83366f388bcf52bf964e4",
          "body": "…NOTES",
          "is_bot": false,
          "headline": "docs: prep v1.1.0 — bump image tags, add Verifying releases, RELEASE_…",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T01:19:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99745e2fa458fda5d9a9a5e2f6498e7e3f6b8ee0",
          "body": "ci: fix check-apk-pins.sh trailing-colon false positive + self-test (#169)",
          "is_bot": false,
          "headline": "Merge pull request #190 from claymore666/fix/169-apk-pin",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T01:15:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "acf6919f73f9d4d0c05dc8cea182f85fbea9d12c",
          "body": "apk policy prints the candidate version with a trailing colon\n(1.36.1-r31:), which the checker compared verbatim against the pin\n(1.36.1-r31) — so a current pin was always reported as an upgrade\ncandidate. Strip the trailing colon before comparing.\n\nAdd scripts/test-check-apk-pins.sh (table-driven, \n[…]\nr) and\nwire it into the gate self-tests. It was the only gate script without a\nself-test — the gap that let this ship. The regression case fails on the\nunfixed script and passes on the fix.\n\nRefs #169",
          "is_bot": false,
          "headline": "ci: fix check-apk-pins.sh trailing-colon false positive + add self-test",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T00:57:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2695a24f2d3593d9b3cbc2465998186ee4b9db7c",
          "body": "build: Go 1.25.9 → 1.26.4 (#177 step 2 of 2)",
          "is_bot": false,
          "headline": "Merge pull request #189 from claymore666/ci/177-go126-gomod",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T00:47:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "67f9f7486839eb251411b2d44131e7a0b7793462",
          "body": "Source side of the Go 1.26 bump. The runner pool is already on Go 1.26\n(runner image #187/#188, orchestrator pulled), so this PR's integration\nruns on the 1.26 pool.\n\n- go.mod: go 1.26.4\n- test.yaml + coverage.yml: go-version 1.25 -> 1.26 (5 pins)\n- Dockerfile builder: golang:1.25-alpine -> golang:1\n[…]\n, so they follow\nautomatically. Validated locally on go1.26.4: go mod tidy -diff clean,\nbuild, vet, race tests, and staticcheck v0.7.0 all pass (staticcheck\nsupports 1.26 — no bump needed).\n\nRefs #177",
          "is_bot": false,
          "headline": "build: bump Go 1.25.9 -> 1.26.4 (#177 step 2 of 2)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T00:28:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fd55ff7f5d27eff4e550b3c062469da2e1cad83f",
          "body": "ci(runner-image): selftest checks golang:1.26 seed (#177 step 1 fix)",
          "is_bot": false,
          "headline": "Merge pull request #188 from claymore666/ci/177-selftest-go126",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-14T00:06:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7f17990fa51141132f71af00df37e7b64efb3c06",
          "body": "#187 bumped the seeded golang base to 1.26 in the Dockerfile but left\nthe entrypoint selftest asserting golang:1.25-alpine, so the Go-1.26\nimage failed its own selftest (\"golang seed missing\") and — correctly —\ndid not publish. Point both seed checks at golang:1.26-alpine.\n\nThe selftest gate working as intended: a mismatched image never reached\n:latest, so the pool was untouched.\n\nRefs #177",
          "is_bot": false,
          "headline": "ci(runner-image): selftest checks golang:1.26 seed (follow-up to #187)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T23:48:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c0917c86e937a6be6d13d512429dd84a1c9a6c59",
          "body": "ci(runner-image): bump baked Go 1.25.9 → 1.26.4 (#177 step 1 of 2)",
          "is_bot": false,
          "headline": "Merge pull request #187 from claymore666/ci/177-runner-go126",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T23:46:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5bb38dbf2d00b5ffcdf26d4cd877e86a21de4f27",
          "body": "First half of the Go 1.26 bump. The dhcp-ci runner image bakes the Go\ntoolchain (integration skips setup-go) and seeds the golang base for the\nnested plugin build, so the pool must be on 1.26 BEFORE go.mod is bumped\n— otherwise the go.mod bump PR runs its own integration on a 1.25 pool.\n\n- ARG GO_VE\n[…]\non still builds on the\ncurrent 1.25 pool. After merge, runner-image.yml republishes :latest;\nthe orchestrator must pull it and a job must pass on 1.26 before the\ngo.mod bump (step 2) opens.\n\nRefs #177",
          "is_bot": false,
          "headline": "ci(runner-image): bump baked Go 1.25.9 -> 1.26.4 (#177 step 1)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T23:18:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "51c77d28520206fd8fd96722d468ddbf7db23d7c",
          "body": "ci: CodeQL advanced setup for Go + actions (#170)",
          "is_bot": false,
          "headline": "Merge pull request #179 from claymore666/ci/170-codeql-advanced",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T23:09:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "600200c4c62c0bf5ae71dc9e807d80848c5a039d",
          "body": "ci: release signing tier — images + provenance + SBOM + signed tags (#173, #174, #175)",
          "is_bot": false,
          "headline": "Merge pull request #186 from claymore666/ci/173-174-supply-chain",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T22:37:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "da8087c0cf28ee8d40fa837258b253eb12307330",
          "body": "The first cut used build-mode: none, but CodeQL 2.25.x rejects that for\nGo (\"Go does not support the none build mode\"). autobuild is the other\noption but it runs make -> docker export -> root-owned plugin/rootfs\nfiles that break CodeQL DB bundling. So use build-mode: manual with a\nplain `go build ./...` (+ setup-go from go.mod) — CodeQL traces the\ncompile, no make/docker involved.\n\nRefs #170",
          "is_bot": false,
          "headline": "ci: CodeQL Go uses build-mode manual (none is unsupported for Go)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T22:29:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b7fcd59b2dd90409b1e0983bb12d7aca182bbc91",
          "body": "The primary language (Go) was unscanned by CodeQL — default setup ran\nonly on actions + a phantom python language. Default setup also cannot\nanalyze this repo's Go: its autobuild invokes make, whose default\ntarget builds the plugin rootfs via docker export and leaves root-owned\nfiles (plugin/rootfs/\n[…]\n export — covering all source files, and keeps the\naction SHA-pinned with the config in version control like the other\nworkflows. Default setup has been disabled so the two do not conflict.\n\nRefs #170",
          "is_bot": false,
          "headline": "ci: add CodeQL advanced setup for Go + actions",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T22:29:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "107a03f2454bb005b04fda59e026ea435bbffd3e",
          "body": "ci: Dependency Review action to gate PRs on new vulnerable deps (#171)",
          "is_bot": false,
          "headline": "Merge pull request #180 from claymore666/ci/171-dependency-review",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T22:27:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a3e02f96c5c86650b24d76e59c66f55b6c225fe8",
          "body": "ci: bump actionlint v1.7.7 → v1.7.12 (part of #177)",
          "is_bot": false,
          "headline": "Merge pull request #185 from claymore666/ci/177-actionlint-bump",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T22:27:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2cb89d79da0ae5af23e415e6dd01cac0efe66ad5",
          "body": "Switch the tag commands (rc + real) to `git tag -s` so release tags\nshow Verified, and document `git tag -v` confirmation. The dev box\nalready has tag.gpgsign=true (verified commits were set up separately);\nthis makes the runbook explicit so it holds from any checkout. Also\nrefresh the expected-step\n[…]\nhe new image-signing / SBOM /\nprovenance steps.\n\nVerified commits (the other half of #175) are already live; branch-\nprotection \"require signed commits\" enforcement stays optional/deferred.\n\nRefs #175",
          "is_bot": false,
          "headline": "docs: sign release tags in the runbook (#175)",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T21:40:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "823608b73ddb06cfb242cb157660b6b87f36d218",
          "body": "Extends the release supply chain (builds on #163, which signs the\nrelease tarball/checksums):\n\n- #173 image signing: resolve each published plugin's registry digest\n  (docker buildx imagetools inspect reads it despite the plugin media\n  type) and cosign-sign it keylessly on GHCR (and Docker Hub when\n[…]\n end-to-end at the next vX.Y.Z-rcN dry-run (per #163). Locally\nvalidated: actionlint+shellcheck clean, YAML parses, and plugin-digest\nextraction confirmed against the published image.\n\nRefs #173, #174",
          "is_bot": false,
          "headline": "ci: sign release images, attest provenance, attach SBOM",
          "author_name": "Chris",
          "author_login": "claymore666",
          "committed_at": "2026-06-13T21:39:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        }
      ],
      "releases_count": 28,
      "commits_last_year": 323,
      "latest_release_at": "2026-07-06T00:55:50Z",
      "latest_release_tag": "v1.3.3",
      "releases_from_tags": false,
      "days_since_last_push": 2,
      "active_weeks_last_year": 5,
      "days_since_latest_release": 16,
      "mean_days_between_releases": 2.2
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 85,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/devplayer0/docker-net-dhcp",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": false,
          "registry_url": "https://pkg.go.dev/github.com/devplayer0/docker-net-dhcp",
          "is_deprecated": false,
          "latest_version": "v0.1.4",
          "repository_url": "https://github.com/devplayer0/docker-net-dhcp",
          "versions_count": 5,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2021-07-15T17:57:10Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 1833
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 9,
      "watchers": 1,
      "fork_history": {
        "days": [
          {
            "date": "2026-07-09",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 17
    },
    "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": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 41827,
      "source_files_sampled": 86,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "docs/requirements.txt",
        "go.mod",
        "scripts/requirements.txt"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "github.com/docker/docker",
            "direct": true,
            "version": "v28.5.2+incompatible",
            "severity": "high",
            "ecosystem": "go",
            "cvss_score": 8.8,
            "advisory_ids": [
              "GHSA-pxq6-2prw-chj9",
              "GHSA-rg2x-37c3-w2rh",
              "GHSA-vp62-88p7-qqf5",
              "GHSA-x744-4wpc-v9h2",
              "GHSA-x86f-5xw2-fm2r",
              "GO-2026-4883",
              "GO-2026-4887",
              "GO-2026-5617",
              "GO-2026-5668",
              "GO-2026-5746"
            ],
            "fixed_version": "29.3.1",
            "advisory_count": 10,
            "oldest_advisory_days": 117
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "high": 1
        },
        "advisory_count": 10,
        "affected_count": 1,
        "assessed_count": 65,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 2,
        "direct_affected_count": 1
      },
      "ecosystems": [
        "go",
        "pypi"
      ],
      "dependencies": [
        {
          "name": "github.com/docker/docker",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v28.5.2+incompatible"
        },
        {
          "name": "github.com/gorilla/handlers",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.5.2"
        },
        {
          "name": "github.com/mitchellh/mapstructure",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.5.0"
        },
        {
          "name": "github.com/sirupsen/logrus",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.9.4"
        },
        {
          "name": "github.com/vishvananda/netlink",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.3.1"
        },
        {
          "name": "github.com/vishvananda/netns",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.5"
        },
        {
          "name": "golang.org/x/sys",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.46.0"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "github.com/docker/docker",
            "direct": true,
            "version": "v28.5.2+incompatible",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gorilla/handlers",
            "direct": true,
            "version": "v1.5.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/mitchellh/mapstructure",
            "direct": true,
            "version": "v1.5.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/sirupsen/logrus",
            "direct": true,
            "version": "v1.9.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/vishvananda/netlink",
            "direct": true,
            "version": "v1.3.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/vishvananda/netns",
            "direct": true,
            "version": "v0.0.5",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/sys",
            "direct": true,
            "version": "v0.46.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/cespare/xxhash/v2",
            "direct": false,
            "version": "v2.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/containerd/errdefs",
            "direct": false,
            "version": "v1.0.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/containerd/errdefs/pkg",
            "direct": false,
            "version": "v0.3.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/containerd/log",
            "direct": false,
            "version": "v0.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/distribution/reference",
            "direct": false,
            "version": "v0.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/docker/go-connections",
            "direct": false,
            "version": "v0.7.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/docker/go-units",
            "direct": false,
            "version": "v0.5.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/felixge/httpsnoop",
            "direct": false,
            "version": "v1.0.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-logr/logr",
            "direct": false,
            "version": "v1.4.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-logr/stdr",
            "direct": false,
            "version": "v1.2.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/microsoft/go-winio",
            "direct": false,
            "version": "v0.6.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/docker-image-spec",
            "direct": false,
            "version": "v1.3.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/sys/atomicwriter",
            "direct": false,
            "version": "v0.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/moby/term",
            "direct": false,
            "version": "v0.5.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/morikuni/aec",
            "direct": false,
            "version": "v1.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/opencontainers/go-digest",
            "direct": false,
            "version": "v1.0.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/opencontainers/image-spec",
            "direct": false,
            "version": "v1.1.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/pkg/errors",
            "direct": false,
            "version": "v0.9.1",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/auto/sdk",
            "direct": false,
            "version": "v1.2.1",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
            "direct": false,
            "version": "v0.68.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel",
            "direct": false,
            "version": "v1.43.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp",
            "direct": false,
            "version": "v1.43.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel/metric",
            "direct": false,
            "version": "v1.43.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel/trace",
            "direct": false,
            "version": "v1.43.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/time",
            "direct": false,
            "version": "v0.15.0",
            "ecosystem": "go"
          },
          {
            "name": "gotest.tools/v3",
            "direct": false,
            "version": "v3.5.2",
            "ecosystem": "go"
          },
          {
            "name": "babel",
            "direct": false,
            "version": "2.18.0",
            "ecosystem": "pypi"
          },
          {
            "name": "backrefs",
            "direct": false,
            "version": "7.0",
            "ecosystem": "pypi"
          },
          {
            "name": "certifi",
            "direct": false,
            "version": "2026.5.20",
            "ecosystem": "pypi"
          },
          {
            "name": "charset-normalizer",
            "direct": false,
            "version": "3.4.7",
            "ecosystem": "pypi"
          },
          {
            "name": "click",
            "direct": false,
            "version": "8.4.1",
            "ecosystem": "pypi"
          },
          {
            "name": "colorama",
            "direct": false,
            "version": "0.4.6",
            "ecosystem": "pypi"
          },
          {
            "name": "docker-image-py",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "ghp-import",
            "direct": false,
            "version": "2.1.0",
            "ecosystem": "pypi"
          },
          {
            "name": "idna",
            "direct": false,
            "version": "3.18",
            "ecosystem": "pypi"
          },
          {
            "name": "jinja2",
            "direct": false,
            "version": "3.1.6",
            "ecosystem": "pypi"
          },
          {
            "name": "markdown",
            "direct": false,
            "version": "3.10.2",
            "ecosystem": "pypi"
          },
          {
            "name": "markupsafe",
            "direct": false,
            "version": "3.0.3",
            "ecosystem": "pypi"
          },
          {
            "name": "mergedeep",
            "direct": false,
            "version": "1.3.4",
            "ecosystem": "pypi"
          },
          {
            "name": "mike",
            "direct": false,
            "version": "2.2.0",
            "ecosystem": "pypi"
          },
          {
            "name": "mkdocs",
            "direct": false,
            "version": "1.6.1",
            "ecosystem": "pypi"
          },
          {
            "name": "mkdocs-get-deps",
            "direct": false,
            "version": "0.2.2",
            "ecosystem": "pypi"
          },
          {
            "name": "mkdocs-material",
            "direct": false,
            "version": "9.7.6",
            "ecosystem": "pypi"
          },
          {
            "name": "mkdocs-material-extensions",
            "direct": false,
            "version": "1.3.1",
            "ecosystem": "pypi"
          },
          {
            "name": "packaging",
            "direct": false,
            "version": "26.2",
            "ecosystem": "pypi"
          },
          {
            "name": "paginate",
            "direct": false,
            "version": "0.5.7",
            "ecosystem": "pypi"
          },
          {
            "name": "pathspec",
            "direct": false,
            "version": "1.1.1",
            "ecosystem": "pypi"
          },
          {
            "name": "platformdirs",
            "direct": false,
            "version": "4.10.0",
            "ecosystem": "pypi"
          },
          {
            "name": "pygments",
            "direct": false,
            "version": "2.20.0",
            "ecosystem": "pypi"
          },
          {
            "name": "pymdown-extensions",
            "direct": false,
            "version": "10.21.3",
            "ecosystem": "pypi"
          },
          {
            "name": "pyparsing",
            "direct": false,
            "version": "3.3.2",
            "ecosystem": "pypi"
          },
          {
            "name": "python-dateutil",
            "direct": false,
            "version": "2.9.0.post0",
            "ecosystem": "pypi"
          },
          {
            "name": "python-dxf",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pyyaml",
            "direct": false,
            "version": "6.0.3",
            "ecosystem": "pypi"
          },
          {
            "name": "pyyaml-env-tag",
            "direct": false,
            "version": "1.1",
            "ecosystem": "pypi"
          },
          {
            "name": "requests",
            "direct": false,
            "version": "2.34.2",
            "ecosystem": "pypi"
          },
          {
            "name": "six",
            "direct": false,
            "version": "1.17.0",
            "ecosystem": "pypi"
          },
          {
            "name": "urllib3",
            "direct": false,
            "version": "2.7.0",
            "ecosystem": "pypi"
          },
          {
            "name": "verspec",
            "direct": false,
            "version": "0.1.0",
            "ecosystem": "pypi"
          },
          {
            "name": "watchdog",
            "direct": false,
            "version": "6.0.0",
            "ecosystem": "pypi"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 67,
        "direct_count": 7,
        "indirect_count": 60
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 5,
        "merged_prs": 147,
        "open_issues": 12,
        "closed_ratio": 0.928,
        "closed_issues": 155,
        "closed_unmerged_prs": 9
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "claymore666",
          "commits": 170,
          "avatar_url": "https://avatars.githubusercontent.com/u/11246284?v=4"
        },
        {
          "type": "User",
          "login": "devplayer0",
          "commits": 86,
          "avatar_url": "https://avatars.githubusercontent.com/u/1427254?v=4"
        },
        {
          "type": "User",
          "login": "200success",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/7194866?v=4"
        }
      ],
      "contributors_sampled": 3,
      "top_contributor_share": 0.661
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "apk-pin-check.yml",
        "codeql.yml",
        "coverage.yml",
        "dependency-review.yml",
        "integration-hosted.yml",
        "integration.yml",
        "pages.yml",
        "release.yml",
        "runner-image.yml",
        "scorecard.yml",
        "test.yaml",
        "trivy.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": 3,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "28 out of 28 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": 5,
            "reason": "badge detected: Passing",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/25 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": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 10,
            "reason": "project is 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": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 10,
            "reason": "all dependencies are pinned",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 10,
            "reason": "SAST tool is run on all commits",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 8,
            "reason": "5 out of the last 5 releases have a total of 5 signed artifacts.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 5,
            "reason": "5 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "c2baff17ebabee144c0d182945c58a22ba84639e",
        "ran_at": "2026-07-22T19:24:55Z",
        "aggregate_score": 7.5,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": true,
      "has_security_policy": true,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-22T09:55:49Z",
      "oldest_open_prs": [
        {
          "number": 221,
          "created_at": "2026-06-14T17:53:11Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 325,
          "created_at": "2026-07-09T05:22:21Z",
          "last_comment_at": "2026-07-17T15:15:19Z",
          "last_comment_author": "claymore666"
        },
        {
          "number": 326,
          "created_at": "2026-07-12T23:04:55Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 327,
          "created_at": "2026-07-12T23:04:56Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 329,
          "created_at": "2026-07-19T23:06:05Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-06T00:50:36Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 110,
          "created_at": "2026-05-05T13:35:25Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 111,
          "created_at": "2026-05-05T13:35:25Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 125,
          "created_at": "2026-06-02T18:17:52Z",
          "last_comment_at": "2026-06-13T19:35:43Z",
          "last_comment_author": "claymore666"
        },
        {
          "number": 178,
          "created_at": "2026-06-13T20:01:35Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 214,
          "created_at": "2026-06-14T15:07:44Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 218,
          "created_at": "2026-06-14T15:28:35Z",
          "last_comment_at": "2026-06-14T23:10:39Z",
          "last_comment_author": "claymore666"
        },
        {
          "number": 219,
          "created_at": "2026-06-14T17:07:45Z",
          "last_comment_at": "2026-07-04T01:10:31Z",
          "last_comment_author": "claymore666"
        },
        {
          "number": 248,
          "created_at": "2026-06-15T14:40:16Z",
          "last_comment_at": "2026-07-04T21:54:43Z",
          "last_comment_author": "claymore666"
        },
        {
          "number": 275,
          "created_at": "2026-06-16T16:31:53Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 278,
          "created_at": "2026-06-16T17:23:38Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 279,
          "created_at": "2026-06-16T17:29:04Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 324,
          "created_at": "2026-07-06T00:51:20Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/claymore666/docker-net-dhcp",
    "host": "github.com",
    "name": "docker-net-dhcp",
    "owner": "claymore666"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 62,
      "inputs": {
        "security": 71,
        "vitality": 74,
        "community": 42,
        "governance": 51,
        "engineering": 71
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 74,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 58,
            "inputs": {
              "commits_last_year": 323,
              "human_commit_share": 0.97,
              "days_since_last_push": 2,
              "active_weeks_last_year": 5
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 2 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 2
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "5/52 weeks with commits",
                "points": 3.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "323 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 323
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 98,
            "inputs": {
              "releases_count": 28,
              "latest_release_tag": "v1.3.3",
              "releases_from_tags": false,
              "days_since_latest_release": 16,
              "mean_days_between_releases": 2.2
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "28 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 28
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 16 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 16
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~2.2 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 2.2
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "5 out of the last 5 releases have a total of 5 signed artifacts.",
                "points": 8,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 42,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 15,
            "inputs": {
              "forks": 1,
              "stars": 9,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "9 stars",
                "points": 14.6,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 9
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 72,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": true,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (GPL-3.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "GPL-3.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 13.5,
                "status": "met",
                "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": 6.3,
                "status": "met",
                "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": 51,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 31,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 3,
              "top_contributor_share": 0.661
            },
            "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 66% of commits",
                "points": 7.6,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 66
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "3 contributors",
                "points": 4.1,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 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": 79,
            "inputs": {
              "merged_prs": 147,
              "open_issues": 12,
              "closed_issues": 155,
              "issue_closed_ratio": 0.928,
              "closed_unmerged_prs": 9
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "93% of issues closed",
                "points": 43.4,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 93
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "147/156 decided PRs merged",
                "points": 36,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 147,
                      "decided": 156
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/25 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 46,
            "inputs": {
              "followers": 4,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "claymore666",
              "public_repos": 23,
              "account_age_days": 4162
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "4 followers of claymore666",
                "points": 5,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 4,
                      "login": "claymore666"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "23 public repos, account ~11 yr old",
                "points": 22.1,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 23
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 11
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 71,
        "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": "12 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 12
                    }
                  }
                ],
                "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": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": 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": "good",
        "name": "Security",
        "value": 71,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "good",
            "name": "Security posture",
            "note": null,
            "notes": [],
            "value": 74,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 18,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 0,
              "scorecard_aggregate": 7.5
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "28 out of 28 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": "badge detected: Passing",
                "points": 1.2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/25 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": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is fuzzed",
                "points": 5,
                "status": "met",
                "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": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "all dependencies are pinned",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is run on all commits",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "5 out of the last 5 releases have a total of 5 signed artifacts.",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "5 existing vulnerabilities detected",
                "points": 3.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "moderate",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories. Remaining weights renormalized. Matched 65 resolved dependencies against OSV; 2 could not be assessed (no resolved version, an unsupported ecosystem, or beyond the reported package list). This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 65
                }
              },
              {
                "code": "advisories_unassessed",
                "params": {
                  "count": 2
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 58,
            "inputs": {
              "source": "osv",
              "advisories": 10,
              "affected_packages": 1,
              "assessed_packages": 65,
              "unassessed_packages": 2,
              "affected_by_severity": "high 1",
              "direct_affected_packages": 1
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "1 affected: github.com/docker/docker v28.5.2+incompatible (high 8.8)",
                "points": 10.4,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "github.com/docker/docker v28.5.2+incompatible (high 8.8)"
                    }
                  }
                ],
                "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": "1 advisory-carrying package(s) unaddressed past 90 days; oldest published 117 days ago",
                "points": 32.8,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_stale",
                    "params": {
                      "days": 90,
                      "count": 1,
                      "oldest": 117
                    }
                  }
                ],
                "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": 65,
              "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": 5
            },
            "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": "moderate",
        "name": "AI Readiness",
        "value": 69,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "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": "97 of 97 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 97,
                      "sampled": 97
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 79,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0.03
            },
            "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": "Dockerfile, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "3 of the last 100 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 3,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "all dependencies are pinned",
                "points": 10,
                "status": "met",
                "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": 41827,
              "source_files_sampled": 86,
              "oversized_source_files": 0
            },
            "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": "0/86 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 86,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "go package 'github.com/devplayer0/docker-net-dhcp' points at a different repository (https://github.com/devplayer0/docker-net-dhcp); excluded from ecosystem scoring"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-22T19:25:12.467627Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/c/claymore666/docker-net-dhcp.svg",
  "full_name": "claymore666/docker-net-dhcp",
  "license_state": "standard",
  "license_spdx": "GPL-3.0"
}

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

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

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