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

alphaleonis / nibs

A file-based issue tracker for AI-first workflows

Go · TypeScriptLicencia propia★ 1 estrella⑂ 0 forksdesde mar 2026Ver en GitHub ↗

alphaleonis/nibs tiene un índice de salud de 46 sobre 100, lo que lo sitúa en la banda En riesgo. Su puntuación más alta es Vitality (78/100) y la más baja, Community & Adoption (21/100). Se actualizó por última vez hace 2 días. Una sola persona concentra la mayor parte del trabajo reciente.

46
global / 100
En riesgo

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

46
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

Peter PalotasCuenta personal
43 seguidores29 repositorios públicosdesde jul 2013

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/alphaleonis/nibsv0.7.0-14hace 2 días

Métricas por categoría

Vitalidad

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

78Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 2 días
6.2/36Cadencia de commits — 9/52 semanas con commits
18/18Volumen de commits — 343 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_year343
human_commit_share1
days_since_last_push2
active_weeks_last_year9
Cómo se puntúa
27/27Publica versiones — 13 versiones publicadas
36/36Recencia de las versiones — última versión hace 2 días
27/27Cadencia de publicación — una versión cada ~11,5 días
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Datos de entrada utilizados
releases_count13
latest_release_tagv0.7.0
releases_from_tagsno
days_since_latest_release2
mean_days_between_releases11,5

Comunidad y Adopción

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

21Crítico · 18% del índice global
Cómo se puntúa
0/60Estrellas — 1 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars1
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
16.9/22.5Licencia — archivo de licencia presente, no es una licencia reconocida
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?

37En riesgo · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
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
0/38.3Aceptación de PR — sin PR decididos o sin datos
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
Excluidos de la puntuación (sin datos o no aplicable): Resolución de issues, Aceptación de PR. 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
11.8/25Alcance del propietario — 43 seguidores de alphaleonis
22.8/25Trayectoria — 29 repos públicos, cuenta de ~13 años
Datos de entrada utilizados
followers43
owner_typeUser
is_verified
owner_loginalphaleonis
public_repos29
account_age_days4746
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 2 días
20/20Historial de versiones — 14 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesgithub.com/alphaleonis/nibs
ecosystemsgo
any_deprecatedno
min_days_since_publish2

Calidad de Ingeniería

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

52Moderado · 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
0/20OpenSSF Scorecard: CI-Tests — sin datos
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_configno
has_precommit_configno
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: CI-Tests. Los pesos restantes se han renormalizado.

Documentación

40En riesgo
Cómo se puntúa
30/30README
0/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_dirno
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?

38En riesgo · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — sin datos
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
5/5Fuzzing — project is fuzzed
2.2/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
1.5/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 3
0/5SAST — no SAST tool detected
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
0/7.5Vulnerabilities — 34 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate3,8
Excluidos de la puntuación (sin datos o no aplicable): ci_tests. Los pesos restantes se han renormalizado.

Preparación para IA

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

72Bueno · 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 — 94 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,94
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes19.108
Cómo se puntúa
18/18Arranque con un solo comando — Taskfile.yml, mise.toml
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — web/tsconfig.json
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
3/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 3
Datos de entrada utilizados
has_nixno
has_tests
lockfilesgo.sum, package-lock.json
has_dockerfileno
typed_language
bootstrap_filesTaskfile.yml, mise.toml
has_devcontainerno
has_linter_configno
typecheck_configsweb/tsconfig.json
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)
54.3/55Tamaños de archivo manejables — 5/399 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes258.861
source_files_sampled399
oversized_source_files5
Cómo se puntúa
40/40Esquema de API (OpenAPI/GraphQL/proto) — internal/graph/schema.graphqls
0/20Servidor MCP
0/40Ejemplos ejecutables
Datos de entrada utilizados
example_dirs
has_mcp_signalno
api_schema_filesinternal/graph/schema.graphqls

Datos clave

