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

step-security / dev-machine-guard

Scan your dev machine for AI agents, MCP servers, IDE extensions, and suspicious packages - in seconds.

GoApache-2.0★ 169 星标⑂ 23 复刻始于 2026年3月在 GitHub 上查看 ↗

step-security/dev-machine-guard 的健康指数为 100 分中的 77 分,处于「良好」区间。 其得分最高的类别是Vitality(85/100),最低的是Sustainability & Governance(70/100)。 最近一次更新在 2 天前。 近期的大部分工作由 2 位贡献者完成。

77
总分 / 100
良好

软件健康指数

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

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

评分画像

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

所有权

251 关注者497 个公开仓库始于 2021年8月

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布
Gogithub.com/step-security/dev-machine-guardv1.14.0-189 天前

按类别列示的指标

活力

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

85优秀 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 2 天前
13.2/36提交节奏 — 52 周中有 19 周有提交
18/18提交量 — 最近一年 513 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year513
human_commit_share1
days_since_last_push2
active_weeks_last_year19

发布纪律

98优秀
评分方式
27/27有发布版本 — 已发布 18 个发布版本
36/36发布时效 — 最近一次发布版本于 9 天前
27/27发布节奏 — 约每 8.8 天发布一次
8/10OpenSSF Scorecard:Signed-Releases — 5 out of the last 5 releases have a total of 5 signed artifacts.
所用输入
releases_count18
latest_release_tagv1.14.0
releases_from_tags
days_since_latest_release9
mean_days_between_releases8.8

社区与采用

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

70良好 · 占总体的 18%
评分方式
36.1/60星标 — 169 个星标
11.2/25复刻 — 23 个复刻
3.3/15关注者 — 5 位关注者
所用输入
forks23
stars169
watchers5
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

92优秀
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(Apache-2.0)
18/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

可持续性与治理

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

70良好 · 占总体的 24%
评分方式
25.2/54巴士系数 — 2 位贡献者贡献了半数提交
13.9/22.5提交分布 — 头号贡献者编写了 38% 的提交
9.5/13.5贡献者广度 — 7 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 3 contributing companies or organizations -- score normalized to 10
所用输入
bus_factor2
contributors_sampled7
top_contributor_share0.384
评分方式
10.2/46.8议题解决 — 22% 的议题已关闭
32.8/38.3PR 接受 — 已裁定的 PR 中 121/141 已合并
15/15OpenSSF Scorecard:Code-Review — all changesets reviewed
所用输入
merged_prs121
open_issues25
closed_issues7
issue_closed_ratio0.219
closed_unmerged_prs20
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
17.3/25所有者影响力 — step-security 有 251 位关注者
22.9/25既往记录 — 497 个公开仓库,账户约 4 年
所用输入
followers251
owner_typeOrganization
is_verified
owner_loginstep-security
public_repos497
account_age_days1,811
评分方式
25/25已发布且可解析 — go 上有 1 个软件包
35/35发布时效 — 最近一次发布于 9 天前
20/20版本历史 — 18 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesgithub.com/step-security/dev-machine-guard
ecosystemsgo
any_deprecated
min_days_since_publish9

工程质量

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

80良好 · 占总体的 20%

工程实践

84良好
评分方式
24/24CI 工作流 — 10 个工作流
24/24存在测试
16/16Linter 配置 — .golangci.yml
0/9.6Pre-commit 钩子
0/6.4.editorconfig
20/20OpenSSF Scorecard:CI-Tests — 9 out of 9 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

安全

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

82良好 · 占总体的 16%

安全态势

82良好
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
6/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 9 out of 9 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
7.5/7.5Code-Review — all changesets reviewed
2.5/2.5Contributors — project has 3 contributing companies or organizations -- score normalized to 10
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
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
6.8/7.5Vulnerabilities — 1 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated18
scorecard_versionv5.5.0
checks_inconclusive0
scorecard_aggregate8.2

AI 就绪度

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

82良好 · 占总体的 0%
评分方式
45/45代理指令 — AGENTS.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 79 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.79
agent_instruction_filesAGENTS.md
agent_instruction_max_bytes42,944
评分方式
18/18一条命令的引导启动 — Makefile
22/22自动化测试
11/11Lint / 格式化配置 — .golangci.yml
11/11静态类型检查 — Go(静态类型)
10/10可复现环境 — lockfile
8/10已体现的代理实践 — 最近 100 次提交中有 4 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
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.04
toolchain_manifestsgo.mod
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — Go(静态类型)
54.7/55可控的文件大小 — 采样的 333 个源文件中有 2 个超过 60KB
所用输入
primary_languageGo
largest_source_bytes70,180
source_files_sampled333
oversized_source_files2

机器可读接口

40存在风险
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
0/20MCP 服务器
40/40可运行示例 — examples
所用输入
example_dirsexamples
has_mcp_signal
api_schema_files

关键数据

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

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

更多细节

Star 与 Fork 历史 0 ★ / 23 ⇿
0Star
23Fork
17发布

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

048121620242322026-032026-052026-07
主版本 0次版本 6修订 11
OpenSSF Scorecard 8.2 / 10
8.2综合

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

10Binary-Artifactsno binaries found in the repo
8Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests9 out of 9 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
10Code-Reviewall changesets reviewed
10Contributorsproject has 3 contributing companies or organizations -- score normalized to 10
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10
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
9Vulnerabilities1 existing vulnerabilities detected
直接依赖 10
注册表软件包版本约束清单文件
Gogolang.org/x/sysv0.33.0go.mod
Gogithub.com/google/shlexv0.0.0-20191202100458-e7afc7fbc510go.mod
Gogithub.com/google/uuidv1.6.0go.mod
Gogithub.com/pelletier/go-toml/v2v2.3.1go.mod
Gogithub.com/tailscale/hujsonv0.0.0-20260302212456-ecc657c15afdgo.mod
Gogithub.com/tidwall/gjsonv1.18.0go.mod
Gogithub.com/tidwall/prettyv1.2.1go.mod
Gogithub.com/tidwall/sjsonv1.2.5go.mod
Gogopkg.in/yaml.v3v3.0.1go.mod
Gohowett.net/plistv1.0.1go.mod
全部依赖 未采集

