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

doomedramen / hitch

Rust未检测到许可证★ 0 星标⑂ 0 复刻始于 2025年11月在 GitHub 上查看 ↗

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

52
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

Martin Page个人账户
58 关注者33 个公开仓库始于 2010年10月@Pikl-Insurance

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布标签
crates.iohitch0.1.152129 天前command-line-utilities

按类别列示的指标

活力

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

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

发布纪律

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

社区与采用

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

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

社区健康

25危急
评分方式
22.5/22.5README
0/22.5许可证 — 未检测到许可证文件
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template
评分方式
10.4/80月度下载量 — crates 合计每月 5 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packageshitch
dependents
ecosystemscrates
total_downloads42
monthly_downloads5
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

46存在风险 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 3 contributing companies or organizations -- score normalized to 10
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
0/46.8议题解决 — 没有议题或无数据
15.4/38.3PR 接受 — 已裁定的 PR 中 21/52 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs21
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs31
已排除计分(无数据或不适用):议题解决。 其余权重已重新归一化。
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
12.7/25所有者影响力 — doomedramen 有 58 位关注者
23.2/25既往记录 — 33 个公开仓库,账户约 15 年
所用输入
followers58
owner_typeUser
is_verified
owner_logindoomedramen
public_repos33
account_age_days5,757
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — crates 上有 1 个软件包
35/35发布时效 — 最近一次发布于 129 天前
12/20版本历史 — 2 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packageshitch
ecosystemscrates
any_deprecated
min_days_since_publish129

工程质量

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

68中等 · 占总体的 20%

工程实践

60中等
评分方式
24/24CI 工作流 — 3 个工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
0/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 无数据
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config
已排除计分(无数据或不适用):OpenSSF Scorecard:CI-Tests。 其余权重已重新归一化。

文档

80良好
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://doomedramen.github.io/hitch/
0/10仓库描述
0/10主题标签
10/10Wiki
所用输入
topics
has_wiki
homepagehttps://doomedramen.github.io/hitch/
has_readme
has_docs_dir
has_description

安全

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

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

安全态势

41存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 无数据
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 3 contributing companies or organizations -- score normalized to 10
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
0/2.5许可证 — license file not detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — 无数据
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 32 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate4.1
已排除计分(无数据或不适用):ci_tests, packaging。 其余权重已重新归一化。

AI 就绪度

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

81良好 · 占总体的 0%
评分方式
45/45代理指令 — AGENTS.md, CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 84 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.84
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes12,291
评分方式
18/18一条命令的引导启动 — justfile
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — crates/hitch-desktop/tsconfig.json
10/10可复现环境 — lockfile
10/10已体现的代理实践 — 最近 100 次提交中有 32 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
所用输入
has_nix
has_tests
lockfilesCargo.lock, pnpm-lock.yaml
has_dockerfile
typed_language
bootstrap_filesjustfile
has_devcontainer
has_linter_config
typecheck_configscrates/hitch-desktop/tsconfig.json
agent_commit_share0.32
toolchain_manifestsCargo.toml, crates/hitch-desktop/src-tauri/Cargo.toml
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — Rust(静态类型)
53.8/55可控的文件大小 — 采样的 138 个源文件中有 3 个超过 60KB
所用输入
primary_languageRust
largest_source_bytes96,079
source_files_sampled138
oversized_source_files3

关键数据

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

数据采集警告

  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

更多细节