1estrellas de GitHub
1contribuidores
343commits en los últimos 12 meses
2días desde el último push
13versiones publicadas
1factor bus
0issues abiertas
Go, npmecosistemas 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 3.8 / 10
3.8agregado

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-27 19:22 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
n/dCI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
10Fuzzingproject is fuzzed
9Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
3Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 3
0SASTno SAST tool detected
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
0Vulnerabilities34 existing vulnerabilities detected
Dependencias directas 37
RegistroPaqueteRestricción de versiónManifiesto
Gogithub.com/99designs/gqlgenv0.17.84go.mod
Gogithub.com/adrg/frontmatterv0.2.0go.mod
Gogithub.com/atotto/clipboardv0.1.4go.mod
Gogithub.com/blevesearch/bleve/v2v2.5.6go.mod
Gogithub.com/charmbracelet/bubblesv0.21.1-0.20250623103423-23b8fd6302d7go.mod
Gogithub.com/charmbracelet/bubbleteav1.3.10go.mod
Gogithub.com/charmbracelet/glamourv0.10.0go.mod
Gogithub.com/charmbracelet/lipglossv1.1.1-0.20250404203927-76690c660834go.mod
Gogithub.com/charmbracelet/x/ansiv0.11.2go.mod
Gogithub.com/creativeprojects/go-selfupdatev1.6.0go.mod
Gogithub.com/fsnotify/fsnotifyv1.9.0go.mod
Gogithub.com/gorilla/websocketv1.5.3go.mod
Gogithub.com/matoous/go-nanoid/v2v2.1.0go.mod
Gogithub.com/spf13/cobrav1.10.2go.mod
Gogithub.com/spf13/pflagv1.0.10go.mod
Gogithub.com/tidwall/prettyv1.2.1go.mod
Gogithub.com/vektah/gqlparser/v2v2.5.31go.mod
Gogithub.com/yuin/goldmarkv1.7.13go.mod
Gogolang.org/x/modv0.36.0go.mod
Gogolang.org/x/sysv0.47.0go.mod
Gogolang.org/x/termv0.44.0go.mod
Gogopkg.in/yaml.v3v3.0.1go.mod
npm@codemirror/lang-markdown^6.5.0web/package.json
npm@codemirror/state^6.6.0web/package.json
npm@codemirror/theme-one-dark^6.1.3web/package.json
npm@codemirror/view^6.40.0web/package.json
npm@urql/svelte^5.0.0web/package.json
npmbits-ui^2.16.3web/package.json
npmclsx^2.1.1web/package.json
npmcodemirror^6.0.2web/package.json
npmdompurify^3.3.3web/package.json
npmgraphql^16.13.2web/package.json
npmgraphql-ws^6.0.7web/package.json
npmmarked^17.0.5web/package.json
npmpaneforge^1.0.2web/package.json
npmtailwind-merge^3.5.0web/package.json
npmtinykeys^3.0.0web/package.json
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": 2545,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Go": 2471451,
        "CSS": 25406,
        "HTML": 2369,
        "Shell": 4915,
        "Svelte": 287294,
        "JavaScript": 116,
        "PowerShell": 4129,
        "TypeScript": 1403652,
        "Go Template": 17407
      },
      "pushed_at": "2026-07-25T16:34:19Z",
      "created_at": "2026-03-18T15:13:06Z",
      "owner_type": "User",
      "updated_at": "2026-07-25T16:21:39Z",
      "description": "A file-based issue tracker for AI-first workflows",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": "NOASSERTION",
      "primary_language": "Go",
      "significant_languages": [
        "Go",
        "TypeScript"
      ]
    },
    "owner": {
      "blog": "http://www.alphaleonis.com/",
      "name": "Peter Palotas",
      "type": "User",
      "login": "alphaleonis",
      "company": null,
      "location": "Göteborg, Sweden",
      "followers": 43,
      "avatar_url": "https://avatars.githubusercontent.com/u/5114354?v=4",
      "created_at": "2013-07-29T15:51:32Z",
      "is_verified": null,
      "public_repos": 29,
      "account_age_days": 4746
    },
    "license": {
      "state": "custom",
      "spdx_id": null,
      "raw_spdx": "NOASSERTION",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-07-25T16:35:37Z"
        },
        {
          "tag": "v0.6.2",
          "kind": "patch",
          "published_at": "2026-07-23T18:27:49Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2026-07-20T19:38:40Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-07-20T09:42:59Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-05-07T06:32:18Z"
        },
        {
          "tag": "v0.4.1",
          "kind": "patch",
          "published_at": "2026-05-04T19:57:51Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-05-01T16:18:22Z"
        },
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2026-04-27T14:32:51Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-04-24T16:53:02Z"
        },
        {
          "tag": "v0.2.3",
          "kind": "patch",
          "published_at": "2026-04-12T19:24:56Z"
        },
        {
          "tag": "v0.2.2",
          "kind": "patch",
          "published_at": "2026-04-12T14:25:58Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2026-04-11T15:17:06Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-04-09T16:51:33Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "41e029500290dfc9b05fc5a734aa4c3559b78692",
          "body": null,
          "is_bot": false,
          "headline": "docs: stamp CHANGELOG v0.7.0 - 2026-07-25 for release",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-25T16:21:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "68660010b5af2c2d73342b055a9890728e07da6e",
          "body": "… drag affordances",
          "is_bot": false,
          "headline": "Merge develop into main: v0.7.0 — web table sorting, column reorder +…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-25T16:20:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "92b2a14767740f030a198ef18e9fb26c05deb10e",
          "body": "…ure)\n\n- setPointerCapture(pointerId) on the header <th> in onHeaderPointerDown +\n  record the active pointerId; pointerId-gate onPointerMove/Up/Cancel so a\n  foreign pointer can't move/end/commit the drag\n- lostpointercapture -> cleanup(); cleanup() releasePointerCapture (guarded,\n  idempotent) + r\n[…]\nclick can't commit a phantom reorder\n- Row drag (native HTML5 DnD, self-terminating) unaffected; sort/resize/threshold\n  arbitration + the nibs-0sru $effect unmount teardown unchanged\n\nRefs: nibs-81jn",
          "is_bot": false,
          "headline": "fix(web): make column drag robust to a lost pointerup (setPointerCapt…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-25T14:11:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0764c001e82dc927118d140c48aef81217bf9ed3",
          "body": "- Gate the loading state on initial load only: {#if fetching && allNibs.length\n  === 0} instead of {#if fetching}. A background (subscription-driven,\n  network-only) refetch keeps data via urql's scan-merge, so the populated table\n  stays mounted and rows update in place — no longer unmounting/remounting and\n  interrupting an in-progress column drag/resize/editor/scroll\n- Error and empty states unchanged; pruning effects untouched\n\nRefs: nibs-ip40",
          "is_bot": false,
          "headline": "fix(web): keep the table mounted during a background refetch",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-25T13:50:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8ce17ba207d1d7000fa9a1d699335b324b5ad151",
          "body": "… cursor\n\n- useColumnDrag exposes ghost state (dragged column's label/sortKey + captured\n  width + live pointer x/y) captured at drag start; TableHeader renders a\n  position:fixed, pointer-events:none, aria-hidden header-clone that follows the\n  pointer at reduced opacity, keeping the in-place .col-\n[…]\nrified in a real browser (Playwright + task demo): ghost follows the cursor,\n  cursor is grabbing over a header / no-drop over the actions column, reorder\n  completes, cleanup on drop\n\nRefs: nibs-0sru",
          "is_bot": false,
          "headline": "feat(web): column-drag affordances — cursor-following ghost + no-drop…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-25T12:54:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "815c469fd6ad7f7a9e0ec556b81007e0f03c9e7f",
          "body": "- Add user-select:none (+ -webkit-) to .col-header. nibs-5ela replaced the\n  inner sort <button> (implicit user-select:none) with a plain <span>, so the\n  whole-header pointer-drag started a text selection of the label. The header is\n  a click/drag sort control now, not selectable text; mirrors the .resize-handle\n  precedent. CSS-only; reorder/resize/click-to-sort unchanged.\n\nRefs: nibs-3btf",
          "is_bot": false,
          "headline": "fix(web): stop column-header drag from selecting the label text",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T22:08:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eb1ec7cac55039f1763d33871f54baa72223787d",
          "body": "…label text)\n\n- Promote the sortable <th> to the sort control: onclick anywhere in the header\n  (bails on .resize-handle, honors columnDrag.consumeClickSuppression) sorts,\n  matching the whole-header drag from nibs-46c1; the inner sort <button> becomes\n  a non-interactive label span\n- Keyboard/a11y:\n[…]\nlickable header is discoverable; resize edge + drag-gating unchanged\n- Behavior-preserving: asc->desc->off cycle, arrows, aria-sort, sorted-column-\n  hidden deactivation all unchanged\n\nRefs: nibs-5ela",
          "is_bot": false,
          "headline": "feat(web): make the whole column header a sort control (not just the …",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T20:41:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e3c7d9ff8dcacf4e5cd36485aaf38a81378d15cf",
          "body": "…tive sort (epics/features lenses)\n\n- Export makeNibComparator from tableSort.ts (reuses the nibs-3jj4\n  KEY_EXTRACTORS/compareKeys); applySort now delegates to it (one source)\n- buildViewTree (tree.ts) takes an optional sortComparator; after classify,\n  stable-sorts headers + bucket items by node.n\n[…]\nnt\n- Tests prove the guards bite (revert-probe: neutralizing the re-sort fails the\n  global-order/desc/parent-field/wiring guards); ReadonlyMap variance keeps the\n  generic byId sound\n\nRefs: nibs-2lqm",
          "is_bot": false,
          "headline": "feat(web): globally order promoted headers + bucket items under an ac…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T18:39:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "04d89c4bb22f3f04a391dcbaad5a61185f651f48",
          "body": "- Add web-side graphql-code-generator (client preset, fragmentMasking:false)\n  driven by internal/graph/schema.graphqls (the same SDL gqlgen reads): dev deps\n  @graphql-codegen/cli + client-preset (+ svelte2tsx for .svelte plucking),\n  web/codegen.ts, generated TypedDocumentNodes committed under src\n[…]\npm install-time deprecation chatter in\n  web:build so task build stays warning-free\n- Time scalar -> string (matches existing NibSummary); no query text changed;\n  Go/gqlgen untouched\n\nRefs: nibs-i3i0",
          "is_bot": false,
          "headline": "feat(web): type GraphQL query results via graphql-code-generator",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T16:31:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4badda7ae74ac8577efc62ed0e2576fda0a04458",
          "body": "…ure seam)\n\n- Move the entire <thead> (actions column + per-column <th> shells + the\n  click-vs-drag arbitration) out of TreeTable.svelte into a new\n  web/src/lib/components/TableHeader.svelte; TreeTable renders <TableHeader/>\n- TableHeader receives resolved columns + gesture composable objects\n  (c\n[…]\n unchanged\n- Delegation contract preserved: header gestures stay on header elements, sort\n  button keeps stopPropagation, headers lack tr[data-nib-id] so row delegation\n  ignores them\n\nRefs: nibs-zw7d",
          "is_bot": false,
          "headline": "refactor(web): extract TableHeader component (consolidate header gest…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T15:36:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dc93b61edf78764f8c2ac958f9707a827d2135c0",
          "body": "- Add per-view columnOrder as the third PerViewColumnMap instance (REPLACE\n  resolve, saveMode auto, default ALL_COLUMN_KEYS); parseColumnOrder drops\n  unknown/dup keys and appends missing ColumnKeys canonically (new columns\n  still appear); round-trips per view level\n- columnOrder drives rendering:\n[…]\ncape-abort and pointercancel also suppress-then-clear\n- Constraints: alwaysVisible (title) reorderable but not hideable; 32px actions\n  column stays leftmost (not part of columnOrder)\n\nRefs: nibs-46c1",
          "is_bot": false,
          "headline": "feat(web): reorder columns by drag/drop, persisted per view",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T15:18:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b5a99f9386eba932ce193c318f47cfc6e5a3d5d2",
          "body": "- Drop the Flat-only gate on the active sort: applySort(allNibs) feeds\n  buildTableData in every view; buildTree/buildViewTree preserve sibling order,\n  so nested views get sibling-sort (siblings, roots, bucket items, promoted\n  headers) with hierarchy intact; Flat still yields a flat sorted list\n- \n[…]\nhanged from nibs-3jj4\n\nKnown gap (deferred to nibs-2lqm): promoted headers in the epics/features lenses\nare grouped-by-hidden-ancestor, not globally sorted — needs a product decision.\n\nRefs: nibs-6grg",
          "is_bot": false,
          "headline": "feat(web): extend sorting to Tree + grouping views (sibling-sort)",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T14:32:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9ea56d7307246c1b2daba55ad0e54a1fd6340e8d",
          "body": "…sort)\n\n- Replace applyFlatSort's date-only body with a per-kind comparator registry\n  (flatSort.ts): text (title ci, id), enum by canonical rank (type via TYPES\n  index, state via STATUSES, effort via ESTIMATES), date (created/modified),\n  relation count (blocking/blockedBy), tags (first tag), pare\n[…]\nleHeader); every\n  sortable header cycles asc->desc->off with arrow + aria-sort; inert outside Flat\n- Scope: Flat-only (Tree/grouping sort is nibs-6grg); no flatSort->tableSort rename\n\nRefs: nibs-3jj4",
          "is_bot": false,
          "headline": "feat(web): sort by any column in Flat view (generalize the date-only …",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T14:03:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ce3b40fdf30c4a5e55ac0451f4d1f235c3b2758e",
          "body": "- Add generic $state-backed primitive web/src/lib/perViewColumnMap.svelte.ts:\n  one implementation of the per-ViewLevel map plumbing, instantiated per concern\n  with injected default / resolve combinator / saveMode / requestSave\n- Preferences holds two instances: visibility (REPLACE, saveMode auto) \n[…]\ngration/reset), same\n  resolved values; existing preferences/storage/Toolbar column tests unchanged\n- columnOrder deferred to nibs-46c1 (the third instance); resolvePrefs.ts untouched\n\nRefs: nibs-42h3",
          "is_bot": false,
          "headline": "refactor(web): unify per-view column-state via PerViewColumnMap<T>",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T13:41:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f7fb2c5f00b9995c263f30e05f67bc696bff3309",
          "body": "…pters)\n\n- Add pure decision core web/src/lib/tableDataSource.ts (zero Svelte/@urql\n  import): dedup by type:nibId:etag, immediate-vs-deferred refetch (delete\n  defers by fadeDurationMs), single pending-delete timer (cancel+replace),\n  throw-isolated safeRefetch, idempotent destroy\n- Add thin adapte\n[…]\n ($effect.root recipe)\n- Behavior-preserving: existing TreeTable live-update/delete-fade/refetch tests\n  pass unchanged; corrects a latent timer leak + fade-cut-short on delete bursts\n\nRefs: nibs-x2w5",
          "is_bot": false,
          "headline": "refactor(web): extract TreeTable data/subscription layer (ports & ada…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T13:17:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a92f1185f59315566ba52ddb7abd461ed92aae7f",
          "body": "…stry\n\n- Add pure column model web/src/lib/columns.ts (zero Svelte import): one\n  ColumnKey union, COLUMNS satisfies Record<ColumnKey, ColumnDef> (11 cols),\n  derived DEFAULT_COLUMN_WIDTHS / DEFAULT_VISIBLE_COLUMNS / ALWAYS_VISIBLE_KEYS\n- Add Svelte snippet adapter web/src/lib/ColumnAdapters.svelte:\n[…]\nolumnAdapters.test.ts (parity/bite)\n- Behavior-preserving: existing TreeTable/TreeTableRow/Toolbar DOM tests pass\n  unchanged; the silent-blank-column bug class is now a compile error\n\nRefs: nibs-1x9o",
          "is_bot": false,
          "headline": "refactor(web): data-driven column rendering via ports-&-adapters regi…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T12:44:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d335c053fa8d9e3dd71fb278b65075af6e7037b4",
          "body": "- Add a \"Flat\" view level: every nib an ungrouped depth-0 row (no\n  nesting, no buckets); relabel the hierarchical \"None\" level to \"Tree\"\n- Client-side date sorting in Flat only — Created/Modified headers\n  become click-to-cycle sort controls (asc -> desc -> off) with an\n  arrow indicator; date head\n[…]\n retained), keeping the header indicator and row order in sync\n- Exclude non-matching ancestors from Flat under a client filter (no\n  stray dimmed rows); add a Flat screenshot capture\n\nRefs: nibs-qd3d",
          "is_bot": false,
          "headline": "feat(web): Flat (no-hierarchy) view mode + date sorting",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-24T09:43:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "12c5f25121e85d097e642fae0cc24ffc7ac8d4e4",
          "body": "- Add shared date formatter web/src/lib/date.ts: relative age\n  (just now / Xm/Xh/Xd/Xmo ago) with a short \"MMM yyyy\" fallback past\n  ~1 year and full ISO on hover; empty/invalid -> \"\"; UTC-consistent\n  label and tooltip\n- Add Created (opt-in) and Modified (default-visible) columns: register\n  keys/\n[…]\nE_QUERY; add createdAt to NibSummary and\n  the synthetic bucket nib in tree.ts (schema already exposes it)\n- Display-only: no sort/drag (flat view + date sorting tracked in nibs-qd3d)\n\nRefs: nibs-v454",
          "is_bot": false,
          "headline": "feat(web): Created/Modified date columns in the table",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-23T20:22:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "853bb5672082f761291003751288535c8d69b932",
          "body": null,
          "is_bot": false,
          "headline": "docs: stamp CHANGELOG v0.6.2 - 2026-07-22 for release",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-22T21:09:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d8d251c0b65c5e4bea786315edcac52ae1f9d7f",
          "body": "… advisory write lock)",
          "is_bot": false,
          "headline": "Merge develop into main: v0.6.2 (blocking pill parity, atomic writes,…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-22T21:09:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bee490e02361586d45aa1f95b6e782e4ba016717",
          "body": "- extract blocked/blocking icon, color, label, pill classes into\n  web/src/lib/relations.ts (RELATION_CONFIG)\n- RelationBadge and the TreeTableRow blocking/blocked-by count columns now\n  both read it, so the two can't drift (pre-existing two-sources-of-truth)\n\nRefs: nibs-2rf2",
          "is_bot": false,
          "headline": "refactor(web): single-source relation icon/color via RELATION_CONFIG",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-22T21:01:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cc5478ecd55816cbc5db8f9d0f7b38ed9c1484b6",
          "body": "- generalize BlockedBadge -> RelationBadge (kind: blocked|blocking): blocked =\n  Lock/red/\"Blocked\", blocking = Link/amber/\"Blocking\"; testids ${kind}-badge/icon\n- wire the blocking pill into TreeTableRow + ActiveNibView header, reusing the\n  blockedEmphasis setting (subtle->icon, pill/pill-dim->pil\n[…]\n both themes + @theme registration\n- tests: RelationBadge both kinds x variants; the ActiveNibView isCreating-gate\n  test now bites; added simultaneously-blocked-and-blocking coverage\n\nRefs: nibs-e81b",
          "is_bot": false,
          "headline": "feat(web): amber Blocking pill via generalized RelationBadge",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-22T20:50:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "513db15af065d34820da810faba83915b3aa8f1d",
          "body": "- delete 12 unused --status-*-bg bare vars (dark + light themes) and their\n  6 --color-status-*-bg @theme registrations from app.css; status renders\n  via --status-*-text (StatusDot/StatusIcon), the -bg tokens had no consumer\n- update the two block comments that described the removed -bg tokens\n\nRefs: nibs-sopc",
          "is_bot": false,
          "headline": "chore(web): remove dead --status-*-bg design tokens",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-22T19:26:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b63ec444db38241112ea1d7e80232f673afd76f4",
          "body": "Delivers epic nibs-3qvm children nibs-eils (atomic saveToDisk) and\nnibs-dg6i (per-op advisory write lock). Deferred: nibs-1w2i (merge driver).",
          "is_bot": false,
          "headline": "Merge concurrency hardening: atomic writes + advisory write lock",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-22T18:56:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "46351fd9ef60b5c1a5be4acbdf5e7c565de17d90",
          "body": "- add acquireFileLock (build-tagged: unix flock / windows LockFileEx) and\n  writeLockPath (OS-temp-dir lock keyed by hash of the abs .nibs path)\n- Core holds the per-op advisory write lock across the read-check-write of\n  every mutator (Create/Update/Delete/Archive/Unarchive/LoadAndUnarchive),\n  clo\n[…]\nsame-machine cross-process lost-update window; lock order is\n  c.mu -> file lock, no nesting so no deadlock\n- tests: lock serializes holders, releases cleanly, and Update participates\n\nRefs: nibs-dg6i",
          "is_bot": false,
          "headline": "feat: serialize cross-process nib writes with an advisory file lock",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-22T18:55:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d64808722c37bf51d42769df49e69fbf0c077587",
          "body": "- add atomicWriteFile: unique temp + fsync + atomic rename over target,\n  cleans up the temp on every error path; renameFn seam for tests\n- saveToDisk uses it so a crash or concurrent reader never sees a torn nib\n- update best-effort-persistence migrate test to force the failure via the\n  rename seam (atomic rename overwrites read-only files by design)\n\nRefs: nibs-eils",
          "is_bot": false,
          "headline": "feat: write nibs atomically (temp file + rename) in saveToDisk",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-22T18:42:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "419e751d3f149165fb196e0ca793b74387705442",
          "body": "- Move the release runbook from .claude/commands/release.md to\n  .claude/skills/release/SKILL.md — the recommended format (custom commands\n  are the legacy form, merged into skills); both invoke as /release\n- invoke-by: user keeps a release explicit and never auto-triggered\n\nRefs: nibs-jw2r",
          "is_bot": false,
          "headline": "refactor: make /release a skill instead of a legacy command",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-20T20:03:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e579c000626c6a915773d351b40bb71c9aefcadf",
          "body": "- .claude/commands/release.md codifies RELEASING.md as a user-invoked runbook:\n  version -> changelog (scrubbed of nib refs) -> merge -> wait for green CI ->\n  dispatch the gated release.yml -> verify + revise the draft -> stop for human\n  publish -> sync develop\n- Encodes the guardrails: release only from main with green CI, no private nib\n  references in the public changelog, halt on error, never auto-publish\n\nRefs: nibs-jw2r",
          "is_bot": false,
          "headline": "chore: add /release slash command to drive releases end-to-end",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-20T20:00:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a0efb617e01871725f69350d8db8d33f38403826",
          "body": "The changelog is a public artifact; nib work items are not. Strip all\n(Refs: nibs-xxxx) tracker trailers from every entry.",
          "is_bot": false,
          "headline": "docs: remove private nib references from CHANGELOG",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-20T19:23:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a992430ecbc9252363c20e3a8132cc39dca8bb38",
          "body": null,
          "is_bot": false,
          "headline": "docs: stamp CHANGELOG v0.6.1 - 2026-07-20 for release",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-20T19:19:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9b0acc994cc37fb66d3d14fcdd95e49825778644",
          "body": "Refs: nibs-o2iv",
          "is_bot": false,
          "headline": "Merge develop into main: gate Release workflow on green CI",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-20T19:18:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "65aceaf86a712a667e59635c307abe533dbc2196",
          "body": "- Refuse to run unless dispatched from `main` (CI only runs on main, so other\n  refs have no signal to gate on) — applies to pre-releases too\n- Require the latest `ci.yml` run for the release commit to have completed with\n  conclusion `success`; a missing or in-progress run aborts before tagging\n- A\n[…]\nions: read` permission so `GITHUB_TOKEN` can query CI run status\n- Gate runs before the tag-push step, so a red commit is never tagged\n- Document the new preconditions in RELEASING.md\n\nRefs: nibs-o2iv",
          "is_bot": false,
          "headline": "ci(release): gate the Release workflow on green CI",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-20T19:03:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "aeb8918147a50332de7ba18230a8fc88c9395428",
          "body": "…g.disable)",
          "is_bot": false,
          "headline": "Merge develop into main: fix empty release notes (goreleaser changelo…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-20T10:15:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7f5f0854de456b2eeb5d4a2a598507bf292f2d50",
          "body": "…he body\n\ngoreleaser loads --release-notes inside the changelog pipe; changelog.disable:\ntrue skipped that pipe entirely, so the notes were never read and the GitHub\nrelease body came out empty (verified against goreleaser v2.17.0 source). With\n--release-notes always passed by the workflow, the pipe uses the file verbatim\nand generates no commit changelog.\n\nRefs: nibs-gyj5",
          "is_bot": false,
          "headline": "fix(release): remove changelog.disable so --release-notes populates t…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-20T10:15:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cfbbe49d6088b71f3eba0ab2e3ada2c39f7e6978",
          "body": null,
          "is_bot": false,
          "headline": "Merge develop into main: deterministic PaneGroup web test",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T22:34:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c9259f6d4e9752544192092b58a1f4e7d86b5f1f",
          "body": "The 'PaneGroup is always present' test read the split direction from\nprefs.detailPanelPosition without seeding it. On CI (functional, shared\nlocalStorage) a 'bottom' dock persisted by an earlier dock-toggle test could\nleak in and flip data-direction to 'vertical', failing the assertion; locally\nloca\n[…]\nStorage is non-functional so it always defaulted to 'right' and never\nflaked. Seed a scoped 'right' preference (mirroring the sibling 'bottom' test)\nso the direction is deterministic.\n\nRefs: nibs-6cfk",
          "is_bot": false,
          "headline": "test: deterministically seed dock position in App PaneGroup test",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T22:34:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9ed13af730be0e3b16a203c1fa141329560656bb",
          "body": null,
          "is_bot": false,
          "headline": "Merge develop into main: Windows CI test-portability fixes",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T22:02:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d297a8cc03cced6f65de88beb0627135d7c77a3f",
          "body": "- cmd: TestDetectPackageManager multi-entry GOPATH used a hardcoded ':' list\n  separator; build it with filepath.ListSeparator so filepath.SplitList splits\n  it on Windows (';') too\n- nibcore: skip the two chmod-0 'unreadable file' etag subtests and the\n  chmod-0 'unreadable dir' WalkDir test on Win\n[…]\nwhere chmod 0 does not\n  remove read access (product behavior is still covered on Linux)\n\nThese surfaced only when main's Windows CI first ran the accumulated develop\nwork; product code is unaffected.",
          "is_bot": false,
          "headline": "test: fix Windows CI portability in three tests",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T22:02:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a6e06b69cc7d43582eccdebff88e03a6db5bb8f5",
          "body": "Self-update notifications (CLI/TUI/web) + `nibs upgrade`, plus the\ndeferred-status change and keyword-search ID matching staged for v0.6.0.",
          "is_bot": false,
          "headline": "Release v0.6.0: merge develop into main",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T20:54:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d98f0f4d89ed6b1e3af262544e1e1dad2340f4be",
          "body": null,
          "is_bot": false,
          "headline": "docs: stamp CHANGELOG v0.6.0 - 2026-07-19 for release",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T20:54:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bd631e228cb60729c166ef997d23d0d82d6426a0",
          "body": "- Key Commands: use canonical names (new/get/set/query, not create/show/\n  update/graphql — graphql is not a command); fix `set` description (no body\n  editing); add `body` and `mv`; roadmap covers epics too\n- Quick Start: `nibs new` with a valid invocation (the old `-d \"inline text\"`\n  errored — -d is a channel, - or @FILE only)\n- Data Model: add the `research` type",
          "is_bot": false,
          "headline": "docs: fix README correctness (command names, Quick Start, types)",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T20:29:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a89ed09a096b4fe10c75f35d6d18fef423bc89d",
          "body": "- CHANGELOG [Unreleased]: update notifications (CLI/TUI/web), `nibs upgrade`,\n  and the release asset-naming change\n- README: add an Updating section and a `nibs upgrade` command row\n\nRefs: nibs-jlzy",
          "is_bot": false,
          "headline": "docs: changelog + README for self-update (nibs upgrade, notifications)",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T20:23:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "939f1e91841b64f036c864dffda67335a69c2982",
          "body": "…ade`\n\nImplements epic nibs-jlzy across all surfaces:\n- version-check core + CLI notifier (nibs-ipmj)\n- nibs upgrade via go-selfupdate + release asset-naming alignment (nibs-hkub)\n- TUI footer indicator (nibs-imib)\n- web updateStatus banner (nibs-25od)\n\nRefs: nibs-jlzy",
          "is_bot": false,
          "headline": "Merge feat/self-update-notify: self-update notifications + `nibs upgr…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T20:19:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "94143f881b22331ebc0f505177eef493a3c3edeb",
          "body": "- GraphQL: add updateStatus { current latest updateAvailable } query, resolved\n  from internal/updatecheck via the running version threaded into the Resolver;\n  best-effort (network failure / dev build → updateAvailable=false, never errors)\n- web: dismissible top banner (shadcn tokens) shown when a \n[…]\nisted per-version in localStorage so a\n  newer version re-surfaces it\n- helper updateStatusResult kept in a non-generated file (gqlgen comments out\n  free functions in resolver files)\n\nRefs: nibs-25od",
          "is_bot": false,
          "headline": "feat(web): update-available banner in the web UI",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T20:15:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ade968f6554cf46992269f167658f99aa2d10b95",
          "body": "- App runs a best-effort background update check on startup (batched into\n  Init, off the render loop) via internal/updatecheck, threading the running\n  version from cmd/tui.go\n- an unobtrusive `↑ nibs vX.Y.Z available — nibs upgrade` hint renders in the\n  list footer when a newer release exists; hidden otherwise; honors the\n  core's dev/CI/opt-out gating (TUI is always a TTY)\n- fix setupTestApp to unwrap Init's batch via processCmd (Init now batches)\n\nRefs: nibs-imib",
          "is_bot": false,
          "headline": "feat(tui): show update-available indicator in the list footer",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T20:02:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1cf9dc06037a9658cbf3a0ae10f490d92d1e0a67",
          "body": "- nibs upgrade: download + checksum-verify + replace with rollback using\n  github.com/creativeprojects/go-selfupdate; --check (report only) and\n  --version <tag> (pin/downgrade) flags; prereleases skipped by default\n- package-manager guard: defer to Homebrew/Nix/Scoop/Chocolatey/WinGet/\n  `go instal\n[…]\names\n  ({project}_{os}_{arch}) and a fixed checksums.txt in .goreleaser.yaml;\n  update install.sh + install.ps1 to match\n- skip core init and self-notification for the upgrade command\n\nRefs: nibs-hkub",
          "is_bot": false,
          "headline": "feat(upgrade): add `nibs upgrade` via go-selfupdate",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T19:55:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c9f91c040820305415fa43964f65f6539c848f52",
          "body": "- internal/updatecheck: cached, gated \"is a newer release available?\"\n  service (GitHub releases/latest tag + semver compare), shared by all\n  notification surfaces; no platform asset-matching, dependency-light\n- cache to os.UserCacheDir()/nibs with 24h cooldown; gate off dev builds,\n  CI, and NIBS_\n[…]\ntentPostRun; suppressed for non-TTY, --json, pipes,\n  and machine/long-running commands (serve/graphql/query/tui/completion)\n- promote golang.org/x/mod (semver) to a direct dependency\n\nRefs: nibs-ipmj",
          "is_bot": false,
          "headline": "feat(updatecheck): add version-check core + CLI update notifier",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T19:34:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3e33fca54c7c9337f189bbfe799753a8aaca7bd9",
          "body": "- Set/SetAtLevel now return (string, appended bool); the `body` shadow warning\n  consumes that write signal instead of re-deriving append-vs-replace with a\n  second Find, removing an unenforced cmd/mdsection invariant\n- rename the threaded bool to `sectionAppended` (false on the plain `--append`\n  p\n[…]\nn --create` append can shadow a wildcard reader)\n- close.go discards the new bool; a direct unit test pins that\n  sectionShadowWarning trusts the write signal (fails if it re-derives)\n\nRefs: nibs-2x53",
          "is_bot": false,
          "headline": "refactor(mdsection): make Set/SetAtLevel report append-vs-replace",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T19:04:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "58feafbe191e61329c9b0c8e2a2515461c1d8142",
          "body": "- non-blocking warning when a spelled `--section \"### X\" --set - --create`\n  appends a new heading while an EXACT same-text heading exists at another\n  level (wildcard readers — nibs context, nibs close — surface the first,\n  shadowing the new content); creation still succeeds (warn, not block)\n- ad\n[…]\ner level; else keeps `--create`\n- warning rides the exit-0 card echo: text→stderr, `--json`→a `warnings` array\n  sibling to `nib` (omitted when empty), mirroring `nibs new` duplicates\n\nRefs: nibs-m8wv",
          "is_bot": false,
          "headline": "fix(cmd): warn when `body --section --create` appends a shadowed heading",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T17:26:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "527a7f28d8a9049141f8efbd07f4f3b00516e948",
          "body": "…atch\n\n- findSection now scans exact-first: an exact heading always wins over a\n  `Name (…)` parenthetical-suffix heading regardless of document order\n  (previously first-match let an earlier parenthetical shadow the exact one),\n  fixing wildcard readers / close.go merges landing on `## X (Phase 1)`\n[…]\narenthetical fallback when no exact heading exists (intentional\n  \"target `Foo (…)` by typing `Foo`\") and document exact-first/fallback in\n  `body --help` + the mdsection doc comments\n\nRefs: nibs-6sgt",
          "is_bot": false,
          "headline": "fix(mdsection): prefer an exact heading over a parenthetical-suffix m…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T16:26:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fd01a5980cc36315b159bb1a23ca49ed8bb15010",
          "body": "…on clobber\n\n- match an existing section by heading TEXT and LEVEL: a spelled `--section`\n  level (`### Sub`) matches only a heading at that level; a bare `--section\n  \"Sub\"` stays wildcard (matches any level), preserving prior behavior\n- strict (non-`--create`) path now errors \"section not found\" o\n[…]\n..)` to avoid a two-int transposition\n- update close/plan/dedup/nibcontext callers to pass `AnyLevel` (behavior\n  preserved); document the contract in `body --help` + prompt-full.tmpl\n\nRefs: nibs-f7mj",
          "is_bot": false,
          "headline": "fix(mdsection): level-aware `--section` matching to stop silent secti…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T14:33:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "12375427527fd957b88d57649427fd919b696b14",
          "body": "- add `bodyArgs` PositionalArgs validator: when a `--set`/`--append` value\n  is a `-`-prefixed token (a swallowed flag; the only valid values are\n  `-` and `@FILE`), emit a targeted diagnostic naming it and steering to\n  `--set - <flag>`, before the generic arg-count check. Placed at\n  ValidateArgs \n[…]\neader comment (three bespoke arg validators now)\n- tests pin the diagnostic across --set/--append x 1-arg/2-arg/single-dash\n  and that valid `-`/`@FILE` channels are not false-flagged\n\nRefs: nibs-594m",
          "is_bot": false,
          "headline": "fix(cmd): name the swallowed channel-flag in `body --set`/`--append`",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T13:36:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cf877d99fef26089286ecbeee5bc80bc806456b5",
          "body": "…t-found error\n\n- add `--create` to `body`: with `--section --set` it upserts via\n  mdsection.Set (replace if present, else create at the heading's level;\n  bare heading defaults to `##`); valid only with `--section --set`\n- keep the strict default: `--section --set` without `--create` still\n  error\n[…]\nelp` states the precondition\n- tests: --create create/replace, --create=false strict-error, leading-space\n  cleanliness, level-derivation boundaries, strengthened doc/guard assertions\n\nRefs: nibs-ie1e",
          "is_bot": false,
          "headline": "feat(cmd): opt-in `--create` for `body --section --set` + teaching no…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-19T12:17:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8b387b56830d359c0afa49c62fbd3942d2732c41",
          "body": "…ermetic\n\n- FindConfig stops the upward .nibs.yml walk at NIBS_CONFIG_ROOT (if set),\n  checking dirs up to and including the ceiling but never above it; unset =\n  walk to filesystem root (unchanged)\n- make config-discovery tests hermetic via a t.Setenv-based isolateConfigSearch\n  helper so a stray ancestor /tmp/.nibs.yml can't leak in; add ceiling test\n\nRefs: nibs-8g78",
          "is_bot": false,
          "headline": "fix(config): bound FindConfig with NIBS_CONFIG_ROOT so discovery is h…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T18:40:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7c69cdf3cd5f930a4e3d62e7bc3de016b5db0771",
          "body": "- `list --parent <short-id>` silently returned nothing because the ParentID\n  branch exact-matched the raw arg against the full (prefixed) stored parent\n- route ParentID through resolveFilterID (NormalizeID) so short forms resolve;\n  unknown target short-circuits to nil, matching Blocking/BlockedBy/Mentions*\n- add short-form + unknown-target tests (short-form proven red first)\n\nRefs: nibs-40y4",
          "is_bot": false,
          "headline": "fix(graph): normalize ParentID filter like the other *ID filters",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T17:13:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99b7fb9f2c39157d98494de68c9353b8b73046e7",
          "body": "- add a warn-only, non-blocking dedup safety net: after create, scan\n  CLOSED nibs (completed/scrapped) for a likely duplicate of the new\n  title/slug and surface matches without blocking (create stays exit 0,\n  non-interactive)\n- match signal: normalized-title equality or token containment, or exac\n[…]\n the full body)\n- `--json` adds an omitempty `possible_duplicates` sibling to the {nib}\n  card contract without changing the nib object shape\n- add `--no-dedup-check` to skip the scan\n\nRefs: nibs-f25n",
          "is_bot": false,
          "headline": "feat(cmd): warn on likely duplicates of closed nibs in `nibs new`",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T17:08:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f2da3dfbbd0e5bb926c6b0cec461c0de8d7bbbcf",
          "body": "… prompt\n\n- cheat: STATUS line names the -s/--no-status groups (open|closed|parked); new\n  FILTER line documents list/rel open-by-default, --all, the \"open work under X\"\n  recipe (rel <id> --rel descendants -t bug), and the -c/-q terse caveat\n- catalog filters: document the open/closed/parked groups\n[…]\nltering paragraph (groups + open\n  default + no post-filtering)\n- tests: assert the group vocabulary + open-work recipe render in cheat/catalog\n  output (both guards verified to bite)\n\nRefs: nibs-5w6s",
          "is_bot": false,
          "headline": "docs(cmd): surface open-default + status groups in cheat/catalog/full…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T16:51:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eaeafebd55ae09e662348236cd1826cfeaa775ff",
          "body": "- resolveStatusFilter now reports openDefaultApplied so list/rel know when the\n  open default silently dropped rows\n- annotate the list/rel TSV header \"# N nibs (M hidden: completed/scrapped —\n  --all to include)\" only under the open default with M>0\n- add omitempty hidden_closed to the {nibs,count,\n[…]\n: header/JSON disclosure shown under default and suppressed for\n  -s/--all/--ready/nothing-hidden, terse outputs stay bare, hidden count\n  respects a non-status filter and --no-status\n\nRefs: nibs-tzzv",
          "is_bot": false,
          "headline": "feat(cmd): disclose completed/scrapped nibs hidden by the open default",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T16:40:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bb72da892dae9abe307e7ae45df2759d10d0aecf",
          "body": "- resolveStatusFilter now fails (exit 2) when include/exclude admit no status\n  at all (e.g. `--no-status open` under the open default, `-s open --no-status\n  open`) — a data-independent empty that an agent misreads as \"none exist\"\n- error names the effective sets and suggests --all as recovery\n- `--all --no-status open` (the closed set via exclusion) still works\n- add contradiction tests; addresses adversarial review of cae9134\n\nRefs: nibs-l0iq nibs-xvxt",
          "is_bot": false,
          "headline": "fix(cmd): error on a contradictory status filter instead of silent empty",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T16:24:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cae913426240d7dbf7b2305197f660d301036ee9",
          "body": "- Add shared cmd-layer helper resolveStatusFilter (cmd/statusfilter.go)\n  that expands status groups, applies open-by-default, and enforces the\n  base-then-subtract precedence in one place for both list and rel.\n- Accept status groups open/closed/parked anywhere a concrete status is\n  accepted in -s\n[…]\n,\n  and transitive match-only traversal.\n- Update --help/flag usage and migrate existing list/rel tests that assumed\n  the full set (add --all); add helper + behavior tests.\n\nRefs: nibs-l0iq nibs-xvxt",
          "is_bot": false,
          "headline": "feat(cmd)!: default list/rel to open nibs with status-group vocabulary",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T16:12:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "617b9724388d9c53327a5d27298ac7bdc28fc3a0",
          "body": "…ning\n\n- bfsTraverse walks transitive edges unfiltered and applies graph.ApplyFilter\n  to the emitted set, so a match behind a non-matching intermediate is returned\n- descendants/blockers-transitive/blocks-transitive/mentions-*-transitive now\n  select matches across the whole subtree; --depth counts structural hops\n- rewrite the prune test to pin match-only; add bug-under-epic and depth tests\n- update rel --help to describe match-only\n\nRefs: nibs-9h6k",
          "is_bot": false,
          "headline": "fix(rel): make transitive filters match-only, not downward-closed pru…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T15:38:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7113553f29e361d4405ee6b0d800f18a0c5da127",
          "body": "- Add shouldOpenEditor: never launch $EDITOR in --json, --no-edit, or\n  non-TTY contexts (agent Bash tool, subagent, pipe/redirect); fall back\n  to the type's template body cleanly so --json output stays parseable\n- Add --no-edit flag as an explicit opt-out escape hatch\n- Add isInteractiveTerminal s\n[…]\nditor contract in `new` help; --json now implies --no-edit\n- Tests: three guard-isolation tests (--json, --no-edit, non-TTY fallback),\n  each verified to bite when its gate is removed\n\nRefs: nibs-y6yk",
          "is_bot": false,
          "headline": "fix(cmd): gate `nibs new` editor behind --json/--no-edit/TTY",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T14:50:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9dcfe2b9833f0a50e4581877d3b036f0d73ba3cc",
          "body": "…hadowing\n\n- loadFromDisk now detects when two on-disk files parse to the same id and\n  logs a warning naming both files (absolute walk paths, like the skip warning)\n  and the id, then keeps the existing last-writer-wins behavior — a duplicate is\n  usually a transient abnormal state, so a visible wa\n[…]\n named, survivor + shadow\n  direction asserted), no false positive on distinct ids, the mccz slugged+\n  slugless pair, and a three-way collision (N-1 warnings + lexically-last winner)\n\nRefs: nibs-lmnq",
          "is_bot": false,
          "headline": "feat(nibcore): warn on duplicate nib id at load instead of silently s…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T11:01:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ee684bd60eb76963556ac3a28a83d01d8436203d",
          "body": "…refixed nibs\n\n- ParseFilename now takes (name, prefix): a name carrying the configured prefix\n  splits only on a dash AFTER the prefix, and a prefixed id with no further dash\n  is slugless (the whole name is the id). Every prefix ends in a dash, which the\n  legacy single-dash fallback mis-split (\"n\n[…]\nlers pass c.configPrefix()\n- add guards: slugless prefixed file loads under its full id; a same-id rename to\n  the slugless {id}.md form no longer evicts the nib (both proven to bite)\n\nRefs: nibs-mccz",
          "is_bot": false,
          "headline": "fix(nib): make ParseFilename prefix-aware to stop evicting slugless p…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-18T10:00:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8b2e303348c618c7c4470f84219b470b67dee422",
          "body": "- add TestCoreMutators_FreezePartition: reflects over *Core's exported methods\n  and requires each to be classified in exactly one of two registries\n  (freezeMutators / freezeNonMutators), and every mutator to be exercised by a\n  freeze-guard subtest — so a new exported mutator can't ship without co\n[…]\ncovers field\n  linking each subtest to the mutator(s) it exercises\n- document the guard's limitations honestly (exported-only; completeness not\n  correctness; covers is self-declared)\n\nRefs: nibs-hzpd",
          "is_bot": false,
          "headline": "test(nibcore): enforce freeze-guard completeness for new Core mutators",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T22:35:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1bc5f486d6c78c1af0e74de2131fdb685f2dd007",
          "body": "- the watcher slug-rename branch rewrote only Path and left the filename-derived\n  Slug stale; it now clones the stored nib, sets Path + re-derived Slug, and\n  installs a fresh pointer (copy-on-write, since Slug is a non-Path field the\n  live-pointer invariant forbids mutating in place), emitting Ev\n[…]\nsks the stale slug; also asserts the emitted event payload)\n- correct the canonical invariant doc + freeze-guard comments that still\n  described slug-rename as an in-place Path writer\n\nRefs: nibs-41xj",
          "is_bot": false,
          "headline": "fix(nibcore): update Slug (copy-on-write) on watcher same-id slug rename",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T22:07:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9fc7dcd554110075fe9bec3053b0a1ed0c019d0b",
          "body": "…e the untested host-binding gap)\n\n- ConfirmDialog takes the whole ConfirmDialogState composable and owns every\n  dismissal route (Cancel/Escape/overlay) by calling confirm.dismiss() itself;\n  App.svelte reduces to <ConfirmDialog confirm={confirmDialog} /> with no inline\n  oncancel a regression coul\n[…]\n no production reader remained\n- add ConfirmDialog owner-fire guards (Cancel/Escape/overlay), proven to bite;\n  migrate sibling white-box dismissAction assertions to behavioral checks\n\nRefs: nibs-i567",
          "is_bot": false,
          "headline": "refactor(web): move confirm-dialog dismissal into ConfirmDialog (clos…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T19:13:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b2fada051e5663241a80f9f26699b2f8ebee5cf9",
          "body": "- add a `task test:race` target scoped to internal/nibcore + internal/graph\n  (the packages carrying the concurrency invariants) and fold it into\n  `task test` so every run exercises the detector\n- add a Linux-only `-race` CI step (the invariants are OS-independent and\n  -race on Windows needs a min\n[…]\ny guards (live-pointer detachment, clone-under-lock,\nthe store-level freeze guard) degrade to trivial checks under plain `go test`\nand a reintroduced data race would pass CI silently.\n\nRefs: nibs-7l3v",
          "is_bot": false,
          "headline": "build(test): run the -race detector automatically on nibcore + graph",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T18:39:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "408d3397519f1d32d157fd9b133dd78b7aac8251",
          "body": "…ariant + consolidate its canonical doc\n\n- add TestCoreMutators_FreezeGuard: drives every Core mutator against\n  already-published nibs and asserts (reflect.DeepEqual, Path neutralized,\n  both sides re-cloned to keep load-boundary fields symmetric) that none\n  mutates a non-Path field in place on a \n[…]\nlink_health.go, bulkreorder.go)\n  now defer to it, and the contradictory in-place-writer lists are reconciled\n- clarify slug-rename rewrites only Path in place (Slug is copy-on-write)\n\nRefs: nibs-0usi",
          "is_bot": false,
          "headline": "test(nibcore): add store-level freeze guard for the copy-on-write inv…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T18:34:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "03822e3ae766d29747f2e800df05e7cb7a135162",
          "body": "…is deleted concurrently\n\n- snapshotResults (bulk-reorder helper) now skips elements whose post-write\n  GetSnapshot is !ok (vanished via concurrent delete) and returns the surviving\n  ordered set, instead of failing the whole already-persisted batch; singular\n  snapshotResult is intentionally unchan\n[…]\nub);\n  update the stale :806 subtest to the new contract\n- disclose the shorter-list-under-concurrent-delete behavior in the public\n  reorderChildren/reorderSiblings schema docstrings\n\nRefs: nibs-3lul",
          "is_bot": false,
          "headline": "fix(graph): return surviving snapshots when a bulk-reordered sibling …",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T17:46:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5b3f87dadbc15b413a49754f85ff3157f6c9d56e",
          "body": "- GetForUpdate now delegates to GetSnapshot (clone-under-RLock) instead of\n  c.Get + off-lock Clone, so the working-copy Path read can no longer race an\n  in-place Path writer (Archive/Unarchive) holding c.mu\n- add TestGetForUpdateRaceAgainstArchive: reproduces the data race pre-fix,\n  clean post-fix (with a return-value assertion on the clone)\n- correct now-stale live-pointer/in-place-mutation comments in core.go,\n  graph/interfaces.go, and resolver_snapshot_test.go\n\nRefs: nibs-r8m5",
          "is_bot": false,
          "headline": "fix(nibcore): clone GetForUpdate's working copy under the store lock",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T17:21:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f6d51442052e7ce853197346d8bc65de7d9e9e22",
          "body": "…pointers on the write side)\n\n- All 10 nib-returning mutation resolvers (CreateNib, UpdateNib, SetParent,\n  AddBlocking, RemoveBlocking, AddBlockedBy, RemoveBlockedBy, ReorderNib,\n  ReorderChildren, ReorderSiblings) now return Reader.GetSnapshot clones via new\n  snapshotResult/snapshotResults helper\n[…]\nistic detachment guards (all fire pre-fix) + an\n  executor -race demonstrator; stubWriter now installs into stubReader (models the\n  real Core's read-after-write) with a nil-map guard\n\nRefs: nibs-hi5i",
          "is_bot": false,
          "headline": "fix(graph): snapshot mutation-resolver return values (no live c.nibs …",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T16:02:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3920c5b039456c44a4c97805654410f727218acf",
          "body": "…the Nibs-pipeline data race)\n\n- RemoveLinksTo and FixBrokenLinks cloned nothing: they mutated the stored c.nibs\n  pointer's Parent/BlockedBy/Documents in place under c.mu, while the GraphQL Nibs\n  filter/sort pipeline reads Parent/BlockedBy off those live pointers off-lock — a\n  race the detector f\n[…]\nboth mutators\n- Update the snapshot docs (interfaces.go / schema.resolvers.go / projection_resolver.go)\n  to state no non-Path field is mutated in place on a published pointer anymore\n\nRefs: nibs-pyei",
          "is_bot": false,
          "headline": "fix(nibcore): make RemoveLinksTo/FixBrokenLinks copy-on-write (close …",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T13:36:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e78e7009e8fb3f129c918c5c74c2078dbad27fb8",
          "body": "…s() method\n\n- Add dismiss() to ConfirmDialogState/createConfirmDialog: capture the dismissal\n  owner, close(), then fire the owner — the capture->close->fire dance previously\n  inlined in App.svelte's ConfirmDialog oncancel, now unit-testable\n- App.svelte oncancel becomes a single confirmDialog.dis\n[…]\ncel vs a leaked\npromise are DOM-indistinguishable); comments say so honestly and the host-wiring\nguard is deferred to nibs-i567 (a ConfirmDialog production seam or a Playwright test).\n\nRefs: nibs-imgm",
          "is_bot": false,
          "headline": "refactor(web): fold confirm-dialog dismissal into a structural dismis…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T10:54:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3adfa3ea2ccd797f2ef8dfb39ed4547b2bcc2d66",
          "body": "…elope\n\n- Add shared coded arg validators in cmd/args.go (codedNoArgs/codedExactArgs/\n  codedMinimumNArgs/codedMaximumNArgs) that emit cmdError(ErrValidation) on an\n  arity violation: exit 2 always, plus the {error:{code,message}} envelope for\n  --json commands — matching value-validation errors (wa\n[…]\ns-name assertion), a per-command\n  wiring table that detects a swapped json pointer, and a structural drift guard\n  that fails if any leaf command regresses to a stock cobra validator\n\nRefs: nibs-2isj",
          "is_bot": false,
          "headline": "fix(cli): route arg-count (usage) errors through the coded --json env…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T10:02:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bec22a5c52bb2ca4e0502a6971ff28e2c9097ff9",
          "body": "…is attached\n\n- Add SubscribeSignal() — a signal-only watcher subscription (chan struct{});\n  the TUI (RealBackend) uses it since it discards payloads and only ticks\n- handleChanges clones each event's Nib only when a payload subscriber is\n  attached (hasPayloadSubscribers, a lock-free atomic payloa\n[…]\n-send wedge)\n- Tests: clone-gating predicate, signal delivery, skip-path payload-drop,\n  StopWatching count reset, and a -race skip-path smoke test; keep the y5nb\n  immutability guard\n\nRefs: nibs-hz5b",
          "is_bot": false,
          "headline": "perf(nibcore): skip watcher payload clone when no payload subscriber …",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T08:44:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "acc3a3ed74e2c84f0b310b878e38451d7d0ff41e",
          "body": "…ve c.nibs pointers)\n\n- Convert Mentions/MentionedBy/Nib/Nibs(+Search) to return Reader.GetSnapshot\n  clones under the lock, so no live c.nibs pointer outlives the store lock to\n  reach gqlgen's async marshaler (extends the nibs-yr1j relationship-resolver rule)\n- Add deterministic detachment guards \n[…]\nd Critical: Nibs pipeline reads\nParent/BlockedBy off-lock vs RemoveLinksTo/FixBrokenLinks in-place mutation) and\nnibs-hi5i (write-side: mutation resolvers still return live pointers).\n\nRefs: nibs-jt2f",
          "is_bot": false,
          "headline": "fix(graph): route remaining read resolvers through GetSnapshot (no li…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-17T07:33:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d0a3d648da86832b1f7044e7a19294ffd89d0184",
          "body": "- Extract one shared, bucket-safe getActionTargetIds into lib/actionTarget.ts,\n  parameterized over the context-target source; delete the two divergent copies\n  in useKeyboardShortcuts and RowContextMenu\n- Exclude isBucketId targets from focusedNibId and the context-menu/right-click\n  target (both u\n[…]\navigateToNib so a bucket id never writes a dangling\n  ?nib=<bucket> history/URL entry\n- Tests cover the focus path, the right-click path, and the history push;\n  guards proven to bite\n\nRefs: nibs-oxaq",
          "is_bot": false,
          "headline": "fix(web): never resolve a bucket id as a delete/bulk-action target",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T21:28:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "74d00be05391a5a54617f13c004da8fe8baa02e5",
          "body": "- Enrich the subscription dedup key with the payload etag\n  (`${type}:${nibId}:${etag}`) so a genuinely distinct second edit to the same\n  nib (new etag) triggers a refetch instead of being coalesced away, which\n  left the tree stale relative to that edit\n- Burst coalescing is preserved: duplicate e\n[…]\npe:nibId) dedup is unchanged\n- Tests: two distinct-etag same-nib edits → two refetches (guard bites); 20\n  identical emissions still coalesce to 1, both with undefined and shared etag\n\nRefs: nibs-s6es",
          "is_bot": false,
          "headline": "fix(web): don't drop a second same-nib edit in TreeTable's event dedup",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T21:19:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a24ce7d9e73974d2a3d7680b3aac1308bbdcc5a0",
          "body": "- Capture the deleted-branch setTimeout handle in a component-scoped var and\n  clearTimeout it in onDestroy, so a deferred refetch never fires after the\n  component is torn down (reexecute on a disposed store)\n- Cleared on true unmount (onDestroy), not via an $effect cleanup, so a\n  still-pending de\n[…]\n Add tests: no reexecute after unmount within the fade window (guard bites),\n  and the deferred refetch still fires once while mounted (pins the previously\n  uncovered deleted branch)\n\nRefs: nibs-mib1",
          "is_bot": false,
          "headline": "fix(web): clear TreeTable's deferred delete refetch timer on unmount",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T21:15:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "12014b606472057df0a8521f919ad343364e87a7",
          "body": "…tUnarchived)\n\n- Add a distinct EventUnarchived event type (Go): watcher's unarchive-out\n  branch now emits it instead of reusing EventUpdated, so an unarchive is no\n  longer indistinguishable from an in-place edit (no GraphQL schema change —\n  type is String!)\n- Web classifier (nibChange.ts): an `u\n[…]\n so the banner\n  comes down without a reload\n- changeTracker highlights `unarchived` like an update (no DEV warning)\n- Plain `updated` still never clears gone (existing pin preserved)\n\nRefs: nibs-2fgz",
          "is_bot": false,
          "headline": "fix: clear the stale 'archived' banner on an external unarchive (Even…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T21:00:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c4545f5126538798e956e2120e5a517658526a48",
          "body": "- Add findRelPathByID: scans the data dir + archive subdir for a file whose\n  parsed id matches, recognizing a nib by id rather than exact basename\n- In handleChanges' removal branch, after the two basename checks (archive-in,\n  unarchive-out) miss and before the genuine-delete fall-through, look th\n[…]\n a title change pulled from another machine)\n- Bounded: the scan runs only on the delete-miss path, under c.mu\n- Test both orderings (remove-first, create-first); guard proven to bite\n\nRefs: nibs-ab2s",
          "is_bot": false,
          "headline": "fix(nibcore): keep a nib live across a same-id slug rename",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T20:46:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1463abd7e96f29efc54648bf56a48e13b3b61452",
          "body": "…lvers\n\n- Add nibcore Core.GetSnapshot(id): clones the stored nib WHILE c.mu (RLock)\n  is held, so the returned value never aliases the live store pointer and no\n  field is read off-lock; add it to the NibReader interface\n- Rewire Parent/Children/BlockedBy/Blocking to return GetSnapshot clones\n  ins\n[…]\nolver to Get\n  re-fires the race, confirming the guard bites\n- Scoped to the 4 named resolvers; Mentions/top-level Nib/Nibs/Search and\n  projection_resolver left for a follow-up audit\n\nRefs: nibs-yr1j",
          "is_bot": false,
          "headline": "fix(graph): return cloned-under-lock snapshots from relationship reso…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T20:36:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9c1188b88fb9833dd5f797b62f3fc69529796f88",
          "body": "…wser\n\n- Replace the raced `var openedURL string` (written on the server goroutine,\n  read on the test goroutine) with a buffered channel, giving a real\n  happens-before edge\n- Remove the now-redundant TCP-dial readiness poll — the channel receive both\n  proves the callback fired and synchronizes its write\n- Test-only change; no production code touched\n\nRefs: nibs-xqpa",
          "is_bot": false,
          "headline": "fix(test): sync openedURL over a buffered channel in TestServeOpenBro…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T20:07:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "39c6ceb2e2d89d190c97646c9bfaa654b17e55bb",
          "body": "…elocate/trim the rest\n\nActiveNibView carried dense comments asserting facts about OTHER files that drift\nsilently. Sorted each claim by what it is:\n\n- the tailwind-merge modifier claim (a bare bg-transparent does not drop a later\n  dark:bg-input/30) is falsifiable by a dependency bump — converted t\n[…]\nne)\n\nComments only in the two components (verified: no runtime line changed); the\nguard is the sole new runtime code, and it bites (flips red if twMerge stops\nkeying on the modifier).\n\nRefs: nibs-2sdz",
          "is_bot": false,
          "headline": "refactor(web): pin ActiveNibView's tailwind-merge claim as a guard, r…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T19:19:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c2ee2e6a075d5f4cfbf46493a673a915a4949247",
          "body": "When the live subscription was down and a viewed dirty nib was deleted\nserver-side, Save dispatched, failed with a raw \"nib not found\" toast, and the\nview stayed `viewing` — no deleted notice, Save a repeated dead end. (The\noriginally-reported \"stranded panel\" does not reproduce: Discard always esca\n[…]\nte can't close a freshly-reopened buffer\n\nThe nib's original strand trace was refuted by a reproduce-first probe and the nib\nrewritten to this demonstrated defect before implementing.\n\nRefs: nibs-w1gw",
          "is_bot": false,
          "headline": "fix: route a deleted-nib Save to the gone notice instead of a raw toast",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T19:11:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b5f7ed8db281429efd67a22f8f2531ad940b319e",
          "body": "…a promise\n\nconfirmDiscard stored its resolver in a single shared slot; a second confirm\n(reached by pressing `n` while a discard dialog was open, because modalOpen()\ngated on the expanded view, not the confirm dialog) overwrote the slot and leaked\nthe first promise, hanging guarded() forever and st\n[…]\nth closed-dialog controls); the n-during-discard close no longer strands\n\nDeferred: nibs-imgm (harden the dismissal contract against future regression —\nzero present risk per review).\n\nRefs: nibs-an5d",
          "is_bot": false,
          "headline": "fix(web): make overlapping confirm dialogs settle instead of leaking …",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T15:14:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3050eaf71b18e5cd9a6ea70e64c246b9feac1d4d",
          "body": "isInputFocused() gates the global shortcuts (n/e/Delete/Backspace) on tag name\nonly, so a readonly input is already treated like an editable one and the\nshortcuts stay suppressed — correct, but invisible in the code (it holds because\nthe check omits `readonly`, inviting a future `if (el.readOnly) re\n[…]\n non-input positive control confirms isInputFocused() is what suppresses it\n- proven to bite: adding the readonly early-return to isInputFocused() fails it\n- production code unchanged\n\nRefs: nibs-ir5t",
          "is_bot": false,
          "headline": "test(web): pin that readonly inputs suppress destructive shortcuts",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T14:15:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1b47e50f35fbf1ac18fbd32de757f3798fc0c972",
          "body": "…from the DOM\n\nSpace on a Tab-focused row title fired a native click (opening the nib) instead\nof toggling selection, because the Enter/Space keyboard path trusted the virtual\n`focusedNibId`, which Tab does not set (DOM focus and the virtual focus model were\nunsynced).\n\n- resolve the acted-on row fr\n[…]\nn passive Tab. Resolving\nfrom the DOM event closes all three and needs no focus sync. The \"focus ring\nfollows DOM focus on Tab\" goal is left to the deferred roving-tabindex a11y work.\n\nRefs: nibs-504h",
          "is_bot": false,
          "headline": "fix(web): Space on a focused row title toggles it, resolving the row …",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T14:08:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "96c97d0684ca52633bc6fe843d14cc257f93c761",
          "body": "A shift-click/shift-arrow whose range spanned a grouping bucket swept the bucket's\nsynthetic id (e.g. __no_milestone__) into selectedIds, where it is unresolvable\nfor any bulk action. Closed the whole SelectionState invariant, not just the\nreported path:\n\n- rangeSelect filters bucket ids out of its \n[…]\nble bucket-click comment updated\n  to match\n\nDeferred: nibs-oxaq (delete/bulk dispatch and history URL accept a bucket id from\nfocus/right-click — a different layer than selectedIds).\n\nRefs: nibs-mn0t",
          "is_bot": false,
          "headline": "fix(web): never admit a synthetic bucket id to selectedIds (any writer)",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T12:20:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6ba1eb49cf356dfe27b8f9938cc354a6f6ad5782",
          "body": "…he flush\n\nTreeTable's subscription effect called result.reexecute() synchronously inside\nuntrack() for non-deleted events. A throw (or absent reexecute) propagated out of\nthe $effect and aborted Svelte's entire effect flush, silently killing live\nupdates for the rest of the session — the failure mo\n[…]\nomment that described the now-removed flush-abort\n\nDeferred: nibs-mib1 (deferred refetch timer not cleared on unmount), nibs-s6es\n(dedup may drop a second same-nib edit — unverified).\n\nRefs: nibs-w4zz",
          "is_bot": false,
          "headline": "fix(web): isolate the live-bridge reexecute so one throw can't kill t…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T11:22:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bf835c82447c4f23ace318af26f074b2e69681cc",
          "body": "Audit of the 9 commands that silently swallowed positional args. Applied the\ncorrect validator per command (not a blind NoArgs sweep):\n\n- new -> MaximumNArgs(1): it joins args into the title, and `nibs new` (0 args)\n  -> \"Untitled\" is valid, so ExactArgs(1) would regress the no-title path\n- check, i\n[…]\nt stating why. new_test pins the arity guard to the\narg-count error specifically.\n\nDeferred: nibs-2isj (arg-count errors bypass the --json envelope CLI-wide —\npre-existing, systemic).\n\nRefs: nibs-ejbe",
          "is_bot": false,
          "headline": "fix(cli): give every arg-less command an Args validator",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T10:41:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9c1b4d5d2b26c0bb411f47758971e2cb7ea94b29",
          "body": "…g them\n\n- `nibs archive <id>` silently discarded the id and archived every eligible nib;\n  an agent archived 18 nibs intending to archive one\n- add a custom Args validator: exit 2, and the error names `nibs rm <id>` (which\n  already archives by default) as the id-taking alternative\n- the coded erro\n[…]\nrs are plain text, exit 1)\n- new cmd/archive_test.go: asserts nothing is archived (file state, not just exit\n  code) and the no-arg happy path is unchanged; both guards proven to bite\n\nRefs: nibs-ejbe",
          "is_bot": false,
          "headline": "fix(cli): reject positional args to `nibs archive` instead of ignorin…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T10:41:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a522736841418cc28060950291c822fc5a7036aa",
          "body": "…apshot event payloads\n\n- rename Core.Unwatch -> Core.StopWatching so the core matches its own\n  StartWatching and the TUI Backend interface (no backwards-compat constraint)\n- document Subscribe()'s sharp edges: backpressure drop (buffer 16), empty-batch\n  early-return notifies nobody, StopWatching \n[…]\nremoved build)\n\nDeferred: nibs-hz5b (clone paid even when payload discarded), nibs-yr1j\n(relationship resolvers read path off-lock — pre-existing, same live-pointer theme).\n\nRefs: nibs-y5nb, nibs-6fbd",
          "is_bot": false,
          "headline": "refactor(core)!: rename Unwatch->StopWatching; document Subscribe; sn…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T10:06:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "61e01aa24503228efcf30da71fa34a7e25ec2684",
          "body": "…d.Path\n\nThe watcher's removal branch decided archive-vs-delete from stored.Path, which is\nauthoritative only for a move Core.Archive made in-process. Any external mover left\nit stale, so the move fell through to the delete branch nondeterministically\n(Go-map batch iteration).\n\n- read direction from\n[…]\nmits\n  EventUpdated regardless\n\nDeferred: nibs-2fgz (stale gone-banner on unarchive), nibs-ab2s (same-id slug\nrename still evicts — pre-existing, third external-move case).\n\nRefs: nibs-y56n, nibs-ow1k",
          "is_bot": false,
          "headline": "fix(core): decide archive/unarchive/delete from disk truth, not store…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T09:28:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bec2fd913b2c80433dc207d9578c133640425df7",
          "body": "- watchLoop took `done <-chan struct{}` as a parameter captured under c.mu at\n  spawn, instead of selecting on the c.done field each iteration\n- an Unwatch->StartWatching restart no longer orphans the old loop onto the new\n  channel (goroutine + fsnotify watcher + fd leak, duplicate events); also\n  \n[…]\ntolerates fsnotify's Windows Create/Write split without\n  false-failing, and does not miss a late duplicate\n- stale-debounce-timer on restart deferred as nibs-ifql (out of scope here)\n\nRefs: nibs-9cac",
          "is_bot": false,
          "headline": "fix(core): capture watchLoop's done channel in the lock, not the field",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-16T08:21:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d700c3537df1f4f497d6281aa54cf799d0d40dd1",
          "body": "- Archived nibs stay in the store and remain visible in all queries;\n  assuming otherwise shipped a fade for a row that never leaves\n- --nibs-path moves only the data dir, so config still comes from cwd;\n  this ran the fixture under the wrong prefix in demo and screenshots\n- go build fails in a fres\n[…]\n\n- A finding is a claim, and a nib made from one inherits the claim without\n  its evidence; four of seven premises in one batch were false\n- No prettier config — running it churned 129 unrelated lines",
          "is_bot": false,
          "headline": "docs: record what two batches of reviews taught us",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-15T22:27:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "702145ff18e379cfc6f9a10d01bc980419cea9d8",
          "body": "- The delegated handler dispatched on data-action before reading modifiers,\n  so a title click early-returned past the ctrl/shift branch: the gesture\n  was never captured, and opening the nib then reset the selection\n- Title and row-body clicks now share one modifier path, which is what the\n  handle\n[…]\n. A ctrl/shift-click on a\n  bucket's body already reached toggleSelect before this\n- Drop a title-click test that became a duplicate, rather than keep a\n  restatement of its neighbour\n\nRefs: nibs-s0tn",
          "is_bot": false,
          "headline": "fix(web): read modifiers on a title click, not just on the row body",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-15T22:03:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c5ac35f9fa2cf72553d5b98d242888da7515634b",
          "body": "- While gone the body renders as preview only, so the raw markdown of any\n  unsaved edits was on screen in rendered form alone; add a Copy body\n  action that hands back the source\n- Offer it only for a deleted nib: an archived buffer still saves, and an\n  escape hatch beside a working Save steers us\n[…]\nonly would let it take a caret early\n- Paint the action against the notice band; the outline variant sets no\n  resting text color, so it inherited near-white on near-white in Daylight\n\nRefs: nibs-mpo4",
          "is_bot": false,
          "headline": "feat(web): let a deleted nib's unsaved markdown be copied out",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-15T21:16:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "931635291dc7ccc0e5cd7cfee1f0b657b0959a7f",
          "body": "…laiming\n\n- The comment claimed the check decides the same way whichever order\n  fsnotify delivers the rename and the create in; that holds only for a\n  move this process made\n- An archive performed elsewhere leaves the stored Path pointing at the\n  vanished file, so the move reports as a deletion — and because the batch\n  is a Go map, which half wins is not stable run to run\n\nRefs: nibs-y56n",
          "is_bot": false,
          "headline": "docs(core): state the archive-detection precondition instead of overc…",
          "author_name": "Alphaleonis",
          "author_login": "alphaleonis",
          "committed_at": "2026-07-15T19:14:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 13,
      "commits_last_year": 343,
      "latest_release_at": "2026-07-25T16:35:37Z",
      "latest_release_tag": "v0.7.0",
      "releases_from_tags": false,
      "days_since_last_push": 2,
      "active_weeks_last_year": 9,
      "days_since_latest_release": 2,
      "mean_days_between_releases": 11.5
    },
    "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/alphaleonis/nibs",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/alphaleonis/nibs",
          "is_deprecated": false,
          "latest_version": "v0.7.0",
          "repository_url": "https://github.com/alphaleonis/nibs",
          "versions_count": 14,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-25T16:21:06Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 2
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 1,
      "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": [
        "Taskfile.yml",
        "mise.toml"
      ],
      "api_schema_files": [
        "internal/graph/schema.graphqls"
      ],
      "has_devcontainer": false,
      "typecheck_configs": [
        "web/tsconfig.json"
      ],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 258861,
      "source_files_sampled": 399,
      "oversized_source_files": 5,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 19108
    },
    "dependencies": {
      "manifests": [
        "go.mod",
        "web/package.json"
      ],
      "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",
        "npm"
      ],
      "dependencies": [
        {
          "name": "github.com/99designs/gqlgen",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.17.84"
        },
        {
          "name": "github.com/adrg/frontmatter",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.2.0"
        },
        {
          "name": "github.com/atotto/clipboard",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.1.4"
        },
        {
          "name": "github.com/blevesearch/bleve/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.5.6"
        },
        {
          "name": "github.com/charmbracelet/bubbles",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.21.1-0.20250623103423-23b8fd6302d7"
        },
        {
          "name": "github.com/charmbracelet/bubbletea",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.3.10"
        },
        {
          "name": "github.com/charmbracelet/glamour",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.10.0"
        },
        {
          "name": "github.com/charmbracelet/lipgloss",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.1-0.20250404203927-76690c660834"
        },
        {
          "name": "github.com/charmbracelet/x/ansi",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.11.2"
        },
        {
          "name": "github.com/creativeprojects/go-selfupdate",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.0"
        },
        {
          "name": "github.com/fsnotify/fsnotify",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.9.0"
        },
        {
          "name": "github.com/gorilla/websocket",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.5.3"
        },
        {
          "name": "github.com/matoous/go-nanoid/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.1.0"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "github.com/spf13/pflag",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.10"
        },
        {
          "name": "github.com/tidwall/pretty",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.2.1"
        },
        {
          "name": "github.com/vektah/gqlparser/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.5.31"
        },
        {
          "name": "github.com/yuin/goldmark",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.7.13"
        },
        {
          "name": "golang.org/x/mod",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.36.0"
        },
        {
          "name": "golang.org/x/sys",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.47.0"
        },
        {
          "name": "golang.org/x/term",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.44.0"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        },
        {
          "name": "@codemirror/lang-markdown",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.5.0"
        },
        {
          "name": "@codemirror/state",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.6.0"
        },
        {
          "name": "@codemirror/theme-one-dark",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.1.3"
        },
        {
          "name": "@codemirror/view",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.40.0"
        },
        {
          "name": "@urql/svelte",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.0.0"
        },
        {
          "name": "bits-ui",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.16.3"
        },
        {
          "name": "clsx",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.1"
        },
        {
          "name": "codemirror",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.0.2"
        },
        {
          "name": "dompurify",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.3.3"
        },
        {
          "name": "graphql",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^16.13.2"
        },
        {
          "name": "graphql-ws",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.0.7"
        },
        {
          "name": "marked",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^17.0.5"
        },
        {
          "name": "paneforge",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.0.2"
        },
        {
          "name": "tailwind-merge",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.5.0"
        },
        {
          "name": "tinykeys",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.0.0"
        }
      ],
      "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": 0,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "alphaleonis",
          "commits": 343,
          "avatar_url": "https://avatars.githubusercontent.com/u/5114354?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "release.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum",
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "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": 10,
            "reason": "project is fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 9,
            "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": 3,
            "reason": "dependency not pinned by hash detected -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 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": 0,
            "reason": "34 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "41e029500290dfc9b05fc5a734aa4c3559b78692",
        "ran_at": "2026-07-27T19:22:09Z",
        "aggregate_score": 3.8,
        "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-25T16:33:15Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": null,
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/alphaleonis/nibs",
    "host": "github.com",
    "name": "nibs",
    "owner": "alphaleonis"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 46,
      "inputs": {
        "security": 38,
        "vitality": 78,
        "community": 21,
        "governance": 37,
        "engineering": 52
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 78,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "commits_last_year": 343,
              "human_commit_share": 1,
              "days_since_last_push": 2,
              "active_weeks_last_year": 9
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 2 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 2
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "9/52 weeks with commits",
                "points": 6.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 9
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "343 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 343
                    }
                  }
                ],
                "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": 13,
              "latest_release_tag": "v0.7.0",
              "releases_from_tags": false,
              "days_since_latest_release": 2,
              "mean_days_between_releases": 11.5
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "13 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 13
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 2 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 2
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~11.5 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 11.5
                    }
                  }
                ],
                "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": 21,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 1,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "1 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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": "at_risk",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 44,
            "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": "license file present, not a recognized license",
                "points": 16.9,
                "status": "partial",
                "details": [
                  {
                    "code": "license_custom",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "at_risk",
        "name": "Sustainability & Governance",
        "value": 37,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "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 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution",
                    "pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "merged_prs": 0,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 0
            },
            "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": "no decided pull requests or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_decided_prs_or_data",
                    "params": {}
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 56,
            "inputs": {
              "followers": 43,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "alphaleonis",
              "public_repos": 29,
              "account_age_days": 4746
            },
            "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": "43 followers of alphaleonis",
                "points": 11.8,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 43,
                      "login": "alphaleonis"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "29 public repos, account ~13 yr old",
                "points": 22.8,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 29
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 13
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/alphaleonis/nibs"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 2
            },
            "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 2 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 2
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "14 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 14
                    }
                  }
                ],
                "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": 52,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "at_risk",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "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": 0,
                "status": "missed",
                "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": 38,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 38,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 3.8
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "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 fuzzed",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.2,
                "status": "partial",
                "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 3",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file 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": "34 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 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": 72,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.94,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 19108
            },
            "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": "94 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 94,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 64,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum",
                "package-lock.json"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "Taskfile.yml",
                "mise.toml"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "web/tsconfig.json"
              ],
              "agent_commit_share": 0,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Taskfile.yml, mise.toml",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Taskfile.yml, 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": "web/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "web/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "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 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 258861,
              "source_files_sampled": 399,
              "oversized_source_files": 5
            },
            "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": "5/399 source files over 60KB",
                "points": 54.3,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 399,
                      "oversized": 5
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [],
              "has_mcp_signal": false,
              "api_schema_files": [
                "internal/graph/schema.graphqls"
              ]
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": "internal/graph/schema.graphqls",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "internal/graph/schema.graphqls"
                    }
                  }
                ],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-27T19:22:14.965857Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/a/alphaleonis/nibs.svg",
  "full_name": "alphaleonis/nibs",
  "license_state": "custom",
  "license_spdx": null
}

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

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

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