Публічний реєстр
Звіт про здоров'я програмного забезпеченнясхема 0.27.0 · метрики 1.13.0 · 2026-07-25 17:42 UTC

doomedramen / hitch

RustЛіцензію не виявлено★ 0 зірок⑂ 0 форківз лист. 2025 р.Переглянути на GitHub ↗

doomedramen/hitch має індекс здоров’я 52 зі 100, що відповідає смузі «Помірний». Найвищий показник — Vitality (83/100), найнижчий — Community & Adoption (12/100). Останнє оновлення було 1 день тому. Більшість нещодавньої роботи виконує один учасник.

52
загалом / 100
Помірний

Індекс здоров'я програмного забезпечення

Метрики згруповано у зважені категорії на шкалі 1–100. Загальна оцінка починається як їхнє середнє; коли публічні дані активують Політику юрисдикцій високого ризику, рейтинг коригується й отримує верхню межу 49 («Під ризиком»). Готовність до ШІ не входить до індексу.

52
Відмінний85-100Зразковий; відповідає практично всім перевіреним критеріям
Добрий70-84Здоровий; незначні прогалини
Помірний50-69Прийнятний, але з помітними прогалинами; рекомендовано перевірку
У зоні ризику30-49Суттєві слабкі місця; впровадження потребує обережності
Критичний1-29Серйозні проблеми (покинутий, єдиний мейнтейнер, без базової гігієни)
ЖиттєздатністьСпільнота тавпровадженняСталість таврядуванняІнженернаякістьБезпекаГотовність доШІ

Профіль оцінок

Кожна вісь — окрема категорія. Форма важить більше, ніж середнє: здоровий об'єкт заповнює всю фігуру, тоді як профіль із піками та провалами означає, що сила в одному вимірі маскує ризик в іншому.

Власність

Martin PageОсобистий обліковий запис
58 підписників33 публічні репозиторіїз жовт. 2010 р.@Pikl-Insurance

Цей репозиторій належить особистому обліковому запису. Проєкт з єдиним власником несе більший ризик безперервності, ніж підтримуваний організацією.

Пакетні екосистеми

РеєстрПакетВерсіяЗавантажень / місВерсіїОстання публікаціяТеги
crates.iohitch0.1.152129 днів томуcommand-line-utilities

Метрики за категоріями

Життєздатність

Чи живий проєкт — чи пишеться код і чи виходять релізи?

83Добрий · 22% загального індексу
Як обчислюється оцінка
36/36Свіжість push — останній push 1 дн. тому
14.5/36Ритм комітів — 21/52 тижнів із комітами
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
Як обчислюється оцінка
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
Як обчислюється оцінка
22.5/22.5README
0/22.5Ліцензія — файлу ліцензії не виявлено
0/18Настанови CONTRIBUTING
0/13.5Кодекс поведінки
0/7.2Шаблон issue
0/6.3Шаблон PR
Використані вхідні дані
has_readmeтак
has_licenseні
has_contributingні
has_issue_templateні
has_code_of_conductні
has_pull_request_templateні
Як обчислюється оцінка
10.4/80Щомісячні завантаження — 5 завантажень/місяць у crates
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Вирішення issue — немає issue або даних
15.4/38.3Прийняття PR — злито 21/52 вирішених PR
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
Виключено з оцінювання (немає даних або не застосовно): Вирішення issue. Залишкові ваги перенормовано.
Як обчислюється оцінка
10/30Підтримка власника — особистий (користувацький) обліковий запис
0/20Верифікований домен — не застосовно до користувацьких облікових записів
12.7/25Охоплення власника — 58 підписників у doomedramen
23.2/25Послужний список — 33 публічних репозиторіїв, вік облікового запису ~15 р.
Використані вхідні дані
followers58
owner_typeUser
is_verified
owner_logindoomedramen
public_repos33
account_age_days5 757
Виключено з оцінювання (немає даних або не застосовно): Верифікований домен. Залишкові ваги перенормовано.
Як обчислюється оцінка
25/25Опубліковано й доступно — 1 пакет(ів) у crates
35/35Свіжість публікацій — остання публікація 129 дн. тому
12/20Історія версій — 2 опублікованих версій
20/20Не застарілий — активний, не deprecated і не yanked
Використані вхідні дані
packageshitch
ecosystemscrates
any_deprecatedні
min_days_since_publish129

Інженерна якість

Чи наявні базові інженерні практики та документація?

68Помірний · 20% загального індексу
Як обчислюється оцінка
24/24Процеси CI — 3 процес(ів) CI
24/24Наявні тести
0/16Конфігурація лінтера
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. Залишкові ваги перенормовано.
Як обчислюється оцінка
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. Залишкові ваги перенормовано.

Готовність до ШІ

Наскільки репозиторій оснащений для розробки та супроводу за участі ШІ-агентів? Незалежний, експериментальний бейдж — вага 0.0, тож він подається окремо і не впливає на загальний індекс здоров'я.

81Добрий · 0% загального індексу
Як обчислюється оцінка
45/45Інструкції для агентів — AGENTS.md, CLAUDE.md
0/15Машиночитана документація (llms.txt)
40/40Читабельна історія комітів — намір зазначено у 84 з 100 людських комітів (структурований заголовок або пояснювальний текст)
Використані вхідні дані
has_llms_txtні
legible_history_share0,84
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes12 291
Як обчислюється оцінка
18/18Розгортання однією командою — justfile
22/22Автоматизовані тести
0/11Конфігурація лінтера / форматера
11/11Статична перевірка типів — crates/hitch-desktop/tsconfig.json
10/10Відтворюване середовище — lockfile
10/10Підтверджена практика роботи з агентами — 32 з останніх 100 комітів створено агентом або з його зазначенням
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Керовані розміри файлів — 3/138 файлів вихідного коду понад 60 КБ
Використані вхідні дані
primary_languageRust
largest_source_bytes96 079
source_files_sampled138
oversized_source_files3

Ключові факти

0зірок GitHub
1контриб'юторів
461комітів за останні 12 місяців
1днів від останнього пушу
48релізів
1бас-фактор
0відкритих issue
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.