Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-23 19:03 UTC

jasonraimondi / plan-bender

Structured planning pipeline for AI coding agents — interview, PRD, issues, review, implement, archive

GoMIT★ 5 estrellas⑂ 0 forksdesde mar 2026Ver en GitHub ↗

jasonraimondi/plan-bender tiene un índice de salud de 56 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Vitality (79/100) y la más baja, Community & Adoption (29/100). Se actualizó por última vez hace 5 días. Una sola persona concentra la mayor parte del trabajo reciente.

56
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.

56
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

Jason RaimondiCuenta personal
101 seguidores186 repositorios públicosdesde oct 2013@intelligems-io

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ón
Gogithub.com/jasonraimondi/plan-benderv0.0.71-61hace 7 días

Métricas por categoría

Vitalidad

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

79Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 5 días
8.3/36Cadencia de commits — 12/52 semanas con commits
18/18Volumen de commits — 388 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_year388
human_commit_share1
days_since_last_push5
active_weeks_last_year12
Cómo se puntúa
27/27Publica versiones — 58 versiones publicadas
36/36Recencia de las versiones — última versión hace 5 días
27/27Cadencia de publicación — una versión cada ~6 días
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Datos de entrada utilizados
releases_count58
latest_release_tagv0.0.71
releases_from_tagsno
days_since_latest_release5
mean_days_between_releases6

Comunidad y Adopción

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

29Crítico · 18% del índice global
Cómo se puntúa
9.8/60Estrellas — 5 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars5
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
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_license
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sostenibilidad y Gobernanza

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

56Moderado · 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 4 contributing companies or organizations
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
31.5/38.3Aceptación de PR — 28/34 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/18 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs28
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs6
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
14.4/25Alcance del propietario — 101 seguidores de jasonraimondi
25/25Trayectoria — 186 repos públicos, cuenta de ~12 años
Datos de entrada utilizados
followers101
owner_typeUser
is_verified
owner_loginjasonraimondi
public_repos186
account_age_days4652
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 go
35/35Recencia de publicación — última publicación hace 7 días
20/20Historial de versiones — 61 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesgithub.com/jasonraimondi/plan-bender
ecosystemsgo
any_deprecatedno
min_days_since_publish7

Calidad de Ingeniería

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

67Moderado · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 2 flujo(s) de trabajo
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 3 out of 3 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_configno
has_precommit_configno

Documentación

65Moderado
Cómo se puntúa
30/30README
25/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
0/10Topics
0/10Wiki
Datos de entrada utilizados
topics
has_wikino
homepage
has_readme
has_docs_dir
has_description

Seguridad

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

44En riesgo · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 3 out of 3 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/18 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 4 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not 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
6/7.5Vulnerabilities — 2 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated18
scorecard_versionv5.5.0
checks_inconclusive0
scorecard_aggregate4,4

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.

76Bueno · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 100 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share1
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes707
Cómo se puntúa
18/18Arranque con un solo comando — mise.toml
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — Go (tipado estático)
10/10Entorno reproducible — lockfile
0/10Práctica demostrada con agentes — ningún commit con autoría de agente entre los últimos 100
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
lockfilesgo.sum
has_dockerfileno
typed_language
bootstrap_filesmise.toml
has_devcontainerno
has_linter_configno
typecheck_configs
agent_commit_share0
toolchain_manifestsgo.mod
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Go (tipado estático)
55/55Tamaños de archivo manejables — 0/167 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes25.732
source_files_sampled167
oversized_source_files0

Datos clave

5estrellas de GitHub
1contribuidores
388commits en los últimos 12 meses
5días desde el último push
58versiones publicadas
1factor bus
0issues abiertas
Goecosistemas de paquetes

Advertencias de recopilación de datos

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

Más detalle