本报告未能采集到解析后的依赖集合:GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 32313,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Go": 2431022,
        "Shell": 39711,
        "Makefile": 3451,
        "Batchfile": 1362,
        "PowerShell": 7357
      },
      "pushed_at": "2026-07-24T16:47:05Z",
      "created_at": "2026-03-10T07:34:34Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-24T16:52:00Z",
      "description": "Scan your dev machine for AI agents, MCP servers, IDE extensions, and suspicious packages - in seconds.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": "https://www.stepsecurity.io",
      "name": "StepSecurity",
      "type": "Organization",
      "login": "step-security",
      "company": null,
      "location": "United States of America",
      "followers": 251,
      "avatar_url": "https://avatars.githubusercontent.com/u/88700172?v=4",
      "created_at": "2021-08-10T04:28:22Z",
      "is_verified": null,
      "public_repos": 497,
      "account_age_days": 1811
    },
    "license": {
      "state": "standard",
      "spdx_id": "Apache-2.0",
      "raw_spdx": "Apache-2.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v1.14.0",
          "kind": "minor",
          "published_at": "2026-07-17T18:53:26Z"
        },
        {
          "tag": "v1.13.0",
          "kind": "minor",
          "published_at": "2026-07-09T18:52:35Z"
        },
        {
          "tag": "v1.12.0",
          "kind": "minor",
          "published_at": "2026-06-10T20:13:35Z"
        },
        {
          "tag": "v1.11.7",
          "kind": "patch",
          "published_at": "2026-06-01T08:42:33Z"
        },
        {
          "tag": "v1.11.6",
          "kind": "patch",
          "published_at": "2026-05-27T22:29:41Z"
        },
        {
          "tag": "v1.11.5",
          "kind": "patch",
          "published_at": "2026-05-27T20:09:39Z"
        },
        {
          "tag": "v1.11.4",
          "kind": "patch",
          "published_at": "2026-05-26T16:29:24Z"
        },
        {
          "tag": "v1.11.3",
          "kind": "patch",
          "published_at": "2026-05-22T06:51:28Z"
        },
        {
          "tag": "v1.11.1",
          "kind": "patch",
          "published_at": "2026-05-11T05:13:06Z"
        },
        {
          "tag": "v1.11.0",
          "kind": "minor",
          "published_at": "2026-04-29T22:18:08Z"
        },
        {
          "tag": "v1.10.2",
          "kind": "patch",
          "published_at": "2026-04-22T08:40:26Z"
        },
        {
          "tag": "v1.10.1",
          "kind": "patch",
          "published_at": "2026-04-21T17:28:40Z"
        },
        {
          "tag": "v1.10.0",
          "kind": "minor",
          "published_at": "2026-04-20T18:41:17Z"
        },
        {
          "tag": "v1.9.2",
          "kind": "patch",
          "published_at": "2026-04-15T17:52:50Z"
        },
        {
          "tag": "v1.9.1",
          "kind": "patch",
          "published_at": "2026-04-08T20:08:31Z"
        },
        {
          "tag": "v1.9.0",
          "kind": "minor",
          "published_at": "2026-04-03T18:38:08Z"
        },
        {
          "tag": "v1.8.2",
          "kind": "patch",
          "published_at": "2026-03-17T18:23:27Z"
        },
        {
          "tag": "v1.8.1",
          "kind": "patch",
          "published_at": "2026-03-10T07:48:58Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "2cf07e270ae355919a8c48fd41bc315cdbe8ceaf",
          "body": "…pport\n\nfeat(devicepolicy): enforce VS Code private-marketplace URL + add MDM verify-only channel",
          "is_bot": false,
          "headline": "Merge pull request #178 from raysubham/feat/vsc-private-markeplace-su…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-24T16:47:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "707b8aac573ce8e0b4e4d593bdc4c550099acda6",
          "body": "…nical enforcement channel\n\nAddress PR review comments:\n\n- ApplyManaged built the RFC-6902 patch path by raw string concat with the\n  backend-supplied key. RFC 6901-escape the pointer token (~->~0, /->~1) and\n  JSON-encode the path (jsonPointerPath) so an unusual key cannot forge a nested\n  pointer \n[…]\nhe raw string. Resolve and stamp the canonical channel\n  the cycle actually ran -- always \"dmg\" or \"mdm\" (empty/unknown -> \"dmg\") -- so\n  the backend's exact-match gate sees the channel that executed.",
          "is_bot": false,
          "headline": "fix(devicepolicy): harden managed-settings patch keys and report cano…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-24T11:14:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bbc89352eab64394632c411f187beb0a002a9fe6",
          "body": "…xtension policy\n\nEnforcement selects a channel per cycle: \"dmg\" (or \"\") is the write-and-verify\npath; \"mdm\" is verify-only — the agent probes the OS-managed VS Code policy and\nreports what it observed, and never writes, patches, or clears settings.json\n(an external MDM owns the policy).\n\n- ProbeMan\n[…]\nnnels fail safe to the\n  DMG write path.\n- The presence probe (DMG-mode yield) also gates on REG_SZ/REG_MULTI_SZ, so a\n  wrong-typed policy value that VS Code ignores no longer suppresses enforcement.",
          "is_bot": false,
          "headline": "feat(devicepolicy): add MDM verify-only enforcement channel for IDE-e…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-23T21:35:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d935b13f18ebb4ab9e4b059ccfa34573a933d028",
          "body": "… map)\n\nThe run-config policy payload is now a settings map (setting id → compiled value) instead of the bare extensions.allowed object plus a sibling gallery_service_url field; the hash covers the whole map.\n\nenforce and clear are fully driven by the settings map and recorded ownership — no per-key\n[…]\n and a JSON object. Deleted managedKeys/managedGalleryValue; added compactSettings/sortedUnion/sortedKeys.\n\nBreaking run-config wire change (pre-GA): requires agent-api to emit the settings-map shape.",
          "is_bot": false,
          "headline": "refactor(devicepolicy): key run-config policy by setting id (settings…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-23T10:15:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7177bed25ecf0bf8f44f56e031c15a1e60abde5d",
          "body": "…tings\n\nMove the VS Code allowlist's ownership record from the scalar WrittenValue\ninto the WrittenSettings map alongside the gallery URL, so every managed key\nis tracked uniformly by setting id. WrittenValue is now used only by the\nsingle-key (npm) writer; adds omitempty so managed records no longer carry a\ndead written_value field. No behavior change: ownership is read back from the\nsame values the agent writes.",
          "is_bot": false,
          "headline": "refactor(devicepolicy): track all managed-key ownership in WrittenSet…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-22T22:05:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c26420a3d8ce5d91b8b4bc04fa28b8bd4f74306c",
          "body": "Fold an optional extensions.gallery.serviceUrl into the existing\nide_extension#vscode reconciler, written into the user-scope\nsettings.json beside extensions.allowed via one atomic multi-key write.\nThe agent owns both keys: set is authoritative, removal is\nownership-gated (never deletes a user-confi\n[…]\nsions OR\n  ExtensionGalleryServiceUrl (Windows / macOS / Linux)\n\nAdditive and regression-guarded: an allowlist-only policy writes exactly\nas before (byte-identical settings.json and ownership record).",
          "is_bot": false,
          "headline": "feat(devicepolicy): enforce VS Code private marketplace URL",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-22T21:30:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e96ecd31cddad99a0cb1bfe37f93ea1ffb1cffcf",
          "body": "…scan-missing\n\nfix(brew): detect Homebrew installed outside PATH",
          "is_bot": false,
          "headline": "Merge pull request #172 from swarit-stepsecurity/swarit/fix/homebrew-…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-20T05:49:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c3bd6eb46ec15e66a9a28bde50cff376ba442c7f",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/fix/homebrew-scan-missing",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-18T19:41:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3854d8839bc6eb6ac0143b299b354050b8dcf37d",
          "body": "…-multi-at\n\nfix(configaudit): mask full userinfo in malformed multi-@ index URLs",
          "is_bot": false,
          "headline": "Merge pull request #173 from swarit-stepsecurity/swarit/fix/wt/redact…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-18T19:40:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e92bd4769cbbd9d923ffca1e357f1b34120de9e4",
          "body": "- resolveBrewExecutable now uses the resolved absolute path as the command\n  even when found via PATH, so all invocations are PATH-independent.\n- describe-cache version is reduced to its base tag and validated against\n  brewVersionTagPattern, so strings like \"4.3.5-17-g<sha>\" no longer leak\n  into PkgManager.Version.",
          "is_bot": false,
          "headline": "fix(brew): address review — use resolved path, normalize version",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-18T06:59:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "709b2673f25243da5f3238ac2226dcfb90b1bb2c",
          "body": "redactCredsInValue split userinfo at the first `@`, so a user-typed\nvalue with several `user:pass@host` runs concatenated before the real\nhost (e.g. a mangled pip index-url) had everything after the first `@`\ntreated as host and shipped verbatim — leaking the trailing credential,\nin one real case a \n[…]\nng up to its *last* `@`. When the userinfo itself contains an\nextra `@` it's malformed and can't be safely parsed into user/pass, so\nmask the whole run. Well-formed single user:pass@host is unchanged.",
          "is_bot": false,
          "headline": "fix(configaudit): mask full userinfo in malformed multi-@ index URLs",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-18T05:04:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c8c2b6d937eafbff442bb59d246e75ef59f1b359",
          "body": "Resolve the brew executable from standard install locations (/opt/homebrew,\n/usr/local, /home/linuxbrew) when it is not on PATH, and read the version from\nthe Homebrew git repo metadata (describe-cache / packed-refs) instead of\nshelling out to `brew --version`. Detection and formula/cask listing now work\nfor scans run without the user's interactive PATH.",
          "is_bot": false,
          "headline": "fix(brew): detect Homebrew installed outside PATH",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-17T18:29:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2652d20dfd0593874e43b08d08450569786959d9",
          "body": "…er-1.14.0\n\nchore(release): update to 1.14.0",
          "is_bot": false,
          "headline": "Merge pull request #171 from swarit-stepsecurity/swarit/chore/wt/up-v…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-17T14:37:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "94ff75765ed86738e6eaff2a79b67aaaeb82d40e",
          "body": "Minor release: adds the AI agent skills inventory scanner; broadens MCP config\ndiscovery (filename recognition, VS Code, vendor heuristic, Windows dedup); adds\nmetadata-first tool version detection and the macOS Gatekeeper pre-exec guard;\nand extends Python package discovery to a filesystem walk. Also backfills\nCHANGELOG entries for features that landed since 1.13.0 without release notes.\n\nSigned-off-by: Swarit Pandey <swarit@stepsecurity.io>",
          "is_bot": false,
          "headline": "chore(release): update to 1.14.0",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-17T14:00:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b5e80eebc0619f4a33215e0663d4592907832349",
          "body": "…scovery\n\nfix(mcp): recognize MCP configs by name, add VS Code + broaden discovery",
          "is_bot": false,
          "headline": "Merge pull request #170 from swarit-stepsecurity/swarit/fix/wt/mcp-di…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-17T08:48:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d092267da05d5ddd6ce5ce1d4bc5c342ae167135",
          "body": "…iscovery\n\n# Conflicts:\n#\tinternal/detector/mcp.go",
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'upstream/main' into swarit/fix/wt/mcp-d…",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-17T08:29:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "50b23ab41ebc10c6c8fc6cfb56f5a1f812e07f70",
          "body": "feat(detector): resolve tool versions from install metadata before exec and skip exect of Gatekeeper-rejected quarantined binaries",
          "is_bot": false,
          "headline": "Merge pull request #169 from ashishkurmi/main",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-17T07:41:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ea704984cc729878c4210495229b2f7811cac209",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into main",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-17T07:38:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4779d7c2cbe6dd71c32df2af5e6331b47b02cebb",
          "body": "fix(mdm): show telemetry-upload lines in downloaded logs; stop double-capturing Claude Desktop",
          "is_bot": false,
          "headline": "Merge pull request #168 from shubham-stepsecurity/sm/dmg-download-logs",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-17T05:27:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9be280ecc254f9d42403e7d59cba1c50ebe60ce8",
          "body": "…ork agent only)",
          "is_bot": false,
          "headline": "fix(detector): stop capturing Claude Desktop as an IDE (report as cow…",
          "author_name": "Shubham Malik",
          "author_login": "shubham-stepsecurity",
          "committed_at": "2026-07-17T04:45:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b21198f9182873f001983d8a3cafb83607cc44a5",
          "body": null,
          "is_bot": false,
          "headline": "fix(telemetry): include upload-intent lines in downloaded execution logs",
          "author_name": "Shubham Malik",
          "author_login": "shubham-stepsecurity",
          "committed_at": "2026-07-17T04:45:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3894108de8cdcf1ac8ae71f1e2f2f2f97a4b98b2",
          "body": "feat: add AI agent skills inventory scanning support",
          "is_bot": false,
          "headline": "Merge pull request #162 from raysubham/feat/ai-agent-skills-inventory",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-16T16:54:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "818b8e0626bf5d31dda3ac060847ceb8ac2b627a",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into feat/ai-agent-skills-inventory",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-16T14:54:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ca4fb5c0588a67704e504c7992ea2bce39c9489f",
          "body": "…erpreter-discovery\n\nfix(python): discover interpreters to find all site-packages",
          "is_bot": false,
          "headline": "Merge pull request #165 from swarit-stepsecurity/swarit/fix/wt/py-int…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-16T14:53:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4a05c0929c3e27bad59dadea8cd0ae4a17461c70",
          "body": "Address review on PR #165:\n- Thread the executor through Python install-root discovery and resolve the\n  home directory via executor.ResolveHome instead of os.UserHomeDir, so a\n  root-run launchd scan anchors the version-manager trees (pyenv/asdf/uv/\n  conda/pipx) on the logged-in user's home rather\n[…]\n_COVERAGE.md: clarify that the whole-home walk skips ~/Library while the\n  global user-site ~/Library/Python/* is still scanned as its own explicit\n  root, so global user-site packages remain covered.",
          "is_bot": false,
          "headline": "fix(python): resolve console-user home for root-run scans; clarify docs",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-16T13:48:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f3891dcff96ecd1857bd7896960b46ab60fde7d1",
          "body": "…ccheck S1016\n\npipeDirEntry and pipeFileInfo are structurally identical (struct{ name string }), so use a type conversion instead of a field-by-field struct literal.",
          "is_bot": false,
          "headline": "test(detector): convert pipeDirEntry to pipeFileInfo to satisfy stati…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-16T11:02:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0e1aa7e25734876562b12d0f5095d3b8e0d48bd2",
          "body": "…gnize\n\nThe disk-based Python scanner gathered site-packages from a fixed allow-list\nof globs, so packages installed under any interpreter not on that list were\ninvisible — most visibly Apple's Command Line Tools python\n(/Library/Developer/CommandLineTools/.../Python3.framework), whose\nsite-packages\n[…]\n) so\n  field logs show exactly where the agent looked.\n\nStill TCC-safe (the walk uses the existing tcc.Skipper). SCAN_COVERAGE.md is\nupdated to document the model and what is/isn't covered by default.",
          "is_bot": false,
          "headline": "fix(python): discover installed packages via filesystem walk-and-reco…",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-16T10:29:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a45201c097768ba2ca0766d2e5cf7e8f7361bfd4",
          "body": "Add a TCC-safe recursive walk of the search dirs (default $HOME) that finds\nproject-convention marker dirs (.claude, .agents, .gemini, .aider, …) and feeds\ntheir parents into discoverProjects, so projects never registered in\n~/.claude.json and unseen by the node/python scanners are still inventoried\n[…]\nmpt can fire under\nthe default posture.\n\nAlso add Gemini CLI (~/.gemini/skills, .gemini/skills) and Aider (.aider/skills)\nsources plus the Zed alias, and walk_dirs_visited / walk_roots_found counters.",
          "is_bot": false,
          "headline": "feat(skills): discover unregistered projects via home-directory walk",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-16T10:06:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "39016f01ddad6c0f07ae05980f6d424b5c8686f7",
          "body": "- mcpVendorForPath: only label VS Code when the path is a .vscode* dotfile\n  root or the actual Code/User config shape, so project roots like ~/code are\n  no longer mislabeled Microsoft.\n- allConfigLocations: case-fold the dedup key on Windows so the same file\n  found via different casings isn't reported twice.\n- Reword the Detect doc comment (it doesn't return content) and the\n  basename-set comment (complete sentence).\n- Add a regression test for the vendor heuristic.",
          "is_bot": false,
          "headline": "fix(mcp): address review — vendor heuristic, Windows dedup, comments",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-16T08:16:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6823550e70a3ad3ecd2bd5c82643bfe135824022",
          "body": "… claim\n\nReview feedback fixes:\n\n- nodepm, pythonpm, and configaudit yarn/bun assessed the resolved\n  absolute path with execguard but then executed the bare command name,\n  letting a PATH re-resolution at exec time reach a binary the guard\n  never assessed. All version-probe fallbacks now run the e\n[…]\native\n  plugins it may dlopen later — metadata-first resolution remains the\n  primary defense; the guard removes the main scan-triggered vector.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(detector): exec the guard-assessed path, bound PlistBuddy, temper…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-16T03:23:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e7515a3cd03302cbe6495ae44df4f029d7d2f382",
          "body": "… on macOS\n\nMetadata-first version resolution removed most third-party execs, but a\ntool with no readable install metadata still fell back to running\n`--version` — and if that binary is quarantined (com.apple.quarantine,\nset by browser downloads and Homebrew casks) and not notarized, macOS\nshows the\n[…]\nbin/xattr, /usr/sbin/spctl) are\nexecuted by the guard itself. Non-macOS platforms are unaffected.\nGeneralizes the existing IsAppleCLTStub guard.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(detector): skip exec of Gatekeeper-rejected quarantined binaries…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-16T00:47:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "10e773f722dfaf342fb35db9a56df8653f4ad47e",
          "body": "Executing third-party binaries for --version popped macOS Gatekeeper\n\"could not verify\" dialogs when a tool ships un-notarized native code\n(cursor-agent dlopens merkle-tree-napi.darwin-arm64.node on any\ninvocation, including --version).\n\n- new internal/versionmeta package resolves versions from on-d\n[…]\nogs a stderr line\n  (\"exec fallback: running ...\") so rollouts can track which tools\n  still get executed; detectors gain a chainable WithLogger\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(detector): resolve tool versions from install metadata before exec",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-16T00:43:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e7b865e935dc5a359ffd8fc474d687f2acb5d388",
          "body": "has_code / code_file_count is a coarse \"this skill could run code\" signal that\ncomplements has_shell_injection and has_hooks. The census counted only\n.py/.js/.ts/.sh, so PowerShell, Ruby, ESM (.mjs/.cjs), .bash/.zsh, and Windows\n.bat/.cmd skills read as has_code=false, understating risk.\n\nWiden code\n[…]\np/.lua). Compiled languages are intentionally excluded\n(build step required, prone to vendored-dep/build-artifact false positives).\n\nNo logic change — the stat-only census keys off this map unchanged.",
          "is_bot": false,
          "headline": "feat(skills): broaden has_code detection to more executable script types",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-15T19:25:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b3ea87d49471324db431a9114266137e87aea466",
          "body": "…scovery\n\nThe agent-skills detector was the one filesystem walker not wired to the\nshared tcc.Skipper, so a project registered in ~/.claude.json under a\nTCC-protected directory (e.g. ~/Documents) was probed directly and could fire\na macOS permission prompt, breaking the agent's \"never triggers a TCC\n[…]\nng the\n  XDG_STATE_HOME-under-~/Library vector.\n- Wire the skipper at the community-scan and telemetry construction sites.\n\nA nil skipper (--include-tcc-protected) and non-macOS builds are unaffected.",
          "is_bot": false,
          "headline": "fix(skills): honor macOS TCC-protected directories in agent-skills di…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-15T17:13:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "497d317aa380c72b73a1a099d7ba5430645074e1",
          "body": "MCP discovery only checked a hard-coded list of exact config paths plus\n.mcp.json files in Claude-registered projects. Anything else was invisible —\nnotably VS Code's user-level mcp.json (%APPDATA%\\Code\\User\\mcp.json,\n~/Library/Application Support/Code/User/mcp.json) and .mcp.json files under\n~/.vsc\n[…]\nss into protected trees is introduced.\n\nThe content parser is unchanged, so once a config is located its servers\n(local command and remote url/serverUrl) are extracted with secrets stripped\nas before.",
          "is_bot": false,
          "headline": "fix(mcp): recognize MCP configs by name, add VS Code + broaden discovery",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-15T06:04:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d7556be31619c70248aad2d73e810fd4912cedc0",
          "body": "…nputs\n\nTruncation honesty: mark the scan Truncated on context cancellation or\ndeadline and in the panic-recovery path, and enforce a 2000-record\naggregate cap (matching the backend payload cap) through a\nfinalizeSkills helper shared by the normal return and the recovery\npath, so a partial inventory\n[…]\ne telemetry\nskills bridge (skills live under <project>/.claude/skills, not the\nvenv), and render \"Not scanned\" vs \"None detected\" distinctly in pretty\nand HTML output when the skills scan did not run.",
          "is_bot": false,
          "headline": "fix(detector): harden agent skills scan against partial and hostile i…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-14T18:03:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "da7bc69184a8d3cd3e009ff88b2e4c04c9267117",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into feat/ai-agent-skills-inventory",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-13T20:53:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b08f2b26fd22637e5219f8a2c6fe2dae8bf955d0",
          "body": "The ~/.claude/plugins/{cache,repos} subtrees are no longer walked for\nskill directories, and claude_plugin is removed from the source set.\nSkills are discovered through the global, project, and skills.sh\nlock-managed roots only; a plugin's skill is inventoried when it is\nsymlinked or installed into \n[…]\ng and the skills.sh lock's\nplugin_name provenance are unchanged.\n\nAlso stop echoing the canonical record's own source into symlink_sources\nwhen another member of its collapse group shares that source.",
          "is_bot": false,
          "headline": "feat(detector): stop walking Claude Code plugin trees for skills",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-09T19:16:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5afc0d4b66cbcc44f6423792831a98a26239e716",
          "body": "skills.sh installs a skill once and symlinks it into each agent's own\nroot, so enumeration emitted one record per root and inflated a single\nphysical skill into N+1 records. Collapse those shadows into one record\nper physical skill dir, keyed on the symlink-resolved path: the real\ndirectory is canon\n[…]\ne now-constant\nis_symlink and present_on_disk fields.\n\nAlso add Pi, Factory, Amp, and Copilot skill roots (global and project),\nincluding Factory's singular .agent/skills and Copilot's .github/skills.",
          "is_bot": false,
          "headline": "feat(detector): collapse symlink shadows in agent skills inventory",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-09T18:39:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "22df21ed653c48a5290c3360f58c3bf097eae11e",
          "body": "…repo-flag\n\nfix(ci): pin repo target for gh release upload/delete-asset in macOS …",
          "is_bot": false,
          "headline": "Merge pull request #164 from ashishkurmi/akurmi/fix/release-macos-gh-…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-09T17:03:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1de49a5b69b91a261b36c143aea865b35146ca45",
          "body": "…notarize job\n\nThis job never checks out the repo, so gh has no git remote to infer\nthe target repository from. The upload/cleanup step omitted -R and\nfailed with \"not a git repository\", unlike the earlier download step\nwhich already passes -R.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ci): pin repo target for gh release upload/delete-asset in macOS …",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-09T16:58:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2d2e69f32892b5d4307e6ab9848bd1f0894af1b7",
          "body": "…raft-race\n\nfix(ci): wait for release-list propagation before resolving draft tag",
          "is_bot": false,
          "headline": "Merge pull request #163 from ashishkurmi/akurmi/fix/release-resolve-d…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-09T15:20:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03253261d8afe44fb565cafec1cb710c6e25f71b",
          "body": "GoReleaser creates the draft release for a tag pushed earlier in the\nsame job, and GitHub can take a few seconds to index that tag before\nthe new release shows up in the releases-list API. Querying\nimmediately can return an empty list and fail with \"Could not find\ndraft release\", even though the release was created successfully.\n\nAdd a fixed 30s sleep before the lookup to give GitHub's API time to\ncatch up.",
          "is_bot": false,
          "headline": "fix(ci): wait for release-list propagation before resolving draft tag",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-09T15:12:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "53c5fac6e2a88e8c2fd061db85b291f024952993",
          "body": "…s-inventory\n\n# Conflicts:\n#\tinternal/featuregate/featuregate.go",
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'upstream/main' into feat/ai-agent-skill…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-09T13:53:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6eda105a49232455cdac2932f40c7cfd4de83adc",
          "body": "The home directory appears in the ~/.claude.json project registry whenever\nClaude Code has been run from $HOME. Treating it as a project re-scanned the\nglobal skill dirs (~/.claude/skills, ~/.agents/skills) and re-emitted every\nglobal skill as a project-scoped duplicate, also double-counting roots_scanned.\n\nSkip the home directory in project discovery — its dotfile skill dirs are the\nglobal roots. Adds a regression test covering a registry that lists both home\nand a genuine sub-project.",
          "is_bot": false,
          "headline": "fix(detector): exclude home dir from skills project discovery",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-09T13:47:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e539e5644e2e5196e68b2e37b259ca9615c80733",
          "body": "Scan for Agent Skills installed for AI coding agents at global and\nper-project scope, covering Claude Code skills and skills.sh-managed\ninstalls (including plugin-provided skills).\n\nFor each skill the scan records metadata (name, agent, scope, source),\na SHA-256 hash of its SKILL.md for drift detect\n[…]\nare never read beyond SKILL.md and are never transmitted; local\nsource paths from lock files are recorded by alias only.\n\nThe ~/.claude.json project-registry discovery is shared with the MCP\ndetector.",
          "is_bot": false,
          "headline": "feat(detector): add AI agent skills inventory scanning",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-09T13:15:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8f0e5912b37ad8f7afcfe6ed7d6e433c2ac6f224",
          "body": "feat(featuregate): enable device-policy enforcement by default",
          "is_bot": false,
          "headline": "Merge pull request #161 from raysubham/subham/feat/wt/device-policy-ga",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-09T10:35:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ac979bb00afe39ea931d3caa4b59eadc109e8999",
          "body": "Turn on the device-policy feature gate so IDE-extension policy enforcement\nruns for all enterprise customers instead of staying behind the beta gate.\n\nAll enforcement code is already on main (run-config policy fetch,\ntarget-aware policy identity, user-scope settings.json convergence,\ncompliance repo\n[…]\n0, matching this build's version\nfloor, so enabling enforcement is safe.\n\nDrop the now-stale gate comment, and note general availability plus\nenabled-by-default on the existing 1.13.0 changelog entry.",
          "is_bot": false,
          "headline": "feat(featuregate): enable device-policy enforcement by default",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-07-09T09:15:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b837f57d15a145ae7ab97c62e4bf62b2cc2209e2",
          "body": "…s-yarn-globals\n\nfix(node): enumerate yarn classic globals on Windows",
          "is_bot": false,
          "headline": "Merge pull request #160 from swarit-stepsecurity/swarit/fix/wt/window…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-08T20:36:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "71c052caff4e9e1be938fcb36bc34497779ee45a",
          "body": "NodeGlobalRoots only had the POSIX yarn global path (~/.config/yarn/global),\nwhich never resolves on Windows (yarn 1.x installs to %LOCALAPPDATA%\\Yarn\\Data\\global).\nSo yarn globals (gulp/grunt-cli) were invisible on Windows while npm/pnpm\nworked. Add the Windows yarn global location(s).",
          "is_bot": false,
          "headline": "fix(node): enumerate yarn classic globals on Windows",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-08T10:59:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b0c88ce222271b034c8ed45e5d7d610a423f33d8",
          "body": "…lobal-discovery\n\nfix(node): discover pnpm globals (v10+ layout + store lockfile fallback)",
          "is_bot": false,
          "headline": "Merge pull request #159 from swarit-stepsecurity/swarit/fix/wt/node-g…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-08T10:40:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4dd5db89596d7912778114f2402c81eff715c774",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/fix/wt/node-global-discovery",
          "author_name": "Swarit",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-08T10:05:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a911076f9011e408651aad9a34bd0303b1ec8efc",
          "body": "…m store)\n\npnpm installs global packages as symlinks into a content-addressed store, so\nwalking the global node_modules yields nothing. When ScanGlobalModules returns\nempty, fall back to parsing the install dir's lockfile (parent of node_modules)\nkeyed on the root's PM, recovering pnpm globals (webpack/jest) with is_direct.",
          "is_bot": false,
          "headline": "fix(node): parse global lockfile when node_modules walk is empty (pnp…",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-08T09:19:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c69100fd6ba38ad0b0ab50bd7d7c97662b632ef1",
          "body": "…dules)\n\nNodeGlobalRoots only globbed <pnpm-home>/global/*/node_modules, matching\npnpm <=9. pnpm v10+ nests each global install under global/v<major>/<hash>/,\nso the disk scan found zero pnpm globals (webpack/jest missing). Add the\nextra-level glob so both layouts are enumerated.",
          "is_bot": false,
          "headline": "fix(node): discover pnpm v10+ globals (global/v<major>/<hash>/node_mo…",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-08T09:03:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6b7a999bcac282cf2b4e0095e0fd2af0d6686c12",
          "body": "…er-1.12.1\n\nchore(release): update to 1.13.0",
          "is_bot": false,
          "headline": "Merge pull request #158 from swarit-stepsecurity/swarit/chore/wt/up-v…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-08T05:39:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0bb1dc8fe638fe15c08b504ae262d21c2a8580fc",
          "body": "Minor release: carries device-policy enforcement, disk-based npm/Python\npackage scanning, scheduler diagnostics + run-on-login, heartbeat, and the\nopt-in scan-state delta protocol.\n\nSigned-off-by: Swarit Pandey <swarit@stepsecurity.io>",
          "is_bot": false,
          "headline": "chore(release): update to 1.13.0",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-08T05:24:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f797e76e91a73cc0127be16f8e49d18b1c62a0fa",
          "body": "…ng-guidelines\n\ndocs: add coding guidelines derived from existing patterns",
          "is_bot": false,
          "headline": "Merge pull request #157 from swarit-stepsecurity/swarit/chore/wt/codi…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-07T06:51:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5e1b1727933631a747f90b1864cb99e2b6346f7f",
          "body": null,
          "is_bot": false,
          "headline": "docs: rename coding-guidelines.md to AGENTS.md at repo root",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-07T06:41:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b4f9888a2002d5271886bbb20dafd8eb726b63ea",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/chore/wt/coding-guidelines",
          "author_name": "Swarit",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-07T06:40:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f585dc0589ed268fe49e8d3a99731c4cd98d6f23",
          "body": "feat(devicepolicy): enforce VS Code extension allowlist",
          "is_bot": false,
          "headline": "Merge pull request #138 from raysubham/feat/dmg-policy-profiles",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-06T06:18:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "413cc837066787de43145c676bb6a988a85db10f",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into feat/dmg-policy-profiles",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-06T06:14:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c9b913c0c37a3115923ba559d7a7442d8816ce2a",
          "body": "…te-npm-scanning\n\nfeat(node): add disk-based package scanning (lockfile parsing)",
          "is_bot": false,
          "headline": "Merge pull request #156 from swarit-stepsecurity/swarit/feat/wt/migra…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-03T06:26:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "02b0de77e3ef97b484906d0fd3f95bee6062e2ed",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/feat/wt/migrate-npm-scanning",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-03T06:21:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "665eaaaa8e8a50adf4317d78429b3ca25004187c",
          "body": "…hooting\n\ndocs: add macOS launchd troubleshooting guide",
          "is_bot": false,
          "headline": "Merge pull request #143 from shubham-stepsecurity/sm/launchd-troubles…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-03T06:20:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e6a1427b7a74b65e3a02a9e8d5cbd4c6164beeda",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/feat/wt/migrate-npm-scanning",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-03T06:19:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83915ba45c4c9fa17835d0dc81a941c240cc22e1",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into sm/launchd-troubleshooting",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-03T06:17:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5bb357e3a3bfe402c3ac9b5f824f0a8f3d8d60db",
          "body": "…tudio\n\nfeat(detector): discover classic Visual Studio extensions and installs",
          "is_bot": false,
          "headline": "Merge pull request #142 from shubham-stepsecurity/sm/classic-visual-s…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-03T05:58:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8b3b85f673faa603ce1b0bdaba73dfaae7b09038",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into sm/classic-visual-studio",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-03T05:54:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8a34e8cdd9222daa0eb8b4509ea7a72d08584e13",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/feat/wt/migrate-npm-scanning",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-03T05:20:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "992f385a2dfc93f59f454b97d58e243085f4a694",
          "body": null,
          "is_bot": false,
          "headline": "feat(detector): discover classic Visual Studio extensions and installs",
          "author_name": "Shubham Malik",
          "author_login": "shubham-stepsecurity",
          "committed_at": "2026-07-03T04:27:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "74fbd1cd805339452b9f2de5393c137fc0ae3fa8",
          "body": "…te-py-scanning\n\nfeat(python): disk-based package scanning (dist-info metadata)",
          "is_bot": false,
          "headline": "Merge pull request #155 from swarit-stepsecurity/swarit/feat/wt/migra…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-02T16:26:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59e25b7b4276ac3e60dbaed9f8a7032c63d6fc16",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/feat/wt/migrate-py-scanning",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-02T06:13:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "44474f0c29cb7d093a52336c589bcc218822907e",
          "body": "…acquire-logging\n\nfeat(telemetry): log and report lock-acquisition contention at info",
          "is_bot": false,
          "headline": "Merge pull request #152 from swarit-stepsecurity/swarit/feat/wt/lock-…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-02T06:13:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9b596f92d49a4d93cd4f6f3eff9b3be1342ff82c",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/feat/wt/lock-acquire-logging",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-07-02T06:08:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1d6ac5edff82c5b1a040764523ae5ea53cddf605",
          "body": null,
          "is_bot": false,
          "headline": "fix(node): count disk packages in scan cap; gate delta on PMVersion",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-07-02T03:49:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4abd891091696bc439bed5ae5131f7aa9a33b1ac",
          "body": null,
          "is_bot": false,
          "headline": "docs(tcc): configure Full Disk Access for all devices only",
          "author_name": "Shubham Malik",
          "author_login": "shubham-stepsecurity",
          "committed_at": "2026-07-01T01:53:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff29a5ba5df74755b9847c0de98da191a8252c32",
          "body": "Document the conventions the codebase already follows and link from\nCONTRIBUTING.md's Code Style section.",
          "is_bot": false,
          "headline": "docs: add coding guidelines derived from existing patterns",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-06-30T15:10:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3f35a34234f967555b7ab94058eebc6da80bd385",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/feat/wt/migrate-npm-scanning",
          "author_name": "Swarit",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-06-30T11:06:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e5c66331e6bde8bcaaf03582b25da4818fb6441d",
          "body": "Read installed Node packages by parsing lockfiles (package-lock v1/v2/v3,\npnpm-lock, yarn.lock, bun.lock) and node_modules instead of running\nnpm/yarn/pnpm/bun. Default to disk scan; legacy command path kept behind\n--legacy-node-scan / use_legacy_node_scan.\n\nEmits structured {name, version, is_direc\n[…]\nth\nempty raw output; the backend stores it via pass-through (no agent-api\nchange). is_direct keys on declared deps to match npm-ls tree semantics; no\n--depth cap, so the full resolved set is reported.",
          "is_bot": false,
          "headline": "feat(node): add disk-based package scanning (lockfile parsing)",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-06-30T10:53:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4b927a303705ef5b1c32329fd517b2841a034cfb",
          "body": "fix(detector): resolve node PM versions via default install paths",
          "is_bot": false,
          "headline": "Merge pull request #141 from shubham-stepsecurity/sm/fix",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-06-30T07:19:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7360ce38f3616557c8868081d23f77b3d5325b7b",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into sm/fix",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-06-30T07:17:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1abf3c056275afc60fe3077da2c58581c8a59fed",
          "body": "lock.Acquire can also fail on permission/IO errors creating the lock\nfile; the underlying error carries the specific cause. Reword the log\nline and comment so they no longer hard-code the 'another instance is\nrunning' assumption.",
          "is_bot": false,
          "headline": "fix(telemetry): don't assume lock failure means contention",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-06-29T15:23:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d85e9c526f80e2e076a7fe28737f92d8f5881d81",
          "body": "- PythonGlobalRoots anchors per-user paths on the console user via\n  executor.ResolveHome (falling back to os.UserHomeDir), so the\n  root/launchd agent scans the logged-in user's ~/.local, ~/.pyenv, pipx.\n- readBounded stats file size before reading to avoid large allocations,\n  keeping the post-read length check as a race-safety fallback.\n- ScanVenv limits its walk to the venv's site-packages dirs instead of\n  the whole tree.",
          "is_bot": false,
          "headline": "fix(python): address PR review on disk-based scanning",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-06-29T15:19:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8266443e2bf11f5b5b301f0429dff3c99af19829",
          "body": "…get)\n\nPolicy identity is now (category, target) rather than category alone. An\nempty target defaults to vscode for ide_extension, so a future IDE family\nbecomes a new target instead of a new category or an on-disk migration. v1\nstill enforces only ide_extension/vscode and preserves VS Code behavior\n[…]\net through fetch, state read/write/clear, and\n  reporting; an empty Reconciler.Target defaults to vscode, so main.go needs\n  no change.\n\nDetection-rules fetch/scan path is untouched (zero regression).",
          "is_bot": false,
          "headline": "feat(devicepolicy): make policy identity target-aware (category + tar…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-06-29T12:35:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "70e644a406e2de973679d472902de9b6ca868a65",
          "body": "…aticcheck S1016)",
          "is_bot": false,
          "headline": "fix(python): use type conversion for PackageDetail->PythonPackage (st…",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-06-28T18:53:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d113b9526529353be89ab9dbe8e684e1ead7c040",
          "body": "Read installed Python packages from *.dist-info/METADATA and *.egg-info/\nPKG-INFO instead of running pip. Default to disk scan; legacy pip path\nkept behind --legacy-python-scan / use_legacy_python_scan.",
          "is_bot": false,
          "headline": "feat(python): add disk-based package scanning (dist-info metadata)",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-06-28T18:30:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "efbd43bbb5fae47cc0b2212b02d63ec262b00ce9",
          "body": "…evel\n\nSurface lock-acquisition failures (another instance already running) at info\nlevel instead of Debug so the contention is visible in agent.log, and report\nthe failed run immediately at the failure site so the backend records that a\nsecond invocation contended for the lock. reportFailedOnce is idempotent, so\nthe deferred handler firing on the error return is a no-op.",
          "is_bot": false,
          "headline": "feat(telemetry): log and report lock-acquisition contention at info l…",
          "author_name": "Swarit Pandey",
          "author_login": "swarit-stepsecurity",
          "committed_at": "2026-06-25T06:52:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d7920c50594481d237033dc05d09fb1ffb68c74",
          "body": "The Windows-as-SYSTEM install branch ran runIDEExtensionEnforce inline\nwhile running as NT AUTHORITY\\SYSTEM. Enforce writes user-scope\nsettings.json (%APPDATA%\\Code\\User), which under SYSTEM resolves to the\nservice profile — a phantom write no real VS Code reads, plus a false\n\"compliant\" report agai\n[…]\neady fires the /ru INTERACTIVE task, which enforces in the\nlogged-in user's profile via send-telemetry. Drop the inline call so the\nSYSTEM branch does no user-profile work, mirroring the macOS branch.",
          "is_bot": false,
          "headline": "fix(install): don't enforce IDE policy inline under SYSTEM",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-06-24T20:13:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c36dfd47333a466cf330f9a556e3aa9a1fea998d",
          "body": "…ve-policy endpoint\n\nThe backend consolidated the per-device IDE-extension policy into the existing\nrun-config response as a `policy` sub-object; the dedicated effective-policy\nendpoint is gone (404). Repoint HTTPFetcher.Fetch at run-config and lift the\ndirective from `policy`.\n\n- GET run-config?dev\n[…]\n document parses to reach `policy`; shared maxBodyBytes stays\n  256 KiB for the error-snippet/drain reads.\n\nEnforcement is inert until the consolidated backend is live in the target env\n(live on int).",
          "is_bot": false,
          "headline": "fix(devicepolicy): fetch policy from run-config, drop removed effecti…",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-06-24T19:59:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d52c94129902382446c2bc559ad4160d2b0eb820",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into feat/dmg-policy-profiles",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-06-24T18:49:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "68fdfb3ab74557264429fd620923ee456bc76459",
          "body": "…dule-24h\n\nfix(schtasks): use DAILY schedule for scan frequencies of 24h+",
          "is_bot": false,
          "headline": "Merge pull request #151 from raysubham/subham/fix/schtasks-daily-sche…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-06-24T09:37:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83a8f73833299ffa295c57dac807ebc82bac68e2",
          "body": "schtasks caps the HOURLY /mo modifier at 23, so a 24-hour scan frequency\nproduced `/sc HOURLY /mo 24`, which schtasks rejects with \"Invalid value\nfor /MO option\". The install custom action then exits non-zero and the MSI\nrolls back, surfacing under Intune as 0x80070643 (and failing identically\non a \n[…]\nr() with table-driven unit coverage (boundaries 23/24, the\n24h case, and pathological 0/100000 inputs) plus a regression guard that\nthe hourly path and the admin /ru INTERACTIVE binding are untouched.",
          "is_bot": false,
          "headline": "fix(schtasks): use DAILY schedule for scan frequencies of 24h+",
          "author_name": "Subham Ray",
          "author_login": "raysubham",
          "committed_at": "2026-06-24T07:53:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1c83b7d792cb6b1ec4fa9707595dff75895fe73f",
          "body": "…nterval-gate\n\nfeat: run-on-login scheduling, reliability fixes, scheduler diagnostics",
          "is_bot": false,
          "headline": "Merge pull request #146 from shubham-stepsecurity/sm/scheduler-info-i…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-06-24T06:43:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "37a0a422cd6111af6ba8584cd06dbbfc8af896bf",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into sm/scheduler-info-interval-gate",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-06-24T06:40:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2412a3fb30b32940f5d55c2237f76082ff9405e1",
          "body": "…logs-python\n\nchore: add per-venv scan logging to Python project detector",
          "is_bot": false,
          "headline": "Merge pull request #144 from swarit-stepsecurity/swarit/chore/wt/add-…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-06-24T06:39:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "911866efa0532b5a086ae3cf5458cb8510005b2f",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'main' into swarit/chore/wt/add-logs-python",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-06-24T06:34:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a5db1c437edd30f9b562837fb54c32570712acb",
          "body": null,
          "is_bot": false,
          "headline": "feat(telemetry): include this run's loader-script logs",
          "author_name": "Shubham Malik",
          "author_login": "shubham-stepsecurity",
          "committed_at": "2026-06-23T23:47:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "af7bb2f659c6d2eb7df6617ecb05977384293d76",
          "body": null,
          "is_bot": false,
          "headline": "feat: enable Windows Task Scheduler history; address review feedback",
          "author_name": "Shubham Malik",
          "author_login": "shubham-stepsecurity",
          "committed_at": "2026-06-23T23:31:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "823bedb66d31e67132018ee90cd4c7b19e81fc0b",
          "body": null,
          "is_bot": false,
          "headline": "feat: run-on-login scheduling, reliability fixes, scheduler diagnostics",
          "author_name": "Shubham Malik",
          "author_login": "shubham-stepsecurity",
          "committed_at": "2026-06-23T23:31:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c9b55b78c588aabd341039afbe859d0fa1d1118e",
          "body": "…-heartbeat\n\nfeat(heartbeat): write last-run.json at top of send-telemetry",
          "is_bot": false,
          "headline": "Merge pull request #148 from swarit-stepsecurity/swarit/feat/last-run…",
          "author_name": "Ashish Kurmi",
          "author_login": "ashishkurmi",
          "committed_at": "2026-06-23T13:06:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 18,
      "commits_last_year": 513,
      "latest_release_at": "2026-07-17T18:53:26Z",
      "latest_release_tag": "v1.14.0",
      "releases_from_tags": false,
      "days_since_last_push": 2,
      "active_weeks_last_year": 19,
      "days_since_latest_release": 9,
      "mean_days_between_releases": 8.8
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 87,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/step-security/dev-machine-guard",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/step-security/dev-machine-guard",
          "is_deprecated": false,
          "latest_version": "v1.14.0",
          "repository_url": "https://github.com/step-security/dev-machine-guard",
          "versions_count": 18,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-17T14:37:14Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 9
        }
      ]
    },
    "popularity": {
      "forks": 23,
      "stars": 169,
      "watchers": 5,
      "fork_history": {
        "days": [
          {
            "date": "2026-03-12",
            "count": 2
          },
          {
            "date": "2026-03-13",
            "count": 1
          },
          {
            "date": "2026-03-15",
            "count": 1
          },
          {
            "date": "2026-03-16",
            "count": 2
          },
          {
            "date": "2026-03-17",
            "count": 1
          },
          {
            "date": "2026-03-24",
            "count": 1
          },
          {
            "date": "2026-04-02",
            "count": 1
          },
          {
            "date": "2026-04-03",
            "count": 1
          },
          {
            "date": "2026-04-08",
            "count": 1
          },
          {
            "date": "2026-04-17",
            "count": 1
          },
          {
            "date": "2026-04-24",
            "count": 1
          },
          {
            "date": "2026-04-29",
            "count": 1
          },
          {
            "date": "2026-05-05",
            "count": 1
          },
          {
            "date": "2026-05-10",
            "count": 1
          },
          {
            "date": "2026-06-01",
            "count": 1
          },
          {
            "date": "2026-06-21",
            "count": 1
          },
          {
            "date": "2026-06-23",
            "count": 2
          },
          {
            "date": "2026-06-26",
            "count": 1
          },
          {
            "date": "2026-06-28",
            "count": 1
          },
          {
            "date": "2026-07-25",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 23,
        "total_forks": 23
      },
      "star_history": null,
      "open_issues_and_prs": 33
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 70180,
      "source_files_sampled": 333,
      "oversized_source_files": 2,
      "agent_instruction_files": [
        "AGENTS.md"
      ],
      "agent_instruction_max_bytes": 42944
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "golang.org/x/sys",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.33.0"
        },
        {
          "name": "github.com/google/shlex",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0-20191202100458-e7afc7fbc510"
        },
        {
          "name": "github.com/google/uuid",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.0"
        },
        {
          "name": "github.com/pelletier/go-toml/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.3.1"
        },
        {
          "name": "github.com/tailscale/hujson",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0-20260302212456-ecc657c15afd"
        },
        {
          "name": "github.com/tidwall/gjson",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.18.0"
        },
        {
          "name": "github.com/tidwall/pretty",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.2.1"
        },
        {
          "name": "github.com/tidwall/sjson",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.2.5"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        },
        {
          "name": "howett.net/plist",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.1"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 8,
        "merged_prs": 121,
        "open_issues": 25,
        "closed_ratio": 0.219,
        "closed_issues": 7,
        "closed_unmerged_prs": 20
      },
      "bus_factor": 2,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "ashishkurmi",
          "commits": 196,
          "avatar_url": "https://avatars.githubusercontent.com/u/100655670?v=4"
        },
        {
          "type": "User",
          "login": "swarit-stepsecurity",
          "commits": 172,
          "avatar_url": "https://avatars.githubusercontent.com/u/208925350?v=4"
        },
        {
          "type": "User",
          "login": "shubham-stepsecurity",
          "commits": 79,
          "avatar_url": "https://avatars.githubusercontent.com/u/171509047?v=4"
        },
        {
          "type": "User",
          "login": "raysubham",
          "commits": 57,
          "avatar_url": "https://avatars.githubusercontent.com/u/66999381?v=4"
        },
        {
          "type": "User",
          "login": "Prateek-stepsecurity",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/209430544?v=4"
        },
        {
          "type": "User",
          "login": "eromosele-stepsecurity",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/193469761?v=4"
        },
        {
          "type": "User",
          "login": "varunsh-coder",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/25015917?v=4"
        }
      ],
      "contributors_sampled": 7,
      "top_contributor_share": 0.384
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "check-notarization-status.yml",
        "gosec.yml",
        "msi-smoke.yml",
        "release-macos.yml",
        "release.yml",
        "test-azure-signing.yml",
        "test-build.yml",
        "test-macos-signing.yml",
        "tests.yml",
        "verify-release.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        ".golangci.yml"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "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": 8,
            "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": "9 out of 9 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 10,
            "reason": "all changesets reviewed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 3 contributing companies or organizations -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 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": 9,
            "reason": "1 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "2cf07e270ae355919a8c48fd41bc315cdbe8ceaf",
        "ran_at": "2026-07-27T03:59:36Z",
        "aggregate_score": 8.2,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-24T16:48:36Z",
      "oldest_open_prs": [
        {
          "number": 78,
          "created_at": "2026-05-16T20:00:18Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 79,
          "created_at": "2026-05-18T03:27:09Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 84,
          "created_at": "2026-05-19T02:18:41Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 85,
          "created_at": "2026-05-19T02:36:13Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 89,
          "created_at": "2026-05-20T18:50:53Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 174,
          "created_at": "2026-07-19T10:09:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 179,
          "created_at": "2026-07-23T04:36:02Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 180,
          "created_at": "2026-07-25T07:28:31Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-24T16:47:05Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 2,
          "created_at": "2026-03-12T06:31:58Z",
          "last_comment_at": "2026-04-08T14:32:30Z",
          "last_comment_author": "swarit-stepsecurity"
        },
        {
          "number": 3,
          "created_at": "2026-03-12T06:33:21Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4,
          "created_at": "2026-03-12T06:34:52Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5,
          "created_at": "2026-03-12T06:36:14Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 6,
          "created_at": "2026-03-12T06:36:57Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 9,
          "created_at": "2026-03-16T18:59:22Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 11,
          "created_at": "2026-04-02T15:23:47Z",
          "last_comment_at": "2026-04-02T15:36:02Z",
          "last_comment_author": "koesper"
        },
        {
          "number": 12,
          "created_at": "2026-04-02T18:29:43Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 13,
          "created_at": "2026-04-02T18:30:53Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 14,
          "created_at": "2026-04-03T16:25:25Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 46,
          "created_at": "2026-04-27T05:59:59Z",
          "last_comment_at": "2026-04-27T06:00:17Z",
          "last_comment_author": "swarit-stepsecurity"
        },
        {
          "number": 57,
          "created_at": "2026-05-01T10:25:59Z",
          "last_comment_at": "2026-06-11T18:28:10Z",
          "last_comment_author": "ashishkurmi"
        },
        {
          "number": 58,
          "created_at": "2026-05-01T10:30:16Z",
          "last_comment_at": "2026-05-04T07:48:21Z",
          "last_comment_author": "ashishkurmi"
        },
        {
          "number": 66,
          "created_at": "2026-05-06T06:45:20Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 83,
          "created_at": "2026-05-18T21:40:23Z",
          "last_comment_at": "2026-05-19T02:37:01Z",
          "last_comment_author": "swarit-stepsecurity"
        },
        {
          "number": 90,
          "created_at": "2026-05-20T22:08:47Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 96,
          "created_at": "2026-05-21T21:04:39Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 102,
          "created_at": "2026-05-22T12:25:15Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 110,
          "created_at": "2026-05-25T21:48:18Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 139,
          "created_at": "2026-06-11T23:25:27Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/step-security/dev-machine-guard",
    "host": "github.com",
    "name": "dev-machine-guard",
    "owner": "step-security"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 77,
      "inputs": {
        "security": 82,
        "vitality": 85,
        "community": 70,
        "governance": 70,
        "engineering": 80
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 85,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 77,
            "inputs": {
              "commits_last_year": 513,
              "human_commit_share": 1,
              "days_since_last_push": 2,
              "active_weeks_last_year": 19
            },
            "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": "19/52 weeks with commits",
                "points": 13.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 19
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "513 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 513
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 98,
            "inputs": {
              "releases_count": 18,
              "latest_release_tag": "v1.14.0",
              "releases_from_tags": false,
              "days_since_latest_release": 9,
              "mean_days_between_releases": 8.8
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "18 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 18
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 9 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 9
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~8.8 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 8.8
                    }
                  }
                ],
                "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": "good",
        "name": "Community & Adoption",
        "value": 70,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "moderate",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 51,
            "inputs": {
              "forks": 23,
              "stars": 169,
              "watchers": 5,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "169 stars",
                "points": 36.1,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 169
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "23 forks",
                "points": 11.2,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 23
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "5 watchers",
                "points": 3.3,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "excellent",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 92,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "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 (Apache-2.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "Apache-2.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "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": "good",
        "name": "Sustainability & Governance",
        "value": 70,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "moderate",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 59,
            "inputs": {
              "bus_factor": 2,
              "contributors_sampled": 7,
              "top_contributor_share": 0.384
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "2 contributor(s) cover half of all commits",
                "points": 25.2,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 38% of commits",
                "points": 13.9,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 38
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "7 contributors",
                "points": 9.5,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "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": "moderate",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 58,
            "inputs": {
              "merged_prs": 121,
              "open_issues": 25,
              "closed_issues": 7,
              "issue_closed_ratio": 0.219,
              "closed_unmerged_prs": 20
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "22% of issues closed",
                "points": 10.2,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 22
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "121/141 decided PRs merged",
                "points": 32.8,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 121,
                      "decided": 141
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "all changesets reviewed",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "good",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "followers": 251,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "step-security",
              "public_repos": 497,
              "account_age_days": 1811
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "251 followers of step-security",
                "points": 17.3,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 251,
                      "login": "step-security"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "497 public repos, account ~4 yr old",
                "points": 22.9,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 497
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 4
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/step-security/dev-machine-guard"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 9
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on go",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "go"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 9 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 9
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "18 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 18
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 80,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "10 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 10
                    }
                  }
                ],
                "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": ".golangci.yml",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".golangci.yml"
                    }
                  }
                ],
                "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": "9 out of 9 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": 82,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "good",
            "name": "Security posture",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 18,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 0,
              "scorecard_aggregate": 8.2
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "9 out of 9 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "all changesets reviewed",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 12 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "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": "1 existing vulnerabilities detected",
                "points": 6.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "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": 9
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 82,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.79,
              "agent_instruction_files": [
                "AGENTS.md"
              ],
              "agent_instruction_max_bytes": 42944
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "79 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 79,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "excellent",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0.04,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": ".golangci.yml",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".golangci.yml"
                    }
                  }
                ],
                "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": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "4 of the last 100 commits agent-authored or agent-credited",
                "points": 8,
                "status": "partial",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 4,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "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": 70180,
              "source_files_sampled": 333,
              "oversized_source_files": 2
            },
            "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": "2/333 source files over 60KB",
                "points": 54.7,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 333,
                      "oversized": 2
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "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",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-27T03:59:57.559871Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/s/step-security/dev-machine-guard.svg",
  "full_name": "step-security/dev-machine-guard",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

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

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

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