OpenSSF Scorecard 4.1 / 10
4.1综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
不适用CI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
10Contributorsproject has 3 contributing companies or organizations -- score normalized to 10
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
0Licenselicense file not detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
不适用Packagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
10Security-Policysecurity policy file detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities32 existing vulnerabilities detected
直接依赖 14
注册表软件包版本约束清单文件
crates.ioclap4.5Cargo.toml
crates.ioanyhow1.0Cargo.toml
crates.iothiserror2.0Cargo.toml
crates.ioserde1.0Cargo.toml
crates.ioserde_json1.0Cargo.toml
crates.iocolored3.1Cargo.toml
crates.ioclap_complete4.5Cargo.toml
crates.iogit20.20Cargo.toml
crates.iochrono0.4Cargo.toml
crates.iouuid1.0Cargo.toml
crates.iotokio1.49Cargo.toml
crates.iofs41Cargo.toml
crates.ioinquire0.7Cargo.toml
crates.iotempfile3.25Cargo.toml
全部依赖 未采集

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 8892,
      "has_wiki": true,
      "homepage": "https://doomedramen.github.io/hitch/",
      "languages": {
        "CSS": 5206,
        "HTML": 619,
        "Just": 16873,
        "Rust": 1144181,
        "Shell": 5254,
        "JavaScript": 82,
        "TypeScript": 123687
      },
      "pushed_at": "2026-07-24T10:37:41Z",
      "created_at": "2025-11-15T21:01:51Z",
      "owner_type": "User",
      "updated_at": "2026-07-24T10:37:24Z",
      "description": null,
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": null,
      "primary_language": "Rust",
      "significant_languages": [
        "Rust"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Martin Page",
      "type": "User",
      "login": "doomedramen",
      "company": "@Pikl-Insurance",
      "location": "UK",
      "followers": 58,
      "avatar_url": "https://avatars.githubusercontent.com/u/445964?v=4",
      "created_at": "2010-10-19T20:34:38Z",
      "is_verified": null,
      "public_repos": 33,
      "account_age_days": 5757
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [
        {
          "tag": "v1.3.2",
          "kind": "patch",
          "published_at": "2026-07-24T10:04:41Z"
        },
        {
          "tag": "v1.3.1",
          "kind": "patch",
          "published_at": "2026-07-23T11:54:52Z"
        },
        {
          "tag": "v1.2.49",
          "kind": "patch",
          "published_at": "2026-07-22T14:10:06Z"
        },
        {
          "tag": "v1.2.48",
          "kind": "patch",
          "published_at": "2026-07-22T13:56:39Z"
        },
        {
          "tag": "v1.2.47",
          "kind": "patch",
          "published_at": "2026-07-17T11:29:31Z"
        },
        {
          "tag": "v1.2.46",
          "kind": "patch",
          "published_at": "2026-07-17T11:06:55Z"
        },
        {
          "tag": "v1.2.45",
          "kind": "patch",
          "published_at": "2026-07-17T10:56:00Z"
        },
        {
          "tag": "v1.2.44",
          "kind": "patch",
          "published_at": "2026-07-10T09:29:15Z"
        },
        {
          "tag": "desktop-v0.0.12",
          "kind": "other",
          "published_at": "2026-07-06T17:55:51Z"
        },
        {
          "tag": "desktop-v0.0.11",
          "kind": "other",
          "published_at": "2026-07-06T16:58:12Z"
        },
        {
          "tag": "v1.2.43",
          "kind": "patch",
          "published_at": "2026-07-06T16:42:27Z"
        },
        {
          "tag": "desktop-v0.0.10",
          "kind": "other",
          "published_at": "2026-07-06T16:25:31Z"
        },
        {
          "tag": "v1.2.41",
          "kind": "patch",
          "published_at": "2026-07-06T15:44:48Z"
        },
        {
          "tag": "desktop-v0.0.7",
          "kind": "other",
          "published_at": "2026-04-18T21:21:21Z"
        },
        {
          "tag": "desktop-v0.0.5",
          "kind": "other",
          "published_at": "2026-04-18T20:22:25Z"
        },
        {
          "tag": "v1.2.38",
          "kind": "patch",
          "published_at": "2026-04-16T09:13:43Z"
        },
        {
          "tag": "v1.2.37",
          "kind": "patch",
          "published_at": "2026-04-15T20:15:14Z"
        },
        {
          "tag": "v1.2.36",
          "kind": "patch",
          "published_at": "2026-04-14T19:12:08Z"
        },
        {
          "tag": "v1.2.35",
          "kind": "patch",
          "published_at": "2026-04-14T13:12:39Z"
        },
        {
          "tag": "v1.2.34",
          "kind": "patch",
          "published_at": "2026-03-27T14:09:17Z"
        },
        {
          "tag": "v1.2.33",
          "kind": "patch",
          "published_at": "2026-03-27T11:25:01Z"
        },
        {
          "tag": "v1.2.32",
          "kind": "patch",
          "published_at": "2026-03-27T11:08:20Z"
        },
        {
          "tag": "v1.2.31",
          "kind": "patch",
          "published_at": "2026-03-26T16:56:21Z"
        },
        {
          "tag": "v1.2.28",
          "kind": "patch",
          "published_at": "2026-02-03T11:40:30Z"
        },
        {
          "tag": "v1.2.27",
          "kind": "patch",
          "published_at": "2026-01-19T13:46:26Z"
        },
        {
          "tag": "v1.2.25",
          "kind": "patch",
          "published_at": "2025-12-15T16:50:19Z"
        },
        {
          "tag": "v1.2.24",
          "kind": "patch",
          "published_at": "2025-12-15T15:17:58Z"
        },
        {
          "tag": "v1.2.23",
          "kind": "patch",
          "published_at": "2025-12-15T11:29:39Z"
        },
        {
          "tag": "v1.2.20",
          "kind": "patch",
          "published_at": "2025-12-10T07:47:31Z"
        },
        {
          "tag": "v1.2.19",
          "kind": "patch",
          "published_at": "2025-12-04T12:46:26Z"
        },
        {
          "tag": "v1.2.18",
          "kind": "patch",
          "published_at": "2025-12-04T12:41:37Z"
        },
        {
          "tag": "v1.2.17",
          "kind": "patch",
          "published_at": "2025-12-04T12:30:04Z"
        },
        {
          "tag": "v1.2.16",
          "kind": "patch",
          "published_at": "2025-11-27T12:51:07Z"
        },
        {
          "tag": "v1.2.15",
          "kind": "patch",
          "published_at": "2025-11-27T12:38:01Z"
        },
        {
          "tag": "v1.2.14",
          "kind": "patch",
          "published_at": "2025-11-27T12:32:00Z"
        },
        {
          "tag": "v1.2.13",
          "kind": "patch",
          "published_at": "2025-11-27T11:13:45Z"
        },
        {
          "tag": "v1.2.10",
          "kind": "patch",
          "published_at": "2025-11-19T13:31:26Z"
        },
        {
          "tag": "v1.2.7",
          "kind": "patch",
          "published_at": "2025-11-19T12:50:23Z"
        },
        {
          "tag": "v1.2.5",
          "kind": "patch",
          "published_at": "2025-11-17T19:12:07Z"
        },
        {
          "tag": "v1.2.4",
          "kind": "patch",
          "published_at": "2025-11-17T18:54:00Z"
        },
        {
          "tag": "v1.2.3",
          "kind": "patch",
          "published_at": "2025-11-17T18:36:32Z"
        },
        {
          "tag": "v1.2.2",
          "kind": "patch",
          "published_at": "2025-11-17T18:20:51Z"
        },
        {
          "tag": "v1.2.1",
          "kind": "patch",
          "published_at": "2025-11-17T18:13:36Z"
        },
        {
          "tag": "v1.1.25",
          "kind": "patch",
          "published_at": "2025-11-17T17:52:53Z"
        },
        {
          "tag": "v1.1.17",
          "kind": "patch",
          "published_at": "2025-11-17T17:20:44Z"
        },
        {
          "tag": "v1.1.16",
          "kind": "patch",
          "published_at": "2025-11-17T12:08:10Z"
        },
        {
          "tag": "v1.1.15",
          "kind": "patch",
          "published_at": "2025-11-16T14:27:20Z"
        },
        {
          "tag": "v1.1.14",
          "kind": "patch",
          "published_at": "2025-11-16T13:03:11Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "063f146be7608cc9c6c1d5f8a56b7b4228b04a57",
          "body": "The stdin-inherited hang wasn't fully fixed by the previous commit: it\nonly covered hitch's own internal git calls (git_operations.rs). The\ntest framework has a completely separate, independent code path —\nGitCommandRunner::run (tests/test_framework/command_runners.rs) spawns\ngit directly for test s\n[…]\nextra insurance against\nany editor invocation regardless of platform/config.\n\nUpdated the AGENTS.md gotcha entry to record that this class of bug\nneeds checking in both src/ and tests/test_framework/.",
          "is_bot": false,
          "headline": "fix: null stdin in test framework's own git/hitch subprocess spawns",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-24T10:37:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "277ba9bb9b3769ffca1b0605cdfd32875b09a979",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.3.2",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-24T10:00:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "37ff823d970f5210d41bde532c2309fbb70136a2",
          "body": "Command::output() captures stdout/stderr but leaves stdin at Rust's\ndefault of inherited, not null. Any git subprocess hitch spawns could\ntherefore block reading from the actual terminal hitch (or the test\nsuite) was launched from, if git or anything it shells out to in turn\n(GPG/SSH commit signing,\n[…]\nfails fast instead of hanging. hitch resolve --tool\n(git mergetool) is left untouched since it's deliberately interactive.\n\nRecorded as a gotcha in AGENTS.md for future git/gh Command::new call\nsites.",
          "is_bot": false,
          "headline": "fix: never let git/gh subprocesses inherit a real terminal's stdin",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-24T09:39:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6052658d54e61e6c01183f04c5c8309f972998ff",
          "body": null,
          "is_bot": false,
          "headline": "docs: add merge-conflict handling flow to README",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-24T09:17:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ac5bb050bee4e6d2735d80dbbe82f5dfabb658dd",
          "body": "Phase 5, part 3 (final): the forcing function that keeps recorded\nresolutions from becoming permanent load-bearing infrastructure.\n\nhitch doctor now reports every recorded resolution and its age;\nhitch doctor --max-resolution-age-days <n> exits nonzero when any exceed\nthe threshold, so CI can gate o\n[…]\now each red-team\ncritical is met; AGENTS.md names src/utils/resolutions.rs; SKILL.md adds\nthe resolve/replay/resolutions/doctor commands. Full suite green\n(303 integration + 55 lib), clippy/fmt clean.",
          "is_bot": false,
          "headline": "feat(doctor): resolution debt SLA + docs; complete phase 5",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-24T09:16:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d2901040db06126a54bb71976c9a01b41de5d000",
          "body": "Phase 5, part 2: opt-in replay. hitch rebuild --replay-resolutions makes\na conflicting branch first try a recorded, content-addressed resolution\nbefore being held — turning a previously hand-resolved peer conflict back\ninto a clean compose without re-resolving it. rebuild_environment gains a\nrebuild\n[…]\n up-front refusal is skipped when\nreplaying so a resolution gets its chance (the in-loop halt still fires\non a genuinely unresolved conflict). Verified end-to-end locally and by\ntwo integration tests.",
          "is_bot": false,
          "headline": "feat(rebuild): replay recorded resolutions with --replay-resolutions",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-24T09:11:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "80ca524ad8b5b2071b85e0cb5421fe3c7aeec0d1",
          "body": "…sed refs\n\nPhase 5, part 1 of docs/merge-conflict-handling-plan.md: recording and\ninspection (replay comes next). hitch resolve --continue --record (or\n--share, which also pushes) stores a resolved peer-vs-peer conflict as a\nref under refs/hitch/resolutions/<key>, where <key> is a git hash over\nthe \n[…]\nch_refspec, push_refspec. Recording verified end-to-end locally\n(resolve --record -> resolutions list -> show); replay is not wired yet,\nso a recorded resolution has no effect on rebuild until part 2.",
          "is_bot": false,
          "headline": "feat(resolutions): record peer-conflict resolutions as content-addres…",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-24T09:05:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2962824ecc3d9a36ee15abf91079e47a0ae40b0b",
          "body": "Last deferred phase-3 piece from docs/merge-conflict-handling-plan.md.\nhitch tree threads GlobalContext through its recursive display and\nruns the same local-only, no-fetch preflight_compatibility_report_local\nhitch status already uses, so a promoted branch that would be held on\nthe next rebuild shows the same ⛔ glyph and \"conflicts with X — held\non rebuild\" suffix in both commands. Phase 3 is now fully done.",
          "is_bot": false,
          "headline": "feat(status): show ⛔ glyph for branches that would be held on rebuild",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-24T08:54:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "317e0731899c99890eec87001197b60cb1a812c6",
          "body": "Adds a maintenance section up front: update the relevant section in\nthe same change that makes it stale, record new gotchas the way the\nmerge-base bug already is, fix wrong lines on sight even if unrelated\nto the task at hand.",
          "is_bot": false,
          "headline": "docs: tell agents to keep AGENTS.md up to date",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T17:01:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cf318154db413004ad24e8675795516b9acf7702",
          "body": "AGENTS.md is the actual content: build/test/lint commands, an\narchitecture map (where domain logic vs CLI parsing lives, the\ngit_operations.rs single-shell-out-point pattern, the three-command\nchecklist for registering a new CLI command), known dead/aspirational\ncode not to build on, house conventio\n[…]\n\nanyone touching merge-tree invocations next.\n\nCLAUDE.md is a thin pointer that imports it via Claude Code's @-file\nsyntax, so there's a single source of truth instead of two documents\ndrifting apart.",
          "is_bot": false,
          "headline": "docs: add AGENTS.md and CLAUDE.md",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T17:01:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4e7146a109a9e3bf93209dba7fad2bed02674fa9",
          "body": "Phase 4 of docs/merge-conflict-handling-plan.md.\n\nhitch resolve <env> [--branch b] [--continue|--abort|--path] [--tool]\nauto-detects mode from what the branch actually conflicts with:\n\n- Mode A (conflicts with base): checks out the branch and runs\n  git rebase <base>, handing off to plain Git's own \n[…]\nrified end-to-end locally for both modes plus 4 new integration\ntests; full suite (300 tests) green, clippy/fmt clean.\n\nDetails in docs/merge-conflict-handling-plan.md's Implementation\nstatus section.",
          "is_bot": false,
          "headline": "feat(resolve): guided Mode A/B conflict resolution + fix merge-base bug",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T16:59:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "79b6dad553c67e5f88857990df5e8bc80391a9ac",
          "body": "Fourth and last deferred phase-3 piece from\ndocs/merge-conflict-handling-plan.md. hitch rebuild <env> --pr-comments\nupserts a single marker-tagged comment on each promoted branch's open PR\nreporting its held/re-included status: a newly-held branch gets one\ncomment (pair, conflicting files, exact fix\n[…]\n\nrepo with an open PR, which is why it's unit-tested at the message/marker\nlevel instead — flagged explicitly in the plan doc's status tracker.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(rebuild): opt-in GitHub PR status comments for held branches",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T16:42:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "890bdba564f7364123409ab183321c46f5fbb37b",
          "body": "Third deferred phase-3 piece from docs/merge-conflict-handling-plan.md.\nAdds preflight_compatibility_report_local: a local-only, no-fetch variant\nof the phase-2 exhaustive preflight, for callers like hitch status that\nrun on every invocation and must stay fast and offline (unlike\nrebuild --dry-run a\n[…]\nural change\nthan status's addition. Left as still-deferred, along with PR comment\nintegration, in the plan doc's Implementation status section.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(status): show ⛔ glyph for branches that would be held on rebuild",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T16:37:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5a03cde9970605d9f9f41a01c010e50ac3d2bcef",
          "body": "…om clean\n\nSecond deferred phase-3 piece from docs/merge-conflict-handling-plan.md.\nhitch rebuild now exits 2 (not 0) when it succeeded but held one or more\nconflicting branches, so CI can warn on holds without treating them as a\nbuild failure, and --dry-run reflects the same code for what a real ru\n[…]\nts.\n\nAdds HitchCommandResult::assert_exit_code to the test framework and uses\nit in the two eject/dry-run rebuild tests that now expect exit 2.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(rebuild): exit-code taxonomy — distinguish held-but-succeeded fr…",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T16:32:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "89c28d231e11f3f517feed7d0cb9584b95353f16",
          "body": "Completes the visibility piece of phase 3 deferred in the previous\ncommit. hitch conflicts <env> runs the same exhaustive preflight\nhitch rebuild --dry-run uses, scoped to one environment, and reports\nevery currently-conflicting branch with its pair, files, the exact\nfix command, and what the enviro\n[…]\n status/tree glyph, PR\ncomment integration, and the exit-code taxonomy are still owed before\nphase 3 is fully done; phases 4-5 haven't started.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(conflicts): add hitch conflicts <env> standup command",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T16:27:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "858630ecb19d2d3723fa07f90337f68798050997",
          "body": "… opt-out\n\nPhase 3 of docs/merge-conflict-handling-plan.md. Adds Environment.on_conflict\n(eject | halt, default eject) and makes rebuild_environment act on it live,\nbranch by branch, using the pinned SHAs from phase 1: a branch that conflicts\nis excluded from the composition and recorded as held (wi\n[…]\nert the new eject behavior\n(success, held branch, dev built from the rest) and adds coverage for\n--dry-run and the --on-conflict halt override.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(rebuild): eject-and-continue conflict policy (default) with halt…",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T16:21:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bfc521014891ca6148fff60123c75e1d41aa7d06",
          "body": "Phase 2 of docs/merge-conflict-handling-plan.md. Adds\npreflight_compatibility_report, which simulates the same sequential\nsquash composition as preflight_compatibility_merge_tree but skips a\nconflicting branch and keeps folding instead of stopping at the first\none, so a single rebuild names every br\n[…]\nbranches touching the\nsame file, the second is now correctly attributed to the first\n(the branch it actually collides with) instead of to base.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(rebuild): exhaustive conflict attribution + --dry-run",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T16:10:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "12e0f4966dc3cd1a9cee882e73ec422e82ccf1b9",
          "body": "…via CAS\n\nPhase 1 of docs/merge-conflict-handling-plan.md. rebuild_environment no\nlonger touches the user's checkout: it syncs and pins base + every\npromoted branch to concrete SHAs once, composes the squash merges in a\ndisposable linked worktree (sibling to the repo, never inside .git),\nand publish\n[…]\ncus.\n\nNew GitOperations primitives: add_worktree, remove_worktree,\nupdate_ref_cas, update_ref, rev_parse_opt, force_push_with_lease,\nworkdir().\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(rebuild): compose environments in an isolated worktree, publish …",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T16:06:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "df553389d487c1ceed67f59d67528636933e1e50",
          "body": "Synthesized from a five-design panel (git-native, merge-queue,\ninteractive-UX, state-machine, team-product lenses), judged by three\nindependent reviewers, and stress-tested with a red-team pass. Covers\nworktree-isolated rebuilds, eject-and-continue policy, pair\nattribution, guided Mode A/B resolution, and hardened shared\nresolutions via rerere-backed refs.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add merge-conflict handling design plan",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T15:54:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c563e32b4f757b5a95dddeca8b7d39eaace7fb53",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.3.1",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T11:50:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a98e60302a0fa7780f340c52bce307575b9b85ce",
          "body": "Interactive prompts had no non-interactive escape hatch, so `hitch rebuild`\nwould block forever in CI or when driven by an agent. Every prompt now goes\nthrough the `Confirm` trait, selected once from a new global `--yes` / `-y`\nflag (also settable via `HITCH_YES=1`). Without a TTY and without `--yes\n[…]\nhitch setup` remains an interactive wizard (branch selection has no\nnon-interactive default) but now errors up front when there is no terminal.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cli)!: add global --yes and unify confirmation prompt handling",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-23T11:43:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "abdf0fad9721767dc6410bb0f06909d827003ffc",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.49",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-22T14:05:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e5aa6f7d665ff46c6d0b438ee075580f5eea87ea",
          "body": "- discover_branches now pre-checks environment names alongside bases\n- save_protection_cache writes protected branches list to\n  ~/.config/hitch/<owner>_<repo>_protection.json after setup\n- hitch status warns when env/bases aren't covered by ruleset",
          "is_bot": false,
          "headline": "feat(setup): pre-check env branches, cache protection state",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-22T13:59:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c711da50f1942894ef27c978468cb1a6081f8f9c",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.48",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-22T13:51:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "065752104746735c9a356e58bf9832e3bd3a7d77",
          "body": null,
          "is_bot": false,
          "headline": "style: apply cargo fmt and fix clippy warning",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-22T13:47:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b8f97a98ecbc588340a86b536a94dab4fa4b68ef",
          "body": "Replace GitHub App + backend token exchange with per-user deploy keys:\n- hitch setup generates ed25519 SSH key (~/.ssh/hitch_<owner>_<repo>)\n- Adds public key as repo deploy key via gh api\n- Sets git config core.sshCommand to use the key\n- Creates ruleset with DeployKey bypass (actor_type: DeployKey\n[…]\nha2\ndeps. Remove token-auth push URL machinery from git_operations\nand release.rs.\n\nFix gh_api_post -> gh_api_with_body to not override caller's\nHTTP method (was appending -X POST after -X PUT/other).",
          "is_bot": false,
          "headline": "refactor(setup): switch to deploy key bypass, drop backend/App auth",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-22T13:46:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "30f5792c99a551753bf91ee8349597f1cd04291d",
          "body": "Add hitch setup command for interactive branch protection configuration:\n- Branch discovery from hitch.json + remote listing\n- Interactive branch selection via inquire crate\n- OAuth device flow for Hitch GitHub App authentication\n- Ruleset creation/activation via gh api\n- Token storage in ~/.config/\n[…]\non tokens.\n\nUpdate hitch release: resolve_push_url injects installation tokens\nfor authenticated pushes to protected branches.\n\nAdd git_operations: push_branch_to_url, push_tag_to_url,\nget_remote_url.",
          "is_bot": false,
          "headline": "feat(setup): hitch setup command + GitHub App token infrastructure",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-22T13:28:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "efa897efccdc18d679419cd5c1b576f0884b743a",
          "body": null,
          "is_bot": false,
          "headline": "drop pr branch",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-22T12:52:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4acab3c6d414dd43036cfb2712d9162edfb0004a",
          "body": null,
          "is_bot": false,
          "headline": "Create hitch-setup-commands-plan.md",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-21T10:08:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cf44833e18f2791c919d00c1dcdd80f9f4561717",
          "body": null,
          "is_bot": false,
          "headline": "snap",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-21T10:05:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0866beac22d9e20b1d864e286d0ca3afc9cbe33b",
          "body": "…tion",
          "is_bot": false,
          "headline": "docs: add hitch doctor and hitch pr to README key commands and pr sec…",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-21T09:53:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff93c3213c5b224fa7fa2c0c5060e0c81cb25e4d",
          "body": "- New  command: infers PR base from promotion targets'\n  shared base, pushes branch, shells out to gh pr create\n-  flag: create branch, push, and open PR in one step\n- README: add GitHub Pull Requests with Hitch section documenting\n  ruleset setup, workflow, and caveats\n- release --squash help: note that squash mode prevents GitHub\n  auto-detecting merged PRs",
          "is_bot": false,
          "headline": "feat: add github PR workflow commands (hitch pr, branch --pr)",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-21T09:36:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "30e71c9ed92dbfa99ad6f7a21b8fd2ee02e97fd7",
          "body": null,
          "is_bot": false,
          "headline": "Create github-pr-workflow-plan.md",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-21T09:24:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6526d3e05f22bef09ed86aea6371e783e5b63b6b",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.47",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-17T11:25:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb2186c9c3ccc45590bbb4118faab8891ed7d15a",
          "body": "`hitch completion <shell>` failed with \"Not in a git repository\" when run\nfrom anywhere but a repo, because GlobalContext (which opens one) was\nconstructed unconditionally before command dispatch — even though completion\nonly reads the static clap command tree and never touches git. It's now\nhandled in main() before GlobalContext exists, so e.g. piping straight into\na completions folder from $HOME now works.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(completion): allow completion generation outside a git repository",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-17T11:18:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3f2c77191c69b34a6e880b8adbbfe738774d7048",
          "body": "Releasing an environment to a target branch also rebuilds any environment\nwhose base is that target (transitively) — non-obvious enough that a\nteammate mistook the extra rebuild for a bug. Document what triggers it, that\nit's usually a no-op, and the --no-rebuild-dependents escape hatch.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: explain release's automatic dependent-environment rebuild",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-17T11:18:14Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f78522473d8d54990394505b2e151ec4cd68979e",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.46",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-17T11:02:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fea4db2f966307b294115bbe960b43934072f5c7",
          "body": "hitch completion <shell> previously emitted hand-written, hardcoded scripts\nper shell — already stale, missing tree/approvals/branch/cleanup/diff/set\nentirely and none of their flags, with no way to keep them in sync as\ncommands were added.\n\nMoved the Cli/Commands clap definitions from the hitch bin\n[…]\netions for bash/zsh/fish/powershell/elvish now\ncover every subcommand and per-command flag automatically and can never drift\nout of sync again.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(completion): generate shell completions from the real command tree",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-17T10:55:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ce4563c15aa8cd5394f13ddc2d266cc643f30099",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.45",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-17T10:51:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5a18d849bd10a9634e41ec761b4da2ec3129b4fa",
          "body": "Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "style: apply rustfmt",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-17T10:44:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7fde49e89e370b9c3c277ece1a0aea8f27abed1f",
          "body": "Teammates who never personally ran `hitch init` got \"hitch-metadata branch\ndoes not exist locally\" from every hitch command, even after `git pull` and\neven though the metadata was sitting on origin the whole time — a plain pull\non another branch never creates a local tracking branch for a separate b\n[…]\nit` or any\nmetadata-writing command create a brand new, unrelated root commit — silently\ndiverging from the team's real hitch-metadata history.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(metadata): bootstrap hitch-metadata locally from origin when missing",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-17T10:42:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "33ce6cd8290ebe8480363b49d1e21c76f5399ef9",
          "body": "…checkout\n\nEvery metadata write (lock/unlock, promote/demote, approvals, init) used to\nrecord the current branch, checkout hitch-metadata, commit, then checkout\nback — needing an auto-stash to protect it and leaving users stranded on the\nwrong branch if the return checkout failed. Reads already avoi\n[…]\nite\nbootstraps hitch-metadata as a root commit through the same path, so\ncreate_orphan_branch is now dead code and removed along with its test.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(metadata): write hitch-metadata via git plumbing instead of …",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-17T10:13:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ad1f82a8b10418505b12e4e28f08eaea0cf2adf2",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.44",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-10T09:24:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "65b9112d84c8845557828a8632e56c2e989be05c",
          "body": "Formats the new code and pre-existing drift so the release pre-flight\n(cargo fmt --check) passes.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "style: apply rustfmt",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-10T09:12:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "458542cf993e69b0557fb31dc0975cc76878211c",
          "body": "squash_merge already commits each branch, so the trailing commit was always\na no-op yet logged a misleading \"Committed release\" line. Remove it; squash\nreleases produce one squash commit per branch.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(release): drop no-op commit in squash mode",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-10T09:08:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e3f72c5aa4e57c60f7ad2841f0e8d8271d31e4d2",
          "body": "When demoting a source environment, the success message counted the full\nresolved batch even though demotion no-ops branches not present in the\ntarget. Report the count of branches actually promoted to the target.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(demote): report the number of branches actually demoted",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-10T09:08:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f2d834179f72041509979dbbb6a3165e718401f1",
          "body": "Previously it locked (a no-op if already locked) and then always unlocked,\nso calling it on an already-locked environment would release a lock it did\nnot take. Not reachable through current commands (callers pre-check), but a\nfootgun for re-entrant/force paths. Now it checks the lock state first and\nonly locks/unlocks when it actually acquires the lock.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(lock): with_locked_env only unlocks a lock it acquired",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-10T09:08:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "70134dc94536d0fd5e83ab610c4e7ec25fa9c86a",
          "body": "promote/demote created one approval request per branch, each in its own\nmetadata transaction (commit + push). If a later branch failed — e.g. it\nalready had a pending request — the earlier branches' requests were left\ncommitted, and retrying could worsen the inconsistent state.\n\nAdd create_approval_\n[…]\nbatch. promote and demote now use it (demote also filters to branches\nactually promoted to the target). Removes the now-unused singular helper.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(approvals): create batched approval requests atomically",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-10T09:04:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7bbb70f41df451f5ecbf343deab1aa1242de7a2b",
          "body": "Post-release pruning iterated every environment and removed merged\nbranches from their metadata without checking locks. A locked env has its\nrebuild skipped, so pruning its metadata left the metadata and the built\nbranch inconsistent (and mutated an env another operation holds a lock\non). Skip pruni\n[…]\nnv being released is locked by\nthis release itself and is still pruned. Deferred prunes are picked up the\nnext time the environment is rebuilt.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(release): don't prune promoted branches from locked environments",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-10T08:58:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5c802060b793b8fd1f341989260ce1d187dc8cc2",
          "body": "When demoting a source environment into an approval-gated target, the\napproval loop created a request for every resolved branch even though\nvalidation only requires one to be present. Branches never promoted to\nthe target got bogus approval requests that demote nothing when approved.\nOnly create requests for branches actually promoted to the environment.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(demote): skip approval requests for branches not in the target env",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-10T08:56:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "25e62700bb80ff0b0d26c8917a84b06a93436d79",
          "body": "Two release correctness bugs:\n\n1. The post-release rebuild skipped the just-released environment because\n   the release holds its lock (\"Skipping rebuild of '<env>' because it is\n   locked\"), pruning its metadata but leaving its branch stale against the\n   new base. The released env is now rebuilt d\n[…]\nto its pre-release commit on\n   failure (new GitOperations::reset_hard_to helper).\n\nAdds regression tests for both; each fails without its fix.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(release): rebuild released env when locked, and make release atomic",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-10T08:56:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ecb1d1122c457ac3ba64944d41992015dc190783",
          "body": null,
          "is_bot": false,
          "headline": "fixes",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-08T11:34:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "70ff8ef91cd4be3dd7f5cbb8996c167a3e156abd",
          "body": null,
          "is_bot": false,
          "headline": "Update icon.json",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-07T07:39:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "421b8f7c7498ee2f6fec9e50c8cae8235caa66b4",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.12",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T17:49:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6b48e912e61888d726d875439405f2219c135fdb",
          "body": null,
          "is_bot": false,
          "headline": "updates to ui",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T17:48:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "486908f91164a5096a6370d67176bae36da919fa",
          "body": "test_add_and_commit_empty_files asserted the old behavior (error on a\nmissing file), which the tolerate-missing-optional-file fix intentionally\nchanged. Rewrite it to verify present files still commit while a missing\none is skipped, and that committing only-missing files is a no-op.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: update add_and_commit test for skip-missing-file behavior",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T17:27:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a6bace7c3c40d6e4c120aa599072199543758c23",
          "body": "The cross-platform integration suite spawns hitch+git per test. On the\nWindows runner the detached 'git gc --auto' inherits the captured stdout\npipe, so Command::output() never sees EOF and the job hangs. Disable\ngc.auto for tests and add a 25m timeout so any future hang fails fast\nwith retained logs.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci: bound Windows test job + disable git auto-gc to prevent hangs",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T17:21:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "da52b74c150c0173d844567dc6982ee881072203",
          "body": "Mutating ops run with the default StdinConfirm, but the desktop has no\nstdin — so the rebuild force-push prompt read EOF, declined, and the\nrebuilt branch was silently never pushed to the remote. The UI button is\nthe confirmation, so wire AlwaysYesConfirm into the op context (used only\nby the locked mutating commands; read-only context_at is untouched).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "desktop: auto-confirm the rebuild force-push prompt",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T17:17:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "47feef54e48ad8e34e4305060063394115956cb6",
          "body": "A hitch-metadata branch without a .gitignore (older init, or removed)\nbroke every metadata mutation: add_and_commit([\"hitch.json\",\n\".gitignore\"]) hard-failed on 'git add .gitignore' ('did not match any\nfiles'), leaving hitch.json staged but uncommitted. The operation was\nthen stranded on hitch-metad\n[…]\nld be\noverwritten by checkout'. Skip an add whose pathspec matches nothing,\nmatching how the commit step already tolerates 'nothing to commit'.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: tolerate a missing optional file in add_and_commit",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T17:17:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "be4dda7ab3b0d47a402641ad15a0b6886f97b750",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.11",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T16:51:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de5bb3fd453029bd5303262043efcb6a46f47114",
          "body": "GitHub rewrites spaces to dots in release asset filenames, so the DMG\nuploaded as 'Hitch Desktop_<ver>.dmg' became 'Hitch.Desktop_<ver>.dmg'\nwhile the cask URL used %20 — a guaranteed 404 on brew install. Rename\nthe DMG to a hyphenated, space-free name before upload and point the\ncask at that exact name.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "desktop-release: use space-free DMG asset name so the cask URL resolves",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T16:50:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dade21d6db195e601a0e5ecf214f721ea1ea69e7",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.43",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T16:37:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f96383842317d1e1703742ac5526096d4c65254d",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: sync Cargo.lock for hitch-desktop 0.0.10",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T16:29:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "85185268295db184fff750901853781223327874",
          "body": "The integration test harness looked for target/debug/hitch, but on\nWindows the executable is hitch.exe, so every add/remove integration\ntest failed with 'Could not find or build hitch binary'. Use\nCARGO_BIN_EXE_hitch when present and fall back to a path built with\nenv::consts::EXE_SUFFIX.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: locate hitch binary with platform exe suffix on Windows",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T16:29:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1cfce8561a900f27b8526cb0822a10e27b255da1",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "dist: allow-dirty ci so the desktop-v* trigger exclusion sticks",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T16:20:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "27ced8e23b0945c2b773cbd73754525f9650b44f",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.10",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T16:17:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d17f6be9f83317eb0ac99adfa1c0f0c5fb53bcb0",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.42",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T16:16:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6e167d0d2d97445d4f408bee74e74b38f36afb4a",
          "body": "- clippy: drop needless lifetime in timeline.rs (needless_lifetimes)\n- audit: bump plist 1.8->1.10 (quick-xml 0.38->0.41) for RUSTSEC-2026-0194/0195\n- desktop: pin pnpm@10.30.3 (corepack was pulling pnpm 11 -> ERR_PNPM_IGNORED_BUILDS)\n- release: exclude desktop-v* tags from the cargo-dist CLI release trigger\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ci): green CI + unblock desktop release",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T16:11:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dd4fc18871851ec38a3e83bff89923e550a4e48b",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.9",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T15:58:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "36b9aa4029789e5408492901366eedc2c80a6c86",
          "body": null,
          "is_bot": false,
          "headline": "Update desktop-release.yml",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T15:57:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "86ae75dd7bee20bdd2e245a030d33314d9825c95",
          "body": null,
          "is_bot": false,
          "headline": "desktop fixes",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T15:54:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5419e1c87dea88c2f31b3ac09f451b550cdc37b1",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.8",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T15:49:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d2ad9cd0097817072aca71f7aa5d4fa77568c8b0",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.41",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T15:40:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bb4b8e9f06bfb22c2b42bc585d8e3377d4597c36",
          "body": null,
          "is_bot": false,
          "headline": "Update dist-workspace.toml",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T15:36:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2382b3dd72a210a46485c4ad49f86093bdaa9bde",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to v1.2.40",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T15:18:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "36c54e95f4118374a6fafea52b78eceb120100c9",
          "body": null,
          "is_bot": false,
          "headline": "release",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T15:14:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4f30ad59adb002aeddff04ee229ddbe42048829b",
          "body": null,
          "is_bot": false,
          "headline": "desktop redesign",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T13:15:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "92b8a5d349abd026838fe1a9fefb55ece0d957ef",
          "body": null,
          "is_bot": false,
          "headline": "snap",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-07-06T12:20:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0f52882988155660367ec2fb37ebf50bcc8aea08",
          "body": null,
          "is_bot": false,
          "headline": "Update repo.rs",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-06-30T14:45:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "342eafcb23d842184ff13a306bac77228be855ec",
          "body": "Delete several dead/unused helper methods from GitOperations (rev_parse_fallback, get_git_config, set_git_config, unset_git_config, stash_top_message) to reduce unused code surface. Also minor whitespace/formatting adjustment in a repo_lock test assertion for readability.",
          "is_bot": false,
          "headline": "Remove unused git helper functions",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-06-30T14:40:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f0fab11a80740f5712c4e1e4eed6992a98565b1d",
          "body": null,
          "is_bot": false,
          "headline": "Update git_operations.rs",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-06-30T14:38:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5340eea8bc379d3f3abd88bd1827cd5cd0faa60e",
          "body": "Introduce a repository-wide lock (src/utils/repo_lock.rs) to serialize mutating Hitch operations and prevent concurrent clobbering of the working tree. Acquire the lock in CLI main (for mutating commands) and in the desktop app for promote/rebuild/release. Make approvals aware of which subcommands m\n[…]\n boundary) and document behavior.\n\nSmall fixes: validation disallows names starting with '-', detached-HEAD handling cleaned up, and various minor refactors to keep rollback/metadata handling simpler.",
          "is_bot": false,
          "headline": "Add repository lock & approval workflow fixes",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-06-30T14:37:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "82757163cd0311e5363715a190afc432cbdccd1b",
          "body": null,
          "is_bot": false,
          "headline": "updated docs",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-05-28T11:57:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3edaf2a32818cccab54df543b53665bd07d1295a",
          "body": null,
          "is_bot": false,
          "headline": "chore: update Cargo.lock",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T21:15:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "67c3457088cbc65a5c2f668906b4d74cc4724e82",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.7",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T21:13:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a1384e377e1fe23ea5da8cb4785b2b7b747ee1c6",
          "body": null,
          "is_bot": false,
          "headline": "feat: add variant and noShadow props to HitchIcon for title bar",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T21:12:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "06251dd4da18491ba5cb9b5afe1d812a3684c6d4",
          "body": null,
          "is_bot": false,
          "headline": "fix: remove invalid iOS config from tauri.conf.json",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T21:02:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f9abad8a2b22b2fee552a7abf09df227f6fba885",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.6",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T21:01:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ce89ab3c099983b32fa726b602c228aea9e0f6eb",
          "body": null,
          "is_bot": false,
          "headline": "fix: correct iOS minimumSystemVersion key in tauri.conf.json",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T21:00:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "569a9dc803f67cee3278a703f919c11832e6e7d2",
          "body": null,
          "is_bot": false,
          "headline": "chore: update Cargo.lock",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T20:59:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "530177a727e6e19017a7c149510530491e534338",
          "body": null,
          "is_bot": false,
          "headline": "fix: enable ad-hoc code signing and disable hardened runtime for macOS",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T20:58:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e4aa46c6ea0fa18589e34e069a32e4158f3f5024",
          "body": null,
          "is_bot": false,
          "headline": "fix: correct version extraction and URL encode DMG name in cask",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T20:26:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9e6255a63b4374fdee7ec562c195325541074624",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.5",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T20:17:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dc5c1a2ce3b6aa5d53b7628b8745f267d7e324fa",
          "body": null,
          "is_bot": false,
          "headline": "chore: update Cargo.lock",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T20:17:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1d94b66c2f8cd9804110e11248decd4834fe96f2",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.4",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T20:16:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "40c3f7832e6288d1b40725748c882fddec3b070e",
          "body": null,
          "is_bot": false,
          "headline": "fix: create release if not exists before uploading DMG",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T20:15:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6efbb4dacbe80376b781210d503bba330f11f913",
          "body": null,
          "is_bot": false,
          "headline": "fix: correct bundle path in desktop release workflow",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T20:03:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "34432516ded3d54e2abbf7753133cf644f09ab75",
          "body": null,
          "is_bot": false,
          "headline": "fix: narrow release.yml tag pattern to only v* tags",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T20:01:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3814e5b23d3cc2d6b90f2859c59bc1aa16c72046",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump desktop version to v0.0.3",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T19:58:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1d4ff836b31a9edba10c790b6b2d80a94a1970ec",
          "body": null,
          "is_bot": false,
          "headline": "fix: use desktop-v prefix for desktop release tags",
          "author_name": "Martin Page",
          "author_login": "doomedramen",
          "committed_at": "2026-04-18T19:56:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 48,
      "commits_last_year": 461,
      "latest_release_at": "2026-07-24T10:04:41Z",
      "latest_release_tag": "v1.3.2",
      "releases_from_tags": false,
      "days_since_last_push": 1,
      "active_weeks_last_year": 21,
      "days_since_latest_release": 1,
      "mean_days_between_releases": 2
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "has_description": false,
      "has_contributing": false,
      "health_percentage": 28,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "hitch",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "command-line-utilities"
          ],
          "ecosystem": "crates",
          "matches_repo": null,
          "registry_url": "https://crates.io/crates/hitch",
          "is_deprecated": false,
          "latest_version": "0.1.1",
          "repository_url": null,
          "versions_count": 2,
          "total_downloads": 42,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 5,
          "first_published_at": "2026-03-17T16:41:38.470268Z",
          "latest_published_at": "2026-03-17T21:13:55.651630Z",
          "latest_version_yanked": false,
          "days_since_latest_publish": 129
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "justfile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "crates/hitch-desktop/tsconfig.json"
      ],
      "toolchain_manifests": [
        "Cargo.toml",
        "crates/hitch-desktop/src-tauri/Cargo.toml"
      ],
      "largest_source_bytes": 96079,
      "source_files_sampled": 138,
      "oversized_source_files": 3,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 12291
    },
    "dependencies": {
      "manifests": [
        "Cargo.toml"
      ],
      "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": [
        "crates"
      ],
      "dependencies": [
        {
          "name": "clap",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "4.5"
        },
        {
          "name": "anyhow",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.0"
        },
        {
          "name": "thiserror",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "2.0"
        },
        {
          "name": "serde",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.0"
        },
        {
          "name": "serde_json",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.0"
        },
        {
          "name": "colored",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "3.1"
        },
        {
          "name": "clap_complete",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "4.5"
        },
        {
          "name": "git2",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.20"
        },
        {
          "name": "chrono",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.4"
        },
        {
          "name": "uuid",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.0"
        },
        {
          "name": "tokio",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1.49"
        },
        {
          "name": "fs4",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "1"
        },
        {
          "name": "inquire",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "0.7"
        },
        {
          "name": "tempfile",
          "manifest": "Cargo.toml",
          "ecosystem": "crates",
          "version_constraint": "3.25"
        }
      ],
      "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": 0,
        "merged_prs": 21,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 31
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "doomedramen",
          "commits": 432,
          "avatar_url": "https://avatars.githubusercontent.com/u/445964?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "desktop-release.yml",
        "release.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "Cargo.lock",
        "pnpm-lock.yaml"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 3 contributing companies or organizations -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 0,
            "reason": "license file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "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": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "32 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "063f146be7608cc9c6c1d5f8a56b7b4228b04a57",
        "ran_at": "2026-07-25T17:42:34Z",
        "aggregate_score": 4.1,
        "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-24T10:46:00Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-01-19T13:15:42Z",
      "ci_last_conclusion": "FAILURE",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/doomedramen/hitch",
    "host": "github.com",
    "name": "hitch",
    "owner": "doomedramen"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 52,
      "inputs": {
        "security": 41,
        "vitality": 83,
        "community": 12,
        "governance": 46,
        "engineering": 68
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 83,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 78,
            "inputs": {
              "commits_last_year": 461,
              "human_commit_share": 1,
              "days_since_last_push": 1,
              "active_weeks_last_year": 21
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "21/52 weeks with commits",
                "points": 14.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 21
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "461 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 461
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 48,
              "latest_release_tag": "v1.3.2",
              "releases_from_tags": false,
              "days_since_latest_release": 1,
              "mean_days_between_releases": 2
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "48 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 48
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~2 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 2
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 1,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 1 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 12,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "critical",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 25,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "no license file detected",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "license_absent",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "critical",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 13,
            "inputs": {
              "packages": [
                "hitch"
              ],
              "dependents": null,
              "ecosystems": "crates",
              "total_downloads": 42,
              "monthly_downloads": 5
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "5 downloads/month across crates",
                "points": 10.4,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 5,
                      "ecosystems": "crates"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "at_risk",
        "name": "Sustainability & Governance",
        "value": 46,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 29,
            "inputs": {
              "merged_prs": 21,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 31
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "21/52 decided PRs merged",
                "points": 15.4,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 21,
                      "decided": 52
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 57,
            "inputs": {
              "followers": 58,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "doomedramen",
              "public_repos": 33,
              "account_age_days": 5757
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "58 followers of doomedramen",
                "points": 12.7,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 58,
                      "login": "doomedramen"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "33 public repos, account ~15 yr old",
                "points": 23.2,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 33
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 15
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 92,
            "inputs": {
              "packages": [
                "hitch"
              ],
              "ecosystems": "crates",
              "any_deprecated": false,
              "min_days_since_publish": 129
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on crates",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "crates"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 129 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 129
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "2 published versions",
                "points": 12,
                "status": "partial",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 68,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "3 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": "https://doomedramen.github.io/hitch/",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://doomedramen.github.io/hitch/",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 41,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "packaging"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 41,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 4.1
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "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": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "32 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "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": 3
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 81,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.84,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 12291
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "84 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 84,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 71,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "Cargo.lock",
                "pnpm-lock.yaml"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "justfile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "crates/hitch-desktop/tsconfig.json"
              ],
              "agent_commit_share": 0.32,
              "toolchain_manifests": [
                "Cargo.toml",
                "crates/hitch-desktop/src-tauri/Cargo.toml"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "justfile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "justfile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "crates/hitch-desktop/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "crates/hitch-desktop/tsconfig.json"
                    }
                  }
                ],
                "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": "32 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 32,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "primary_language": "Rust",
              "largest_source_bytes": 96079,
              "source_files_sampled": 138,
              "oversized_source_files": 3
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Rust (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Rust"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "3/138 source files over 60KB",
                "points": 53.8,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 138,
                      "oversized": 3
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-25T17:42:39.179052Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/d/doomedramen/hitch.svg",
  "full_name": "doomedramen/hitch",
  "license_state": "absent",
  "license_spdx": null
}

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

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

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