Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-25 17:42 UTC

doomedramen / hitch

RustSin licencia detectada★ 0 estrellas⑂ 0 forksdesde nov 2025Ver en GitHub ↗

doomedramen/hitch tiene un índice de salud de 52 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Vitality (83/100) y la más baja, Community & Adoption (12/100). Se actualizó por última vez hace 1 día. Una sola persona concentra la mayor parte del trabajo reciente.

52
global / 100
Moderado

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala de 1 a 100. El resultado global parte de su media; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe el límite 49 (En riesgo). Preparación para IA queda fuera.

52
Excelente85-100Ejemplar; cumple prácticamente todos los criterios evaluados
Bueno70-84Saludable; carencias menores
Moderado50-69Aceptable con carencias notables; se recomienda revisión
En riesgo30-49Debilidades significativas; su adopción exige cautela
Crítico1-29Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

Cada eje es una categoría. La forma importa más que la media: un proyecto sano llena toda la figura, mientras que un perfil de picos y cráteres indica que la fortaleza en una dimensión enmascara el riesgo en otra.

Titularidad

Martin PageCuenta personal
58 seguidores33 repositorios públicosdesde oct 2010@Pikl-Insurance

Este repositorio pertenece a una cuenta personal. Un proyecto con un único propietario conlleva más riesgo de continuidad que uno respaldado por una organización.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicaciónEtiquetas
crates.iohitch0.1.152hace 129 díascommand-line-utilities

Métricas por categoría

Vitalidad

¿Está vivo el proyecto: se escribe código y se publican versiones?

83Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 1 días
14.5/36Cadencia de commits — 21/52 semanas con commits
18/18Volumen de commits — 461 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year461
human_commit_share1
days_since_last_push1
active_weeks_last_year21
Cómo se puntúa
27/27Publica versiones — 48 versiones publicadas
36/36Recencia de las versiones — última versión hace 1 días
27/27Cadencia de publicación — una versión cada ~2 días
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Datos de entrada utilizados
releases_count48
latest_release_tagv1.3.2
releases_from_tagsno
days_since_latest_release1
mean_days_between_releases2

Comunidad y Adopción

¿Tiene el proyecto usuarios, descargas, atención y unas condiciones acogedoras para quienes contribuyen?

12Crítico · 18% del índice global
Cómo se puntúa
0/60Estrellas — 0 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
0/22.5Licencia — no se detectó ningún archivo de licencia
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_licenseno
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno
Cómo se puntúa
10.4/80Descargas mensuales — 5 descargas/mes en crates
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packageshitch
dependents
ecosystemscrates
total_downloads42
monthly_downloads5
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

¿Sobrevivirá el proyecto a sus personas: factor bus, capacidad de respuesta, quién lo respalda y mantenimiento del paquete?

46En riesgo · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
10/10OpenSSF Scorecard: Contributors — project has 3 contributing companies or organizations -- score normalized to 10
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
0/46.8Resolución de issues — sin issues o sin datos
15.4/38.3Aceptación de PR — 21/52 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs21
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs31
Excluidos de la puntuación (sin datos o no aplicable): Resolución de issues. Los pesos restantes se han renormalizado.
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
12.7/25Alcance del propietario — 58 seguidores de doomedramen
23.2/25Trayectoria — 33 repos públicos, cuenta de ~15 años
Datos de entrada utilizados
followers58
owner_typeUser
is_verified
owner_logindoomedramen
public_repos33
account_age_days5757
Excluidos de la puntuación (sin datos o no aplicable): Dominio verificado. Los pesos restantes se han renormalizado.
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en crates
35/35Recencia de publicación — última publicación hace 129 días
12/20Historial de versiones — 2 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packageshitch
ecosystemscrates
any_deprecatedno
min_days_since_publish129

Calidad de Ingeniería

¿Existen unas prácticas mínimas de ingeniería y documentación?

68Moderado · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 3 flujo(s) de trabajo
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — sin datos
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_configno
has_precommit_configno
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: CI-Tests. Los pesos restantes se han renormalizado.
Cómo se puntúa
30/30README
25/25Directorio de documentación
15/15Sitio de documentación / página del proyecto — https://doomedramen.github.io/hitch/
0/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepagehttps://doomedramen.github.io/hitch/
has_readme
has_docs_dir
has_descriptionno

Seguridad

¿Son sólidas las prácticas visibles de seguridad y de cadena de suministro, sin exposición jurisdiccional de alto riesgo sin resolver?

41En riesgo · 16% del índice global
Cómo se puntúa
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 — sin datos
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.5Licencia — 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 — sin datos
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
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate4,1
Excluidos de la puntuación (sin datos o no aplicable): ci_tests, packaging. Los pesos restantes se han renormalizado.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Es una insignia independiente y experimental — peso 0,0, de modo que se presenta por separado y no afecta a la puntuación de salud global.

81Bueno · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — AGENTS.md, CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 84 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,84
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes12.291
Cómo se puntúa
18/18Arranque con un solo comando — justfile
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — crates/hitch-desktop/tsconfig.json
10/10Entorno reproducible — lockfile
10/10Práctica demostrada con agentes — 32 de los últimos 100 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfilesCargo.lock, pnpm-lock.yaml
has_dockerfileno
typed_language
bootstrap_filesjustfile
has_devcontainerno
has_linter_configno
typecheck_configscrates/hitch-desktop/tsconfig.json
agent_commit_share0,32
toolchain_manifestsCargo.toml, crates/hitch-desktop/src-tauri/Cargo.toml
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Rust (tipado estático)
53.8/55Tamaños de archivo manejables — 3/138 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageRust
largest_source_bytes96.079
source_files_sampled138
oversized_source_files3

Datos clave

0estrellas de GitHub
1contribuidores
461commits en los últimos 12 meses
1días desde el último push
48versiones publicadas
1factor bus
0issues abiertas
crates.ioecosistemas de paquetes

Advertencias de recopilación de datos

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

Más detalle

OpenSSF Scorecard 4.1 / 10
4.1agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).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
n/dCI-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
n/dPackagingpackaging 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
Dependencias directas 14
RegistroPaqueteRestricción de versiónManifiesto
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
Todas las dependencias no recopilado

No fue posible recopilar el conjunto de dependencias resuelto para este informe: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Informe JSON sin procesar legible por máquina
{
  "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
}

Las puntuaciones son señales, no garantías. Reflejan prácticas públicamente visibles en GitHub; no son una auditoría de código ni una garantía de seguridad.

Los datos ausentes se excluyen y los pesos se renormalizan; nunca se puntúan como cero. La metodología es versionada y abierta: métricas v1.13.0, esquema v0.27.0 — metodología completa · wiki de métricas.

Cómo se sitúa un resultado dentro del registro general: estadísticas agregadascrates.io.