OpenSSF Scorecard 4.4 / 10
4.4agregado

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-23 19:03 UTC

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests3 out of 3 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/18 approved changesets -- score normalized to 0
10Contributorsproject has 4 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
8Vulnerabilities2 existing vulnerabilities detected
Dependencias directas 7
RegistroPaqueteRestricción de versiónManifiesto
Gogithub.com/charmbracelet/huhv1.0.0go.mod
Gogithub.com/hasura/go-graphql-clientv0.15.1go.mod
Gogithub.com/spf13/cobrav1.10.2go.mod
Gogithub.com/stretchr/testifyv1.11.1go.mod
Gogolang.org/x/sysv0.41.0go.mod
Gogolang.org/x/toolsv0.42.0go.mod
Gogopkg.in/yaml.v3v3.0.1go.mod
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": 1472,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Go": 731458,
        "Shell": 2288,
        "Go Template": 64155
      },
      "pushed_at": "2026-07-17T21:38:03Z",
      "created_at": "2026-03-28T01:49:49Z",
      "owner_type": "User",
      "updated_at": "2026-07-17T21:38:07Z",
      "description": "Structured planning pipeline for AI coding agents — interview, PRD, issues, review, implement, archive",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": "jasonraimondi.com",
      "name": "Jason Raimondi",
      "type": "User",
      "login": "jasonraimondi",
      "company": "@intelligems-io ",
      "location": null,
      "followers": 101,
      "avatar_url": "https://avatars.githubusercontent.com/u/5787967?v=4",
      "created_at": "2013-10-27T17:20:27Z",
      "is_verified": null,
      "public_repos": 186,
      "account_age_days": 4652
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.0.71",
          "kind": "patch",
          "published_at": "2026-07-17T21:34:12Z"
        },
        {
          "tag": "v0.0.70",
          "kind": "patch",
          "published_at": "2026-06-08T02:45:11Z"
        },
        {
          "tag": "v0.0.62",
          "kind": "patch",
          "published_at": "2026-06-06T03:36:37Z"
        },
        {
          "tag": "v0.0.61",
          "kind": "patch",
          "published_at": "2026-06-03T13:50:25Z"
        },
        {
          "tag": "v0.0.60",
          "kind": "patch",
          "published_at": "2026-06-03T02:08:06Z"
        },
        {
          "tag": "v0.0.58",
          "kind": "patch",
          "published_at": "2026-05-29T18:42:00Z"
        },
        {
          "tag": "v0.0.57",
          "kind": "patch",
          "published_at": "2026-05-28T03:28:13Z"
        },
        {
          "tag": "v0.0.56",
          "kind": "patch",
          "published_at": "2026-05-28T02:29:13Z"
        },
        {
          "tag": "v0.0.55",
          "kind": "patch",
          "published_at": "2026-05-26T02:59:43Z"
        },
        {
          "tag": "v0.0.54",
          "kind": "patch",
          "published_at": "2026-05-25T01:37:24Z"
        },
        {
          "tag": "v0.0.53",
          "kind": "patch",
          "published_at": "2026-05-22T13:08:07Z"
        },
        {
          "tag": "v0.0.52",
          "kind": "patch",
          "published_at": "2026-05-21T02:41:04Z"
        },
        {
          "tag": "v0.0.51",
          "kind": "patch",
          "published_at": "2026-05-21T02:08:03Z"
        },
        {
          "tag": "v0.0.50",
          "kind": "patch",
          "published_at": "2026-05-20T20:19:45Z"
        },
        {
          "tag": "v0.0.49",
          "kind": "patch",
          "published_at": "2026-05-20T12:25:07Z"
        },
        {
          "tag": "v0.0.48",
          "kind": "patch",
          "published_at": "2026-05-15T21:49:39Z"
        },
        {
          "tag": "v0.0.47",
          "kind": "patch",
          "published_at": "2026-05-15T20:10:28Z"
        },
        {
          "tag": "v0.0.46",
          "kind": "patch",
          "published_at": "2026-05-15T03:07:32Z"
        },
        {
          "tag": "v0.0.45",
          "kind": "patch",
          "published_at": "2026-05-14T21:30:57Z"
        },
        {
          "tag": "v0.0.44",
          "kind": "patch",
          "published_at": "2026-05-14T02:40:47Z"
        },
        {
          "tag": "v0.0.43",
          "kind": "patch",
          "published_at": "2026-05-12T18:24:51Z"
        },
        {
          "tag": "v0.0.42",
          "kind": "patch",
          "published_at": "2026-05-12T13:38:56Z"
        },
        {
          "tag": "v0.0.41",
          "kind": "patch",
          "published_at": "2026-05-08T19:43:03Z"
        },
        {
          "tag": "v0.0.40",
          "kind": "patch",
          "published_at": "2026-05-05T20:33:32Z"
        },
        {
          "tag": "v0.0.39",
          "kind": "patch",
          "published_at": "2026-05-05T16:54:48Z"
        },
        {
          "tag": "v0.0.38",
          "kind": "patch",
          "published_at": "2026-05-25T01:38:08Z"
        },
        {
          "tag": "v0.0.37",
          "kind": "patch",
          "published_at": "2026-05-04T02:56:26Z"
        },
        {
          "tag": "v0.0.36",
          "kind": "patch",
          "published_at": "2026-05-03T03:08:39Z"
        },
        {
          "tag": "v0.0.35",
          "kind": "patch",
          "published_at": "2026-05-03T01:06:08Z"
        },
        {
          "tag": "v0.0.34",
          "kind": "patch",
          "published_at": "2026-05-02T18:06:34Z"
        },
        {
          "tag": "v0.0.33",
          "kind": "patch",
          "published_at": "2026-05-01T19:44:52Z"
        },
        {
          "tag": "v0.0.31",
          "kind": "patch",
          "published_at": "2026-04-30T19:48:18Z"
        },
        {
          "tag": "v0.0.30",
          "kind": "patch",
          "published_at": "2026-04-30T19:20:34Z"
        },
        {
          "tag": "v0.0.29",
          "kind": "patch",
          "published_at": "2026-04-24T14:53:21Z"
        },
        {
          "tag": "v0.0.28",
          "kind": "patch",
          "published_at": "2026-04-23T02:27:11Z"
        },
        {
          "tag": "v0.0.27",
          "kind": "patch",
          "published_at": "2026-04-23T02:21:15Z"
        },
        {
          "tag": "v0.0.26",
          "kind": "patch",
          "published_at": "2026-04-18T21:18:12Z"
        },
        {
          "tag": "v0.0.25",
          "kind": "patch",
          "published_at": "2026-04-17T15:28:27Z"
        },
        {
          "tag": "v0.0.24",
          "kind": "patch",
          "published_at": "2026-04-14T18:13:55Z"
        },
        {
          "tag": "v0.0.23",
          "kind": "patch",
          "published_at": "2026-04-09T18:18:47Z"
        },
        {
          "tag": "v0.0.22",
          "kind": "patch",
          "published_at": "2026-04-08T14:50:03Z"
        },
        {
          "tag": "v0.0.18",
          "kind": "patch",
          "published_at": "2026-04-02T04:03:56Z"
        },
        {
          "tag": "v0.0.17",
          "kind": "patch",
          "published_at": "2026-04-02T03:30:40Z"
        },
        {
          "tag": "v0.0.16",
          "kind": "patch",
          "published_at": "2026-04-01T15:17:27Z"
        },
        {
          "tag": "v0.0.15",
          "kind": "patch",
          "published_at": "2026-04-01T14:40:43Z"
        },
        {
          "tag": "v0.0.14",
          "kind": "patch",
          "published_at": "2026-04-01T13:53:13Z"
        },
        {
          "tag": "v0.0.13",
          "kind": "patch",
          "published_at": "2026-03-31T03:28:22Z"
        },
        {
          "tag": "v0.0.12",
          "kind": "patch",
          "published_at": "2026-03-30T19:28:06Z"
        },
        {
          "tag": "v0.0.11",
          "kind": "patch",
          "published_at": "2026-03-30T15:47:15Z"
        },
        {
          "tag": "v0.0.10",
          "kind": "patch",
          "published_at": "2026-03-29T03:48:36Z"
        },
        {
          "tag": "v0.0.9",
          "kind": "patch",
          "published_at": "2026-03-29T03:17:44Z"
        },
        {
          "tag": "v0.0.8",
          "kind": "patch",
          "published_at": "2026-03-29T01:26:39Z"
        },
        {
          "tag": "v0.0.7",
          "kind": "patch",
          "published_at": "2026-03-29T00:11:59Z"
        },
        {
          "tag": "v0.0.6",
          "kind": "patch",
          "published_at": "2026-03-29T00:09:22Z"
        },
        {
          "tag": "v0.0.5",
          "kind": "patch",
          "published_at": "2026-03-28T23:43:21Z"
        },
        {
          "tag": "v0.0.4",
          "kind": "patch",
          "published_at": "2026-03-28T23:40:10Z"
        },
        {
          "tag": "v0.0.3",
          "kind": "patch",
          "published_at": "2026-03-28T23:33:29Z"
        },
        {
          "tag": "v0.0.2",
          "kind": "patch",
          "published_at": "2026-03-28T22:17:12Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "744099fd2f3c926c93124083b6f3d3543c6e7984",
          "body": null,
          "is_bot": false,
          "headline": "docs(changelog): stamp v0.0.70 and v0.0.71",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-07-17T21:38:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d6d6a9fb887dc995a2911c17839825302a968fb3",
          "body": null,
          "is_bot": false,
          "headline": "feat(template): disable model invocation on all bender skills",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-07-16T01:50:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ce20eedfde4a905d599710369b070400584cdc7",
          "body": "…spatcher (#34)\n\n* feat(status): add needs-input workflow status\n\n* feat(cli): add merge command for dependency-ordered merge-back\n\nExpose the merge-back step as a standalone `pb merge <slug>` / `pba merge`\nso it survives the upcoming removal of the dispatch loop. Purely additive:\nthe Run/RunBatch/r\n[…]\n still advertised `pb dispatch <slug>`, a command\nremoved in this branch, and setup_test pinned the stale string. Relocate the\nimplementation entry point to the agent section as /bender-implement-prd.",
          "is_bot": false,
          "headline": "feat(dispatch)!: replace cold-subprocess engine with live Workflow di…",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-08T02:38:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8eaee07b9cad30f1e622d7826590799b1539c880",
          "body": null,
          "is_bot": false,
          "headline": "docs(changelog): stamp v0.0.61 and v0.0.62",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-06T12:56:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "40648264c29a47bd00f458edf108d7a967c4c9e8",
          "body": "When `no_implement: true` (default false), `pb setup`/`pb generate` skip\ngenerating the implementation skills (bender-implement-prd,\nbender-implement-hitl, bender-implement-issue) and drop them from the\norchestrator menu. Flipping the flag on removes any previously generated\ncopies and prunes their installed symlinks on the next run, reusing the\nexisting wipe-and-prune path.",
          "is_bot": false,
          "headline": "feat(config): add no_implement flag to skip implementation skills",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-06T03:34:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3eaed5a8f16311e57e0bf40cf02f14085142cd4a",
          "body": "…-issues skills\n\nBoth were superseded by bender-write-plan, which drafts the PRD and\ndecomposes issues in one pass. Slated for removal in >=0.0.60. pb setup\nno longer generates either skill and the pipeline menu no longer lists\nthem. The plan-bender-agent write-prd CLI command is retained —\nbender-write-plan still uses it to write prd.json.",
          "is_bot": false,
          "headline": "feat(template)!: remove deprecated bender-write-prd and bender-prd-to…",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-03T13:47:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4048d0783fcd868d32c7e7aaa937be9db0cbe0fe",
          "body": null,
          "is_bot": false,
          "headline": "docs(changelog): stamp v0.0.53 through v0.0.60",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-03T02:15:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a841fff6ad54f3f1d9fc3ed62a82d43ed11c360b",
          "body": "The skill still described the pre-integration-worktree model: after_batch\nrunning in the repo root, dispatch refusing a dirty tree, and HEAD being\ncaptured/restored. Align with docs/cli.md + ADR-0003 — merge-back, status\nflips, and after_batch run in the per-slug integration worktree; the parent\nrepo's HEAD is never touched and a dirty parent is allowed.",
          "is_bot": false,
          "headline": "docs(cli): correct stale dispatch lifecycle in plan-bender-cli skill",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-03T01:52:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7079c271719b71d61aaa74075cf1316b6b6c0f35",
          "body": "- rename \"completion sentinel\" -> \"completion marker\" everywhere; the\n  <pba:complete/> line is a log marker, not dispatch's completion signal\n  (the in-review status flip is). pba complete JSON field sentinel->marker.\n  Glossary entries added to CONTEXT.md.\n- hide the `completion` command so it no \n[…]\ne line\n  (root SilenceUsage otherwise hid them)\n- plan-not-found: drop the leaked reading-prd/ENOENT chain\n- docs: open the browser on linux/windows too, not just macOS\n- setup: add -y short for --yes",
          "is_bot": false,
          "headline": "fix(cli): polish command surface from CLI review",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-03T01:37:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "903b0110d6de6ac13f9aecb3686fb4dd78859550",
          "body": "Regeneration only ever removed the per-skill dirs still present in the\ntemplate set, so renamed, removed, or filtered-out skills (e.g. backend\nskills with Linear disabled) were orphaned in .plan-bender/skills/ and\ntheir installed symlinks left dangling in each agent's skills dir.\n\nGenerateSkills now\n[…]\nngling symlinks that\npoint into that source dir. Real dirs and symlinks pointing elsewhere\nare left alone, so a user's own skills and links from other projects in\na shared user-scoped dir stay intact.",
          "is_bot": false,
          "headline": "fix(cli): prune stale skills on generate/setup",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-03T01:26:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "afc010ba18d20924a260393397998cbb7b2e6fc1",
          "body": "Add a §0 that makes a dispatched sub-agent detect INTEGRATION vs STANDALONE mode up front (cwd contains -wt/, branch contains --, or the prompt's issue is already in-progress with a branch it didn't create). In integration mode: skip §2/§8, never ask the operator (stdout is consumed by dispatch, not\n[…]\ners, so the sub-agent ran the standalone completion flow and stalled dispatch.\n\nAlso fix §9 prose claiming dispatch detects the completion sentinel on stdout; the trigger is the in-review status flip.",
          "is_bot": false,
          "headline": "feat(template): integration-mode preamble for bender-implement-issue",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-03T01:26:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9c1e67a9d751c2e9ba0835e0010c673ce8a835c0",
          "body": "A dispatched sub-agent runs from its worktree, where `pba complete` resolved plans_dir relative to the worktree's own checkout and flipped a copy the dispatcher never re-reads. With a git-tracked plans_dir the two diverge: the worktree shows in-review, the parent stays in-progress, and Verdict block\n[…]\nr defeats.\n\nAlso correct complete.go comments claiming dispatch detects the sentinel on stdout — the contract is the status-file re-read (Verdict); the <pba:complete/> line is a human-readable marker.",
          "is_bot": false,
          "headline": "fix(dispatch): route sub-agent pba complete to the parent plans store",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-06-03T01:26:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4c33afadb50dbdb1c84222f1346c60bd68f93536",
          "body": "\"merge issue #N\" auto-links to an unrelated GitHub issue and the\nplan-local number is meaningless on the remote. Derive the merge commit\nsubject from the issue name, falling back to the branch name.",
          "is_bot": false,
          "headline": "fix(dispatch): use issue name as merge subject instead of plan number",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-29T18:39:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d86ea297351045e417770e843fa118dbe857cb74",
          "body": null,
          "is_bot": false,
          "headline": "fix: stop referencing issue numbers in gh",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-29T18:31:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "643400f9786663d70cd6c2a6912e6a2db21acac3",
          "body": "…near op\n\nEvery Linear read/write now reads the project .plan-bender.json and refuses\nwith an error when it explicitly sets linear.enabled:false, making the flag a\nlive kill-switch. The file's explicit flag is read directly rather than the\nmerged config because mergeLinear only turns enabled on, so a project-level\nfalse could never override a global enable. Threads project root through\nbackend.New -> NewLinear.",
          "is_bot": false,
          "headline": "feat(backend): re-check linear.enabled in project file before each Li…",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-29T18:31:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ef728c2af7dd698d9b141a224fd0350845cb7e63",
          "body": "* docs(adr): record dispatch completion-mode pre-flight prompt\n\nADR 0005 captures the decision to add a pre-flight three-mode prompt\n(merge/branch/pr) before dispatch runs, replacing the unconditional\nPR-at-end step. CONTEXT.md gains \"integration branch\" and \"landing\nbranch\" entries so the prompt UX\n[…]\nker.\n\nThe merge block uses `pba worktree gc <slug>` (which removes the worktree dir\nAND deletes the branch) rather than `git branch -d`, which would fail on a\nbranch still checked out in the worktree.",
          "is_bot": false,
          "headline": "feat(template): three-mode completion prompt for dispatch skills (#33)",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-28T03:26:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "20c2c48d979feb982b86c213ada49aa357ebc9e3",
          "body": "…-plan\n\nThe two skills always ran sequentially with a forced handoff between them.\nCombine them into one bender-write-plan skill that interviews, drafts the\nPRD, and decomposes it into issues in a single pass (honoring\nreview_with_user for the two review checkpoints). Mark the legacy skills\nas deprecated in their frontmatter + body; both still work and will be\nremoved in >=0.0.60.",
          "is_bot": false,
          "headline": "feat(template): combine write-prd and prd-to-issues into bender-write…",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-27T19:42:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "033ef27611d647d16268815c76a245f0ea891b64",
          "body": "feat: ship supporting files alongside SKILL.md in skill templates",
          "is_bot": false,
          "headline": "Merge pull request #32 from jasonraimondi/feat/skill-supporting-files",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-26T02:57:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6a4fef4e8716cc4e4066c91e361df295ccd69278",
          "body": "Drop assertions for the agent-conditional intro and issues URL that\nwere removed in f985c5c. Repoint the multi-agent generate check at\nbender-implement-hitl, which still carries the conditional.",
          "is_bot": false,
          "headline": "test: align interview-me tests with simplified template",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-26T02:56:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "70426f76f13434efa6a2ecea4736cd3e4c2a7df3",
          "body": "Two gaps in skill-template tests:\n\n- bender-sync-linear is filtered out by SkillRequiresBackend when Linear\n  is disabled, but no test asserted the directory was absent or present\n  based on cfg.Linear.Enabled. Now covered both ways.\n\n- The collision check would catch a verbatim SKILL.md silently shadowing\n  the rendered SKILL.md.tmpl body, but only by accident — no test pinned\n  it. Add the body-shadow case alongside the existing NOTE.md collision.",
          "is_bot": false,
          "headline": "test: cover Linear toggle and body-shadow collision cases",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-26T02:48:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "84cafbc8cd05289911b4c9d934c239f69513ba78",
          "body": "Skill.Name was written but never read in production; the map key already\ncarries it. Removing keeps the type minimal and the struct literal honest.\n\nIterate skills and files in sorted order in validate() so collision and\nmissing-body errors are deterministic across runs (map iteration order\notherwise leaks into error messages).",
          "is_bot": false,
          "headline": "refactor(template): drop dead Skill.Name, sort validate errors",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-26T02:48:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f985c5c12e4c4144450e48a0ca78906c6a874050",
          "body": null,
          "is_bot": false,
          "headline": "fix: simplify the interview me skill",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-26T02:43:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c6974cf06d4d2d60eb9607bf1033a7cb06fae9d2",
          "body": "A subdir under .plan-bender/templates/ whose name doesn't match a bundled\nskill was promoted to a phantom skill, then validate() hard-failed on the\nmissing SKILL.md.tmpl body — aborting LoadTemplates for every agent.\n\nAccept an override dir only when its name matches a bundled skill or it\nships its own SKILL.md.tmpl; silently skip the rest.",
          "is_bot": false,
          "headline": "fix(template): ignore stray override dirs instead of bricking the loader",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-26T02:11:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a807d8ac618118b1c645dce800b85fe63edb544e",
          "body": "`pb setup` called GenerateSkills + symlinkSkills directly without the\nwarnStaleTemplateOverrides hop, so a pre-existing flat `{name}.skill.tmpl`\noverride silently vanished through the documented entry point even though\ndocs/configuration.md and ADR 0004 promised a warning.",
          "is_bot": false,
          "headline": "fix(setup): emit stale-override warning from pb setup",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-26T02:11:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90c2b54096c27333960e3669422abea81d99169b",
          "body": null,
          "is_bot": false,
          "headline": "docs: document skill directory layout and supporting files",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-25T16:59:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cfe3a93b566751c5673db404684fcdc21ed48ad9",
          "body": "RemoveAll the per-skill output dir before writing, then render .tmpl\nfiles (stripping the suffix) and copy all other files verbatim,\npreserving subdirectory structure via writeSkill helper.",
          "is_bot": false,
          "headline": "feat: emit skill supporting files into generated skills",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-25T16:52:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "88ed61e961c8c4d6e8425f7f41b637924c4cbdcf",
          "body": null,
          "is_bot": false,
          "headline": "feat: warn on stale flat overrides and dir-located forks",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-25T16:50:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5240e1d840bce512e19b4a4a17332c69ea8f5ca9",
          "body": null,
          "is_bot": false,
          "headline": "feat: validate skill templates have a body and no output collisions",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-25T16:42:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e87b6278f9c1fa6f8bc714524b1c2c377cc34eba",
          "body": "Move embedded *.skill.tmpl flat files into {name}/SKILL.md.tmpl directories.\nChange LoadTemplates to return map[string]Skill (with Main() accessor) instead\nof map[string]string. Update GenerateSkills and all tests accordingly.",
          "is_bot": false,
          "headline": "refactor: skill templates as per-skill directories",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-25T16:37:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3ddd4ffb78949cc81e5e657c756dac338d1e815e",
          "body": null,
          "is_bot": false,
          "headline": "docs: implementation plan for skill supporting files",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-25T16:28:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1a481630b00a2b8e1a91482a9b1be0353a3fbd5b",
          "body": "Skill templates become per-skill directories so they can ship supporting files (e.g. CONTEXT-FORMAT.md) alongside SKILL.md. Records the directory model, the breaking flat-override change, and the domain glossary.",
          "is_bot": false,
          "headline": "docs: design, ADR, glossary for skill supporting files",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-25T02:48:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c0e6d920970230ac2339f7e78094a241e8569dcc",
          "body": null,
          "is_bot": false,
          "headline": "chore(gitignore): ignore serena workspace",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-25T01:35:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e2e52e6046053c59fded3a77c373a67a1b4c1504",
          "body": "Wrap all-setup failures with a sentinel so report_bugs ignores stuck or lock-contention errors. Fold per-issue worktree paths when grouping setup causes.",
          "is_bot": false,
          "headline": "fix(dispatch): limit bug reports to setup failures",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-25T01:34:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "531b6b3cf64d758ea07f6c20dffb2bdf11d20ea3",
          "body": "…failures (#30)\n\n* fix(dispatch): provision worktree skills per-child, surface setup failures\n\nlinkPlansDir symlinked .claude/skills only when the dir was absent in the\nworktree. A repo that git-tracks even one skill makes git recreate\n.claude/skills in every fresh worktree, so the linker skipped an\n[…]\nrop redundant/nonlocal comments in linker tests\n\nRemove two section-label comments that restated the assertions beneath them\nand trim a nonlocal reference to the session retro from a test doc comment.",
          "is_bot": false,
          "headline": "fix(dispatch): provision worktree skills per-child and surface setup …",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-24T16:46:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fe8214e678e6380589a5b7b27f04902f2b1fdfb8",
          "body": "Status transitions (retry/complete/worktree create) committed through the\nwhole-plan validation path, so one rule-invalid issue anywhere blocked\nrecovery of every other issue -- exactly when the status->retry flow is\nneeded most.\n\nAdd CommitTouched, which validates only the mutated entities, skippin\n[…]\ntatus\nflip can't break. The status adapter's Save now uses it. Authoring/sync\ncommits keep whole-plan validation (their only consistency gate), and\n`agent validate` remains the strict whole-plan gate.",
          "is_bot": false,
          "headline": "fix(planrepo): scope status-commit validation to the touched issue (#31)",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-24T16:46:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ee073aa723578494d0961429d435c4f3c38898c5",
          "body": "pb setup now inserts a \"$schema\" key into existing .plan-bender.json /\n.plan-bender.local.json when missing, preserving formatting and unknown\nkeys. Drops the stale pi starter-config assertion.",
          "is_bot": false,
          "headline": "feat(setup): backfill $schema into existing config files",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-22T01:54:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "367efd7964aa93c6e6d6c21e065a84c319252aeb",
          "body": "dc3fbd1 dropped pi from scaffolded configs but left the test asserting\n'\"pi\": true'. Assert pi is absent instead.",
          "is_bot": false,
          "headline": "test(setup): assert pi absent from starter config defaults",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-21T21:52:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d31d1c464f251cd66a811fffafad2460b6f8f3c6",
          "body": "… missing issues/\n\nwrite-prd failed with 'reading prd {slug}/prd.json: no such file' whenever\nthe slug directory already existed without a prd.json (e.g. a leftover/empty\ndir from a prior partial run): OpenOrCreate treated any existing dir as\nloadable. Treat a slug with no prd.json and no issues/ tr\n[…]\nror.\n\nAlso: a missing issues/ dir now means zero issues (not a load error), so a\nfreshly written PRD validates before decomposition; and write-prd/write-issue\naccept '-' as the file arg to read stdin.",
          "is_bot": false,
          "headline": "fix(write-prd): create PRD into existing/empty slug dirs and tolerate…",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-21T21:52:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5248deff190dec94965d56ade86807864d1128d3",
          "body": null,
          "is_bot": false,
          "headline": "docs(changelog): stamp v0.0.51 and v0.0.52",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-21T02:39:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "762d6c96349cff58a917fc35b51139839f5f2ba5",
          "body": null,
          "is_bot": false,
          "headline": "chore(config): enable interview_with_docs",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-21T02:35:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dc3fbd1cc00d1b133619a9752585237eee267997",
          "body": null,
          "is_bot": false,
          "headline": "feat(config): drop pi from starter config defaults",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-21T02:35:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dd1c83d6c109a7b870131c8bc84c3c97ffe6d6a6",
          "body": "pb setup now writes a \"$schema\" key pointing at the published schema so\nnew .plan-bender.json files get editor validation out of the box.",
          "is_bot": false,
          "headline": "feat(config): scaffold new configs with $schema reference",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-21T02:32:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "000a4e570de652e665d597e93b1c60187b4b4f47",
          "body": "Hand-written draft 2020-12 schema modeling the full config (agents\nbool|object union, pipeline/linear/hooks, custom_fields enum rule).\nReference it via $schema for editor validation and autocomplete.",
          "is_bot": false,
          "headline": "feat(config): publish JSON Schema for .plan-bender.json",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-21T02:30:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f52ad3bd953d0fe38070d76ca2f2e69127d3511d",
          "body": "* feat(dispatch): per-slug lock rejects same-slug parallel runs\n\nTryFlock takes a non-blocking exclusive flock and returns ErrLocked on\ncontention so callers can distinguish lock-held from other I/O failures.\nDispatcher.Run acquires {plansDir}/{slug}/.dispatch.lock before any work\nand releases on ex\n[…]\ne the GC integration-branch inline block that duplicated the\nfunction doc, and drop two comments that restated the code (a git\nadd/commit/branch loop and a sleep already explained by the block above).",
          "is_bot": false,
          "headline": "Parallel dispatch + configurable worktree base (#29)",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-21T02:05:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b33a0f2b39bfff843b9bb2d0d4f0acda8903b579",
          "body": null,
          "is_bot": false,
          "headline": "docs(interview-me): default to new plan unless slug named",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-20T19:35:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2fb6625f8c7e8d3252fb2e022a386b4f44cef775",
          "body": "fix(dispatch): dispatch reliability hardening",
          "is_bot": false,
          "headline": "Merge pull request #28 from jasonraimondi/jason/dispatch-reliability",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-20T03:05:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f2f7e954a9161aa7e6dd8895f15dc1854dbceacf",
          "body": "The truncation-race tests used echo, which writes a trailing newline —\nlinePrefixWriter emitted the line through the normal Write path and the\npost-Wait Flush() was never exercised. Swap to printf so the partial-line\nbuffer is the only path that delivers the tail, matching the regression\nthe tests c\n[…]\nir) is asserted to clean up\nits leaked worktree — previously only Claim was covered. The\nlinkPlansDir variant commits .plan-bender to the integration branch to\ntrigger the narrowed real-dir rejection.",
          "is_bot": false,
          "headline": "test(dispatch): exercise flush path and remaining cleanup branches",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-20T03:03:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f2b2662cb4e416d03be242178148c79b5009cd25",
          "body": "A real .plan-bender in the worktree silently routes sub-agent writes away\nfrom the dispatch loop's parent state. Narrow linkPlansDir's real-dir\ntolerance to .claude/skills only (skills are legitimately committed),\nand reject a real .plan-bender so the failure surfaces loudly.\n\nAlso thread caller ctx\n[…]\nubprocess uses a fresh ctx because the subprocess ctx may be\ndeadline-exceeded — otherwise the read fails on lock contention and\nVerdict falls back to exit-code even when the sub-agent flipped status.",
          "is_bot": false,
          "headline": "fix(dispatch): narrow linkPlansDir tolerance and thread ctx into reads",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-20T03:03:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8f94057490ca4eacd3f48d29c2943e04b4e46962",
          "body": "A subprocess_timeout SIGKILL or Ctrl-C cancelling the dispatch loop\nwould otherwise drop the failure-path blocked-state transition and\nleave the issue in-progress for the next loop to re-pick. Route the\ntransition through a fresh ctx bounded by blockTransitionTimeout in\nboth RunSubprocess and markBlockedAndWarn.",
          "is_bot": false,
          "headline": "fix(dispatch): detach blocked-state write from parent ctx",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-20T02:45:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ba4c41b899df4e686296215f6bee1e54b3d5dd1",
          "body": null,
          "is_bot": false,
          "headline": "style(dispatch): drop redundant comments and internal incident slug",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-20T02:44:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7acca6c04ce4d47d658dd1703eed9718017c7955",
          "body": "* jason/dispatch-reliability--2-restructure-subprocess-io:\n  fix(dispatch): kill StdoutPipe/Wait race with line-prefixing writer",
          "is_bot": false,
          "headline": "merge issue #2",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:22:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "78969bdc8469039511b23c2b303540853d16ddd7",
          "body": "Replace cmd.StdoutPipe + an explicit reader goroutine with a\nlinePrefixWriter set as cmd.Stdout in both RunSubprocess and RunHook.\nos/exec now owns the copy goroutine, so cmd.Wait (already bounded by\nWaitDelay from issue 1) is the single synchronization point — the\ndocumented hazard of calling Wait \n[…]\nlonger be\nlost when Wait closes the pipe.\n\nPartial lines buffer until the next newline and Flush emits any\ntrailing fragment after Wait, so a single huge stream-json event is\nnever split or truncated.",
          "is_bot": false,
          "headline": "fix(dispatch): kill StdoutPipe/Wait race with line-prefixing writer",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:21:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2239238abfeac75beeb83d006015be85930682ab",
          "body": "* jason/dispatch-reliability--9-cleanup-leaked-worktree-on-claim-failure:\n  fix(dispatch): clean up a leaked worktree on pre-subprocess failure",
          "is_bot": false,
          "headline": "merge issue #9",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:12:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7d7ade36b9a79a81911f274f7b558aabb964a422",
          "body": "* jason/dispatch-reliability--8-preserve-prior-dispatch-logs:\n  feat(dispatch): append to per-issue log across re-dispatch runs",
          "is_bot": false,
          "headline": "merge issue #8",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:12:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c25355ba0cc500d2f8c57e201f657b204eeaac3d",
          "body": "* jason/dispatch-reliability--7-route-loadissue-shared-planrepo-handle:\n  refactor(dispatch): route loadIssue through the shared planrepo handle",
          "is_bot": false,
          "headline": "merge issue #7",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:12:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6c5f3606f2ac47ac134fc010e6efde97ee18037a",
          "body": "* jason/dispatch-reliability--6-dedupe-block-status-label-helpers:\n  refactor(dispatch): dedupe block-status and label helpers",
          "is_bot": false,
          "headline": "merge issue #6",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:12:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7197fb373bffcb06fe0127a57de36ec71f1f2a45",
          "body": "* jason/dispatch-reliability--5-linkplansdir-tolerate-real-skills-dir:\n  fix(dispatch): tolerate a committed .claude/skills dir in the worktree",
          "is_bot": false,
          "headline": "merge issue #5",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:12:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2b13db3d38251c975e6b7f218c06d41ee5d7d0cc",
          "body": "* jason/dispatch-reliability--4-ctx-aware-plan-lock:\n  feat(planrepo): ctx-aware plan lock acquisition",
          "is_bot": false,
          "headline": "merge issue #4",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:12:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4611302760f959531b3b26df8e821d9ecf1146eb",
          "body": "* jason/dispatch-reliability--3-bound-batch-parallelism:\n  feat(dispatch): bound batch parallelism with pipeline.max_parallel",
          "is_bot": false,
          "headline": "merge issue #3",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:12:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6ac9e21e55c28947f35d06b91b7f79967f2ce340",
          "body": "* jason/dispatch-reliability--1-process-group-kill-waitdelay:\n  fix(dispatch): kill the process group and bound cmd.Wait on timeout",
          "is_bot": false,
          "headline": "merge issue #1",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:12:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6536fb70fdf49e5c527c05b4ea0674d7698fefca",
          "body": "RunBatch previously fanned out one goroutine per ready AFK issue, so a\nplan with 20 ready slices spawned 20 heavyweight `claude` subprocesses at\nonce (model API + MCP servers + a git worktree apiece). Add a worker\npool capped at pipeline.max_parallel (default 3) so the dispatcher\nmatches real machin\n[…]\ntinguishing the two with a plain int isn't possible.\n\nAlso drop RunBatch's always-nil error return (finding #9). The\ngoroutines route every failure through SubResult; the second return\nvalue was dead.",
          "is_bot": false,
          "headline": "feat(dispatch): bound batch parallelism with pipeline.max_parallel",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:12:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0e65743e5543a1997efad21ae70f38b42fa8d39c",
          "body": "Threads ctx through Store.OpenSession, Plans.OpenContext, and LockPlanDir\non Unix (flock LOCK_NB) and Windows (LockFileEx LOCKFILE_FAIL_IMMEDIATELY).\nA canceled or timed-out ctx unwinds a wait for a held plan lock instead of\nblocking unkillably. The uncontended path still acquires on the first\nattempt without consulting ctx. status.Owner.Transition and Claim stop\ndiscarding their ctx.",
          "is_bot": false,
          "headline": "feat(planrepo): ctx-aware plan lock acquisition",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:11:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e3b7e706288f375fbc327a205d37adc1c60eec3d",
          "body": "When runOne failed after worktree.Create but before RunSubprocess\n(Claim, linkPlansDir, before_issue hook, or BuildPrompt), the worktree\nwas left orphaned on disk. Add worktree.Remove and call it from each\nof those failure paths; a removal failure warns but does not mask the\noriginal error.",
          "is_bot": false,
          "headline": "fix(dispatch): clean up a leaked worktree on pre-subprocess failure",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:10:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dcd21cc8a1425dbcf96d54a7569ae87039847d14",
          "body": "Extract the [backlog, todo, in-progress, in-review] blocked-from set\ninto a package-level blockFromStatuses shared by RunSubprocess's block\nhelper and Dispatcher.markBlockedAndWarn.\n\nReplace the duplicated hasLabel helpers in internal/dispatch and\ninternal/plan with a single Issue.HasLabel method on schema.",
          "is_bot": false,
          "headline": "refactor(dispatch): dedupe block-status and label helpers",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:10:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "846c39e480e9fdb87ee775c28ae8c0d081a14b92",
          "body": "A timed-out claude or hook subprocess could hang for the natural\nlifetime of a grandchild process (MCP server, bash tool) that\ninherited the stdout/stderr pipe: the surviving write end keeps the\nI/O-copy goroutine alive so cmd.Wait never returns.\n\nconfigureProcessGroup puts the child in its own proc\n[…]\nhole group, reaping\ngrandchildren so the pipes close. cmd.WaitDelay (10s) backstops\ncmd.Wait regardless. Windows has no process groups, so the helper\nis a no-op there; WaitDelay still bounds the wait.",
          "is_bot": false,
          "headline": "fix(dispatch): kill the process group and bound cmd.Wait on timeout",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:09:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "83b5ec05d6e163630232d84a3eb82dcd113d2c69",
          "body": "RunSubprocess took a plansDir and loadIssue rebuilt a fresh\nplanrepo.NewProd from it on every post-run read. Pass the dispatcher's\nmemoized planrepo.Plans handle in instead, so every read in a Run flows\nthrough the same handle the plansOnce comment claims it does.\n\nCorrect the plansOnce/ownerOnce comments: the status.Owner wraps its own\nplanrepo handle, distinct from `plans`, so reads and status writes never\nshared a handle — only the on-disk plansDir.",
          "is_bot": false,
          "headline": "refactor(dispatch): route loadIssue through the shared planrepo handle",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:08:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "23e0f241ac54d551aab8f264e14ac650b323ef1f",
          "body": "linkPlansDir kept a real directory at the destination but then let\nos.Symlink fail with EEXIST, blocking the issue. Now a non-symlink at\ndst is logged and skipped so dispatch links what it can and proceeds.",
          "is_bot": false,
          "headline": "fix(dispatch): tolerate a committed .claude/skills dir in the worktree",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:07:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bdd955e1c1c74d07d75f68fe3093c9ab301b904a",
          "body": "writeLog truncated the log on every run, so re-dispatching an issue\ndiscarded the prior run's transcript. Open the log with O_APPEND and\nwrite a timestamped run-separator header before each run's output.",
          "is_bot": false,
          "headline": "feat(dispatch): append to per-issue log across re-dispatch runs",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T21:06:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a1439e5f18d709495d44fc7638f8e9432d714bdd",
          "body": "The stuck error reused plan.Resolve's BlockedCount, which counts only\ndependency-blocked issues. An issue blocked operationally (killed sub-agent,\nmerge conflict, failed hook) has no open deps and went uncounted, yielding\na misleading \"0 blocked\" on a run that had just blocked an issue. Count\nstatus==blocked directly and name the IDs so the operator knows what to fix.",
          "is_bot": false,
          "headline": "fix(dispatch): count blocked issues honestly in the stuck error",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T18:38:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "21d52b88530e29473a6a821fa858223380f920ce",
          "body": "A subprocess killed by exec.CommandContext's deadline was indistinguishable\nfrom an OS OOM-kill — both surfaced as \"code -1: signal: killed\". Detect\ncontext.DeadlineExceeded after Wait and name the subprocess_timeout knob in\nthe blocked-state reason.",
          "is_bot": false,
          "headline": "fix(dispatch): report a deadline SIGKILL as a subprocess_timeout",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T18:38:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "84a5bfcb237111792de1b66724a4c481c83d8a66",
          "body": "A sub-agent that ran pba complete (status -> in-review) and was then\nkilled during wrap-up had its finished work downgraded to blocked,\nbecause Verdict ranked exitErr above the post-run status. Make an\nin-review post-status outrank exitErr so completed work merges instead.",
          "is_bot": false,
          "headline": "fix(dispatch): trust in-review post-status over a wrap-up SIGKILL",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T18:38:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a91e216f5058a727d4c1f03b89ff5eb411cd4d86",
          "body": "…#25)\n\nWhen interview_with_docs is true, the bender-interview-me and\nbender-write-prd skills gain a grill-with-docs-style domain-awareness\nblock: glossary challenges, fuzzy-term sharpening, scenario stress-tests,\ncode cross-referencing, inline CONTEXT.md writes, and sparse ADRs.\nbender-interview-me \n[…]\ntioning.\n\nThe flag defaults to false; with it off both skills render byte-identical\nto today. Plumbed field-for-field after report_bugs across the config\nstruct, defaults, merge, and template context.",
          "is_bot": false,
          "headline": "feat(config): add interview_with_docs flag for grill-style planning (…",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-19T17:29:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7ae327781bbc29e17065849147cb7f7d5a97d6b0",
          "body": "feat(sync): publish full plan content to Linear",
          "is_bot": false,
          "headline": "Merge pull request #23 from jasonraimondi/jason/linear-sync-full-content",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T21:47:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b851aa4b6b199a39f055b39c8868a1ab4f9501c3",
          "body": "ADR 0002: push publishes full plan content one-way with plan JSON\ncanonical; pull mirrors back only status, priority, assignee.",
          "is_bot": false,
          "headline": "docs(adr): record one-way Linear sync publish decision",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T20:46:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "92a90a1c3bb402f77780466e2c8a9605548379f0",
          "body": "Add a plan-bender-cli reference skill and a PostToolUse hook that nudges\nupdating SKILL.md and docs/cli.md when CLI-defining Go files change.",
          "is_bot": false,
          "headline": "chore(skills): add plan-bender-cli skill and CLI doc-sync hook",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T20:46:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "db0a9604b2ba22c5542d0213fe4944640d3281f3",
          "body": "Test helpers, fixture constants, and test names referred to plan\nfiles as YAML (issueYAML, loadIssueYAML, *IssueYAML constants,\nTestX_MalformedYAML, Test*Yaml_RoundTrip). The files they produce\nand parse are JSON. Legacy-YAML detection tests and migrate_test.go\nkeep their YAML references intentionally.",
          "is_bot": false,
          "headline": "test: rename stale YAML identifiers to JSON",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T20:45:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "867e8c22c55f61a050e15b075078f9751f2f4bd3",
          "body": "Command help text, an error message, and comments referred to plan\nfiles as YAML; the format is JSON. The subprocess.go \"YAML\nfrontmatter\" comment is left intact — it accurately describes the\nskill body's markdown frontmatter.",
          "is_bot": false,
          "headline": "refactor: replace stale YAML terminology with JSON in source",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T20:45:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1201ff70fab3d541927469ff222932b69c829653",
          "body": "Skill templates described plan files as YAML; the on-disk format is\nJSON. Update the prose so generated skills are accurate.",
          "is_bot": false,
          "headline": "chore(skills): replace stale YAML terminology with JSON in templates",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T20:45:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f252676172a3ee37f34e2a44d119f608232baab4",
          "body": "Plan files migrated from YAML to JSON; scrub user-facing docs so the\ndescribed format matches what's on disk. The `pb migrate` reference\nkeeps `.yaml` since it describes the legacy-to-JSON conversion.",
          "is_bot": false,
          "headline": "docs: replace stale YAML terminology with JSON",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T20:44:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "28d3c2feacbb3ce6dce1adc764ad8e42004f674f",
          "body": "defaultSyncPlanFiles gated skill regeneration on the presence of\n.plan-bender.yaml/.plan-bender.local.yaml. After `pb migrate` those\nfiles no longer exist, so `pb self-update` silently stopped\nregenerating skills. Check the .json config files instead.",
          "is_bot": false,
          "headline": "fix(self-update): detect JSON config files, not legacy YAML",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T20:44:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2d156b6152d2251cd06e44b63ac9dbeeb9648298",
          "body": "…base-flag\n\nfeat(dispatch): add --base flag to pb dispatch",
          "is_bot": false,
          "headline": "Merge pull request #20 from jasonraimondi/jason/dispatch-base--1-add-…",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T18:16:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9621b4acb3df0137a811c6a9607e87c0607b5dae",
          "body": "Test names already describe what they cover; keeping only comments\nthat explain non-obvious setup or assertion intent.",
          "is_bot": false,
          "headline": "chore(tests): prune redundant test-doc comments",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T16:37:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "501659f527c0cd2cf560fc8f598bcc4310ac48f8",
          "body": "Opt-in --base <commit-ish> overrides the auto-detected default branch\nas the integration branch's fork point (or merge target under direct\nstrategy). Validated via git rev-parse before any worktree is created.\nWhen the integration branch already exists from a prior run, an explicit\n--base is ignored with a warning rather than re-forking — re-forking\nwould clobber merged work.\n\nDecision context in docs/adr/0001-dispatch-base-flag-not-default-change.md.",
          "is_bot": false,
          "headline": "feat(dispatch): add --base flag to pb dispatch",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-15T15:22:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bccd5326ea42761334917ed3c4d22e465470f3ca",
          "body": "End-of-session self-improvement pass on plan-bender itself. Scans\nconversation memory, the TodoWrite trail, pb-error-report-*.log files,\nand plan-state anomalies, then writes a structured log to\n.plan-bender/retros/<UTC-timestamp>.log.\n\nSwitched the conditional bug-report test marker from \"pb-error-report-\"\nto \"## Bug reports\" because the retro skill legitimately mentions the\nlog filename pattern in its body; the heading is a more semantic check\nfor whether the footer block rendered.",
          "is_bot": false,
          "headline": "feat(skills): add bender-retrospective skill",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-14T21:26:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "75b2fafa767c034032e4dd945dc0c6bb60ba5b20",
          "body": null,
          "is_bot": false,
          "headline": "chore: prune redundant doc comments",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-14T19:08:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d40b5b0e745d470a8004b4c909b8fd750c798c7b",
          "body": "Tab completion produces slugs like \"jason/plans/foo\" when plansDir\nis \"./jason/plans/\"; the loader joined them twice and reported the\nplan missing. Open/OpenOrCreate now normalize the slug so both bare\nand path-style forms resolve.",
          "is_bot": false,
          "headline": "fix(planrepo): strip plansDir prefix from slug args",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-14T18:40:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb43e4c95569f62d35cfa9ad2b8a656b48d34222",
          "body": null,
          "is_bot": false,
          "headline": "fix(skills): harden HITL handoff flow",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-14T14:55:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d29ce08582b1bb04c27f723b8f0206485fd54bc9",
          "body": null,
          "is_bot": false,
          "headline": "feat(skills): add HITL implementation skill",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-13T02:30:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "965abec6c86b9815b40c07ee1a7deda4fe6ad0bb",
          "body": null,
          "is_bot": false,
          "headline": "chore: run pb migrate",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-13T02:28:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9b5309c023357b4d563c24a4b5cbc926f369da33",
          "body": "feat(locksafe): add plan session lock analyzer",
          "is_bot": false,
          "headline": "Merge pull request #18 from jasonraimondi/refactor/yaml-to-json",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-12T18:19:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "17a61ee0641f43daf97aabeffca0193217e411c7",
          "body": null,
          "is_bot": false,
          "headline": "test(cli): restore cwd in command tests",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-12T15:30:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "75945335af6e99d9cfe22f9bcf78aa6af54040e0",
          "body": null,
          "is_bot": false,
          "headline": "test(locksafe): cover subprocess lock checks",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-12T15:24:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d6c1bbce2b41bb4061b9113583418c693d11da5",
          "body": null,
          "is_bot": false,
          "headline": "feat(locksafe): add plan session analyzer",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-12T13:11:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "73015ca8ad4a0eae96ba90c416678a1a97db4a14",
          "body": "* origin/refactor/internal-comments:\n  style(internal): gofmt struct field alignment in touched files\n  chore(internal): remove noise, redundant, and stale comments\n  fix(cli): strict-decode JSON at write-issue/write-prd boundary\n  fix(config): reject null agent entries\n  fix(skills): drop invalid-J\n[…]\nat(skills): rewrite embedded skill templates for JSON format\n  feat(cli): add pb migrate command for one-shot YAML->JSON conversion\n  refactor!: switch on-disk plan and config format from YAML to JSON",
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'origin/refactor/internal-comments'",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-12T13:11:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d5660a9b89c8f9cb663251c9b91f84304cccbc0b",
          "body": null,
          "is_bot": false,
          "headline": "style(internal): gofmt struct field alignment in touched files",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-12T01:29:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aaca00e6108216e6bb2c7c5a33bb0873338cbf4c",
          "body": "Sub-agents run non-interactively so auto mode doesn't activate.\nAdd Write(*), Edit(*), and scoped Bash rules so worktree sub-agents\ncan implement issues without per-call permission prompts.",
          "is_bot": false,
          "headline": "feat(.claude): add scoped permissions for dispatch sub-agents",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-12T01:19:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "975b5695d5420c2397e457011d4ddebe7860e9ec",
          "body": "…on to worktrees\n\nDispatch sub-agents need Write/Edit/Bash permissions to implement issues.\nsettings.local.json is gitignored globally so new worktrees don't inherit it.\nThis hook copies it from the main repo into each newly created worktree.",
          "is_bot": false,
          "headline": "feat(.claude): add WorktreeCreate hook to propagate settings.local.js…",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-12T01:19:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3f8e544dd811eadc42d9e9061027eac72989da9a",
          "body": "Runs GenerateSkills + symlinkSkills at the end of every successful\nself-update path (already up to date, NPM notice, or direct binary\nreplace). Skips silently when not in a pb project directory.",
          "is_bot": false,
          "headline": "feat(cli): self-update re-generates and symlinks skills after updating",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-12T01:19:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "637b4cb02a9682ab614f51acf2a057112b5fdf3a",
          "body": "Audit of ./internal per best-practices-comments: drops godoc that merely\nrestates the identifier, \"// Verify X\"-style assertion narration in tests,\nsection-divider comments, numbered step labels, and a few stale references\n(YAML→JSON, shipped-follow-up hedges, gitignored-doc pointers). No behavior\nchanges; all internal tests pass.",
          "is_bot": false,
          "headline": "chore(internal): remove noise, redundant, and stale comments",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-11T22:56:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d6381960b743a42ca1301d3b859305305e291155",
          "body": "The planrepo loader uses DisallowUnknownFields so a typo'd field on\ndisk surfaces as a parse error. The CLI write entry points used plain\njson.Unmarshal, so the same typo at write time was silently dropped on\nthe way to disk — asymmetric. Export StrictUnmarshal and use it from\nboth write_issue.go and write_prd.go.",
          "is_bot": false,
          "headline": "fix(cli): strict-decode JSON at write-issue/write-prd boundary",
          "author_name": "Jason Raimondi",
          "author_login": "jasonraimondi",
          "committed_at": "2026-05-11T22:20:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 58,
      "commits_last_year": 388,
      "latest_release_at": "2026-07-17T21:34:12Z",
      "latest_release_tag": "v0.0.71",
      "releases_from_tags": false,
      "days_since_last_push": 5,
      "active_weeks_last_year": 12,
      "days_since_latest_release": 5,
      "mean_days_between_releases": 6
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/jasonraimondi/plan-bender",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/jasonraimondi/plan-bender",
          "is_deprecated": false,
          "latest_version": "v0.0.71",
          "repository_url": "https://github.com/jasonraimondi/plan-bender",
          "versions_count": 61,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-16T01:50:46Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 7
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 5,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": 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": [
        "mise.toml"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 25732,
      "source_files_sampled": 167,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 707
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/charmbracelet/huh",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.0"
        },
        {
          "name": "github.com/hasura/go-graphql-client",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.15.1"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "github.com/stretchr/testify",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.11.1"
        },
        {
          "name": "golang.org/x/sys",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.41.0"
        },
        {
          "name": "golang.org/x/tools",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.42.0"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 28,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 6
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "jasonraimondi",
          "commits": 386,
          "avatar_url": "https://avatars.githubusercontent.com/u/5787967?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "locksafe.yaml",
        "release.yaml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 3,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "3 out of 3 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/18 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 4 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 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": 10,
            "reason": "packaging workflow 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": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not 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": 8,
            "reason": "2 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "744099fd2f3c926c93124083b6f3d3543c6e7984",
        "ran_at": "2026-07-23T19:03:29Z",
        "aggregate_score": 4.4,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-17T21:38:24Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-06-08T02:38:15Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/jasonraimondi/plan-bender",
    "host": "github.com",
    "name": "plan-bender",
    "owner": "jasonraimondi"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 56,
      "inputs": {
        "security": 44,
        "vitality": 79,
        "community": 29,
        "governance": 56,
        "engineering": 67
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 79,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 72,
            "inputs": {
              "commits_last_year": 388,
              "human_commit_share": 1,
              "days_since_last_push": 5,
              "active_weeks_last_year": 12
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "12/52 weeks with commits",
                "points": 8.3,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 12
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "388 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 388
                    }
                  }
                ],
                "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": 58,
              "latest_release_tag": "v0.0.71",
              "releases_from_tags": false,
              "days_since_latest_release": 5,
              "mean_days_between_releases": 6
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "58 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 58
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~6 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 6
                    }
                  }
                ],
                "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": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 29,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "forks": 0,
              "stars": 5,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "5 stars",
                "points": 9.8,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "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": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "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": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "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
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 56,
        "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 4 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "moderate",
            "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": 59,
            "inputs": {
              "merged_prs": 28,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 6
            },
            "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": "28/34 decided PRs merged",
                "points": 31.5,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 28,
                      "decided": 34
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/18 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": 62,
            "inputs": {
              "followers": 101,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "jasonraimondi",
              "public_repos": 186,
              "account_age_days": 4652
            },
            "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": "101 followers of jasonraimondi",
                "points": 14.4,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 101,
                      "login": "jasonraimondi"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "186 public repos, account ~12 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 186
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 12
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/jasonraimondi/plan-bender"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 7
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on go",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "go"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 7 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 7
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "61 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 61
                    }
                  }
                ],
                "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": 67,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "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": "3 out of 3 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 44,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": null,
            "notes": [],
            "value": 44,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 18,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 0,
              "scorecard_aggregate": 4.4
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "3 out of 3 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/18 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 4 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 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 detected",
                "points": 5,
                "status": "met",
                "details": [],
                "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": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "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": "2 existing vulnerabilities detected",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 2
            },
            "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": 76,
        "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": 1,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 707
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "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": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 61,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "mise.toml"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "mise.toml",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "mise.toml"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "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": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 25732,
              "source_files_sampled": 167,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/167 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 167,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-23T19:03:41.790365Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/j/jasonraimondi/plan-bender.svg",
  "full_name": "jasonraimondi/plan-bender",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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 agregadasGo.