Registro público
Informe de salud del softwareesquema 0.26.0 · métricas 1.13.0 · 2026-07-22 03:25 UTC

shhac / lib-agent-cli

Shared CLI runtime for agent-first tools: cobra root scaffolding + credential plumbing (XDG config, 0600 store, macOS keychain), atop lib-agent-output.

GoLicencia propia★ 0 estrellas⑂ 0 forksdesde jun 2026Ver en GitHub ↗

shhac/lib-agent-cli tiene un índice de salud de 45 sobre 100, lo que lo sitúa en la banda En riesgo. Su puntuación más alta es AI Readiness (73/100) y la más baja, Community & Adoption (21/100). Se actualizó por última vez hace 4 días. Una sola persona concentra la mayor parte del trabajo reciente.

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

45
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

Paul SomersCuenta personal
10 seguidores63 repositorios públicosdesde nov 2012

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/shhac/lib-agent-cliv0.21.0-26hace 4 días

Métricas por categoría

Vitalidad

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

68Moderado · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 4 días
3.5/36Cadencia de commits — 5/52 semanas con commits
15.4/18Volumen de commits — 51 commits en el último año
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Datos de entrada utilizados
commits_last_year51
human_commit_share1
days_since_last_push4
active_weeks_last_year5
Cómo se puntúa
16.2/27Publica versiones — 26 etiquetas de versión (sin releases de GitHub)
36/36Recencia de las versiones — última versión hace 4 días
27/27Cadencia de publicación — una versión cada ~2,8 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count26
latest_release_tagv0.21.0
releases_from_tags
days_since_latest_release4
mean_days_between_releases2,8
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

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 — 0 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
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?

36En 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
7.5/25Alcance del propietario — 10 seguidores de shhac
25/25Trayectoria — 63 repos públicos, cuenta de ~13 años
Datos de entrada utilizados
followers10
owner_typeUser
is_verified
owner_loginshhac
public_repos63
account_age_days4997
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 4 días
20/20Historial de versiones — 26 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesgithub.com/shhac/lib-agent-cli
ecosystemsgo
any_deprecatedno
min_days_since_publish4

Calidad de Ingeniería

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

68Moderado · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 1 flujo(s) de trabajo
24/24Pruebas presentes
16/16Configuración de linter — .golangci.yml
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_config
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

50Moderado
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
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
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?

23Crítico · 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
0/5Fuzzing — project is not fuzzed
2.2/2.5Licencia — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — sin datos
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — sin datos
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0.8/7.5Vulnerabilities — 9 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated15
scorecard_versionv5.5.0
checks_inconclusive3
scorecard_aggregate2,3
Excluidos de la puntuación (sin datos o no aplicable): ci_tests, packaging, signed_releases. 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.

73Bueno · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — AGENTS.md, CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 48 de 51 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,941
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes3304
Cómo se puntúa
12.6/18Arranque con un solo comando — go.mod (convención del toolchain, sin ejecutor de tareas)
22/22Pruebas automatizadas
11/11Configuración de lint / formato — .golangci.yml
11/11Verificación estática de tipos — Go (tipado estático)
10/10Entorno reproducible — lockfile
0/10Práctica demostrada con agentes — ningún commit con autoría de agente entre los últimos 51
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfilesgo.sum
has_dockerfileno
typed_language
bootstrap_files
has_devcontainerno
has_linter_config
typecheck_configs
agent_commit_share0
toolchain_manifestsgo.mod
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Go (tipado estático)
55/55Tamaños de archivo manejables — 0/59 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes9183
source_files_sampled59
oversized_source_files0
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
0/20Servidor MCP
40/40Ejemplos ejecutables — examples
Datos de entrada utilizados
example_dirsexamples
has_mcp_signalno
api_schema_files

Datos clave

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

Advertencias de recopilación de datos

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

Más detalle

OpenSSF Scorecard 2.3 / 10
2.3agregado

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-22 03:25 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
0Fuzzingproject is not fuzzed
9Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
n/dPackagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
n/dSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
1Vulnerabilities9 existing vulnerabilities detected
Dependencias directas 6
RegistroPaqueteRestricción de versiónManifiesto
Gogithub.com/mattn/go-isattyv0.0.22go.mod
Gogithub.com/ncruces/zenityv0.10.14go.mod
Gogithub.com/shhac/lib-agent-outputv0.10.0go.mod
Gogithub.com/spf13/cobrav1.10.2go.mod
Gogopkg.in/yaml.v3v3.0.1go.mod
Gogithub.com/shhac/lib-agent-keyringv0.1.1go.mod
Todas las dependencias no recopilado

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

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 155,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Go": 120495
      },
      "pushed_at": "2026-07-17T15:39:33Z",
      "created_at": "2026-06-19T12:29:04Z",
      "owner_type": "User",
      "updated_at": "2026-07-17T15:39:36Z",
      "description": "Shared CLI runtime for agent-first tools: cobra root scaffolding + credential plumbing (XDG config, 0600 store, macOS keychain), atop lib-agent-output.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": "NOASSERTION",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Paul Somers",
      "type": "User",
      "login": "shhac",
      "company": null,
      "location": "London, UK",
      "followers": 10,
      "avatar_url": "https://avatars.githubusercontent.com/u/2800184?v=4",
      "created_at": "2012-11-14T23:30:38Z",
      "is_verified": null,
      "public_repos": 63,
      "account_age_days": 4997
    },
    "license": {
      "state": "custom",
      "spdx_id": null,
      "raw_spdx": "NOASSERTION",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.21.0",
          "kind": "minor",
          "published_at": "2026-07-17T15:37:28Z"
        },
        {
          "tag": "v0.20.0",
          "kind": "minor",
          "published_at": "2026-07-08T14:11:52Z"
        },
        {
          "tag": "v0.19.0",
          "kind": "minor",
          "published_at": "2026-07-07T09:41:34Z"
        },
        {
          "tag": "v0.18.0",
          "kind": "minor",
          "published_at": "2026-06-29T00:31:38Z"
        },
        {
          "tag": "v0.17.0",
          "kind": "minor",
          "published_at": "2026-06-28T12:36:19Z"
        },
        {
          "tag": "v0.16.0",
          "kind": "minor",
          "published_at": "2026-06-23T00:28:31Z"
        },
        {
          "tag": "v0.15.0",
          "kind": "minor",
          "published_at": "2026-06-22T23:42:08Z"
        },
        {
          "tag": "v0.14.0",
          "kind": "minor",
          "published_at": "2026-06-22T22:55:48Z"
        },
        {
          "tag": "v0.13.0",
          "kind": "minor",
          "published_at": "2026-06-22T22:27:51Z"
        },
        {
          "tag": "v0.12.0",
          "kind": "minor",
          "published_at": "2026-06-22T10:43:24Z"
        },
        {
          "tag": "v0.11.0",
          "kind": "minor",
          "published_at": "2026-06-22T10:04:13Z"
        },
        {
          "tag": "v0.10.0",
          "kind": "minor",
          "published_at": "2026-06-22T09:21:57Z"
        },
        {
          "tag": "v0.9.1",
          "kind": "patch",
          "published_at": "2026-06-21T23:26:27Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2026-06-21T23:18:58Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-06-21T20:32:27Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-06-21T20:01:35Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-06-21T12:21:55Z"
        },
        {
          "tag": "v0.5.1",
          "kind": "patch",
          "published_at": "2026-06-21T11:40:20Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-06-20T23:44:12Z"
        },
        {
          "tag": "v0.4.2",
          "kind": "patch",
          "published_at": "2026-06-20T09:23:21Z"
        },
        {
          "tag": "v0.4.1",
          "kind": "patch",
          "published_at": "2026-06-20T09:21:39Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-06-20T00:00:37Z"
        },
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2026-06-19T23:18:47Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-06-19T23:08:44Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-06-19T18:07:01Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-06-19T17:19:58Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "7c67bc6351abed679124f4805a9fa210e2c0eec4",
          "body": "Two gaps: the flag-wins test used a whitespace-free value, so a stray\nTrimSpace(flagVal) regression would pass; and no test used *os.File — the\nactual production reader type (cmd.InOrStdin() -> os.Stdin) — so the non-tty\npiped read was only exercised via strings.Reader. Assert the flag is returned\nuntrimmed, and add an os.Pipe-backed read of the real *os.File reader.",
          "is_bot": false,
          "headline": "test[creds]: assert flag-verbatim contract and cover the *os.File path",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-07-17T15:37:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4103d648056072d31240c8745027ccdbfc4131ec",
          "body": "creds/stdin.go's isInteractive was a byte-for-byte copy of term.IsTerminal and\nre-imported go-isatty — the only such import outside internal/term, reopening\nthe isatty seam that package exists to keep singular. Add term.IsTerminalReader\n(reader-typed companion to IsTerminal, both delegating to one fileIsTerminal),\ncall it from creds, and delete the local copy. go-isatty is again confined to\ninternal/term; the tty predicate is covered by term's os.Pipe tests.",
          "is_bot": false,
          "headline": "refactor[creds]: reuse internal/term for the tty check, drop go-isatty",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-07-17T15:36:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "73baa7e62b25d654dbe4926546ac3d554c113558",
          "body": "The multi-secret helper only read raw lines and pushed the two load-bearing\ninvariants — all-or-nothing (consult stdin only when no field's flag was set)\nand positional line->field mapping — onto every consumer, so the same secret\ncontract was re-derived and re-documented in each caller. ReadSecrets\n[…]\ns and owns both invariants; the line splitter is now\nan unexported readSecretLines. Its sole caller (agent-dd) collapses to one\ncall. Unreleased API, single in-tree consumer, so no compat shim needed.",
          "is_bot": false,
          "headline": "refactor[creds]: replace ReadSecretLines with ReadSecrets(...*string)",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-07-17T15:34:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b14e7f3be24254ace0ce1693d7961a81308ba3fd",
          "body": "…entry\n\nNon-interactive companion to the dialog package's --form path: resolve a\nsecret from a flag or, failing that, piped stdin (trimmed), keeping it off\nargv — where it would land in shell history, ps/proc, and agent transcripts.\nAn interactive tty with no flag returns \"\" rather than blocking on stdin,\nsteering the user to --form. ReadSecretLines covers the rare multi-secret\ncommand (e.g. an API key + application key) via newline-delimited input.",
          "is_bot": false,
          "headline": "feat[creds]: add ReadSecret/ReadSecretLines for flag-or-stdin secret …",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-07-17T14:58:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e76062d0c1bb68c35049c38d20fa3c9aca5feb79",
          "body": "…matAllowed\n\nA persisted default for a flag is flag resolution — the family precedence\nflag > config > built-in belongs at the pre-run boundary, not re-resolved\nper emit inside a CLI's output layer. Passing the command into\nConfigDefaults lets a CLI scope a persisted default to a command class\n(e.g.\n[…]\nike a bad flag instead of silently falling\nback. Doctrine recorded in design-docs/design.md.\n\nBREAKING: Options.ConfigDefaults is now func(cmd *cobra.Command);\nexisting hooks add an ignored parameter.",
          "is_bot": false,
          "headline": "feat[cli]!: ConfigDefaults receives the executing command; export For…",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-07-08T14:11:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2ddff73c9cb6e88f90cec80b8640cbebf860ace3",
          "body": "ConfigCommand hardcoded NDJSON to os.Stdout, silently ignoring the\n--format flag the root command validates, and its ack shapes were\ninconsistent (\"set\" meant is-set in get but key-name in set). Every\nverb now emits the key's {key, value, set} state (list adds\ndescription) through EmitItem/WriteList, so json|yaml render the bare\nobject or the {\"data\":[…]} envelope like the rest of the family.\n\nBREAKING: ConfigCommand now takes *Globals first (nil → NDJSON):\nConfigCommand(g, keys).",
          "is_bot": false,
          "headline": "fix[cli]!: ConfigCommand honors --format and emits one record shape",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-07-07T09:41:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0e4c29f65a4365a7c22d5c8a2c93b30d369eae05",
          "body": null,
          "is_bot": false,
          "headline": "chore[deps]: require lib-agent-keyring v0.1.1",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-29T00:31:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "669a54a57a60b23e67d7a3ca9c8f4a9784a68cb8",
          "body": "The OS keychain backend now lives in the shared github.com/shhac/lib-agent-keyring\nmodule so lib-agent-mcp can use it without depending on the rest of this module.\ncreds keeps the long-standing API via thin aliases (Keychain = keyring.Keyring,\nNewKeychain, ErrKeychainUnavailable, NoKeychain* consts), so existing callers and\nthe NO_KEYCHAIN opt-out env vars are unchanged. go-keyring is now indirect.",
          "is_bot": false,
          "headline": "refactor[creds]: move the keychain backend to lib-agent-keyring",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-29T00:22:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5089a9e443dda29ad15818a914c1ee8a1aadbdf5",
          "body": null,
          "is_bot": false,
          "headline": "chore[deps]: bump lib-agent-output to v0.10.0 (FileRef + path safety)",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-28T12:36:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "760caaa45aaa79c2addfb6895d0eefd71ce2c029",
          "body": null,
          "is_bot": false,
          "headline": "docs[xdg]: document Root constructor for MCP file roots",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-28T12:20:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dc0f37620824c78f61a869df94c3ccc0fb5dc1ca",
          "body": "Root(name, dir) pairs a stable agent-facing name with a host directory,\nproducing the output.FileRoot a CLI hands to lib-agent-mcp's WithFileRoots\nto opt into the read-only fs file tool. Centralizing root construction in\nthe dir-owning package keeps the family's file-access surface defined once.",
          "is_bot": false,
          "headline": "feat[xdg]: add Root constructor for MCP file roots",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-28T11:59:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a3d91ed8118ec8d7853fcd8bc26afd94e1f5c234",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump lib-agent-output to v0.8.0",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-23T00:28:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c20b0fdbc4359b2ed47097a19b20cb130bcbfe34",
          "body": "The keyringStore backend (Secret Service / Credential Manager) ships to non-macOS\nusers but had zero tests — invisible to darwin-only CI. Add build-tagged tests\n(go-keyring mock) for the get/set/delete round-trip, the idempotent\ndelete-absent (ErrNotFound swallowing), deleteAll, and keychainErr wrapping.",
          "is_bot": false,
          "headline": "test[creds]: cover the linux/windows keyring credential backend",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T23:59:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d419dadccdad5ec5199e3c843d1e776a05b668ea",
          "body": "The package exists to stop large IDs rendering as scientific notation, but the\nonly test passed an int literal (hitting the passthrough), so the float64→int64\nconversion, nested recursion, and Inf/NaN guards were never executed. Add an\nencode-level regression test (no e+ for large whole floats) plus a unit test on\nthe conversion itself.",
          "is_bot": false,
          "headline": "test[yaml]: cover normalizeNumbers whole-float→int64 conversion",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T23:57:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "405b6018ef587a0abaddb95c7dc84cdad17acc3c",
          "body": "Drop the hand-rolled first-element empty-check; build the list (split existing,\nappend non-empty new) and Join once, so the store/load round-trip is symmetric.",
          "is_bot": false,
          "headline": "refactor[cli]: simplify AllowFormats store via split/append/join",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T23:55:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "706ce7cd5d0778d04eda8c9a59139d98ccce9d54",
          "body": "Early-return on nil Globals (de-nests the per-line guard the repo style prefers),\nand fold the two byte-identical stream-toggle blocks into bindStreamToggle\n(register hidden off/auto/on flag + completion) and validateToggle (parse +\nagent-fixable error). Adding a third toggle is now one call each, not a copied\nblock.",
          "is_bot": false,
          "headline": "refactor[cli]: dedupe --images/--hyperlinks flag wiring in NewRoot",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T23:55:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5f69049fdcc3cc70f5c75b5ba201149e22026447",
          "body": "…al/term\n\nisTerminal was copied byte-for-byte in cli/color.go, graphics/mode.go, and\nhyperlink/hyperlink.go, and the off/auto/on Mode machinery (ParseMode/String/\nActive) was a near-twin across graphics and hyperlink — three/two copies that\ndrift as siblings are added. Move both into a new internal/\n[…]\neam CLIs; the only\nper-package difference — graphics' auto also requires Detect() — is now the\nexplicit auto predicate. cli/color.go injects term.IsTerminal into\nlib-agent-output. Behavior-preserving.",
          "is_bot": false,
          "headline": "refactor[term]: consolidate isTerminal + off/auto/on Mode into intern…",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T23:53:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3272dfebc6950c27bb77703b973e27961c2ce4ab",
          "body": "A new hyperlink package, sibling of graphics: render clickable OSC 8 terminal\nhyperlinks (label hides the url). Same two-seam shape as graphics — Mode\n(off/auto/on) + Active(w, mode) as the per-stream decision, Encode as the\nmechanism — bound opt-in via libcli Options.Hyperlinks into a hidden --hyperlinks\nflag. Unlike pixel graphics, OSC 8 has no reliable capability probe (it's widely\nsupported and degrades to plain label text), so auto gates on a TTY alone.",
          "is_bot": false,
          "headline": "feat[hyperlink]: OSC 8 terminal hyperlinks via --hyperlinks mode",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T23:42:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "511c0a6303fb1c008ef63eb563d5b2184693dd22",
          "body": "Add graphics.Mode (off/auto/on, mirroring --color) and Active(w, mode) — the\nper-stream image decision a renderer consults, the images counterpart to\noutput.Enabled for color. off never draws, auto draws on a graphics-capable TTY,\non forces past TTY/detection (the escape hatch for a capable terminal\n[…]\nlobal --images\nflag into Globals and validates it up front — same pattern as --expose under\nOptions.Redacts. Image rendering isn't universal, so a tool with nothing to draw\ndoesn't advertise the flag.",
          "is_bot": false,
          "headline": "feat[graphics]: --images mode (off/auto/on) + opt-in libcli binding",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T22:55:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f646af07c57c274ba7e4dda8c19480f3f2492850",
          "body": "A new graphics package for rendering bitmap images inline in terminals that\nspeak the Kitty graphics protocol (Ghostty, kitty, WezTerm). It is the\nhuman-facing counterpart to lib-agent-output's color, living in the runtime\nlayer beside dialog rather than the zero-dep wire contract — an image escape\n\n[…]\n an inline escape sequence clamped to a cell height, with\ntransmit deduplication so a repeated emoji uploads once and re-places by\nreference. Includes a runnable example (graphics/examples/inlineimg).",
          "is_bot": false,
          "headline": "feat[graphics]: inline terminal images via the Kitty graphics protocol",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T22:27:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "725d9bdfa9590245ae4aa6f026f973e10de0d952",
          "body": "…ke format parser\"\n\nThis reverts commit 7d709b08863944340086ec93cdb3e61af2d77bc7.",
          "is_bot": false,
          "headline": "Revert \"feat[cli]: Options.SkipFormatValidation for CLIs with a bespo…",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T10:55:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7d709b08863944340086ec93cdb3e61af2d77bc7",
          "body": "…t parser\n\nNewRoot couples --format binding and validation, which blocked a CLI with its own\nlenient parser / error wording (lin) from routing globals through NewRoot. Add\nSkipFormatValidation: NewRoot still binds --format and resolves --color, but skips\nits ParseFormat rejection, leaving validation to the CLI. Lets such a CLI align\nonto libcli.Globals (and stop hand-registering shared flags) without changing its\ndocumented format-error contract.",
          "is_bot": false,
          "headline": "feat[cli]: Options.SkipFormatValidation for CLIs with a bespoke forma…",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T10:45:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8461a3d59c2fe2d49a9e7a765c090b8ae5be8e0e",
          "body": "Only register the global --expose flag when the CLI declares it redacts output\n(Options.Redacts). A tool that never hides a field no longer advertises a flag\nthat would do nothing; the redacting CLIs set Redacts:true and keep --expose so\nthe @redacted notes' hint stays actionable.",
          "is_bot": false,
          "headline": "feat[cli]: --expose is opt-in via Options.Redacts",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T10:43:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ca262548ae193da83daeba39bc2aae98996ffaf9",
          "body": "The Linux and Windows backends were byte-identical except for available(); hoist\nthe go-keyring get/set/delete/deleteAll into one keyringStore (build-tagged\nlinux||windows) that each platform embeds and wraps with its own availability\ncheck. Behavior unchanged; verified darwin/linux/windows/freebsd build + tests.",
          "is_bot": false,
          "headline": "refactor[creds]: share keyringStore between linux + windows backends",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T10:04:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2ea23bdffa79ed201c5250d39e341e79f318bda5",
          "body": "Reframe the macOS-shaped Keychain behind an unexported backend interface selected\nper-OS by build tag (mirroring the dialog/ package), so a new OS is a new file,\nnot a conditional. macOS is UNCHANGED — keychain_darwin.go keeps the exact\nsecurity-CLI logic (raw values), so existing keychain items sta\n[…]\nper logic (availability/opt-out/delegation) is now tested\nvia an in-memory fakeBackend on EVERY platform, closing the credential-path CI\ncoverage gap. Builds verified for darwin/linux/windows/freebsd.",
          "is_bot": false,
          "headline": "feat[creds]: cross-platform keychain via a per-OS backend seam",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T10:02:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "85ae4e6a295ea7845627ec5e1bae2ba6f075f304",
          "body": "Add Globals.Expose + a persistent --expose flag (repeatable; 'all'). A CLI that\nredacts output passes it straight to output.Redactor; making it family-wide keeps\nthe @redacted notes' '--expose <path>' hint actionable everywhere.",
          "is_bot": false,
          "headline": "feat[cli]: global --expose flag for revealing redacted fields",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T09:21:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "63d857faa647c69a87f4c6b0ce1b48be0760bbef",
          "body": "Add tests for the credential file-store failure branches (malformed JSON load,\ndirectory-path read error, MkdirAll-blocked and unmarshalable saves) — the active\nbackend whenever the keychain is opted out — and pin every arm of\nclassifyResolveErr (the get-batch per-item-miss vs command-abort router).\nclassifyResolveErr 88.9%->100%, Save->100%.",
          "is_bot": false,
          "headline": "test: cover file-store failure modes + resolve-error classifier",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T00:17:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3f8573c0982386392f3ce972761de5e0409fcf2c",
          "body": "Extract a lookup() closure for the unknown-key guard repeated across get/set/unset,\nand a ConfigKey.value() method for the nil-safe Get read repeated in get/list. No\npublic API or behavior change.",
          "is_bot": false,
          "headline": "refactor[cli]: dedup config key lookup + nil-Get read",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-22T00:16:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "79f4c55bb240ff46b04a8d480b2f85965db87c57",
          "body": "ParseColorMode returns the safe ColorAuto default on a bad value; set it\nunconditionally before returning the agent-fixable error, so an invalid --color\nnever leaves a previously-set process-global mode in force (which surfaced as a\ncolored error envelope in in-process test suites).",
          "is_bot": false,
          "headline": "fix: --color always sets a mode, even on invalid input",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-21T23:26:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "24b0c95518fe2d606d31bd307acc8574bdecac7f",
          "body": "NewRoot now binds a persistent --color flag (default auto) and resolves it in\nPersistentPreRunE into lib-agent-output's color mode, so every CLI built on this\npackage gets colored JSON/NDJSON + error envelopes for free on a bump, with no\ncall-site changes. An unknown value is fixable_by:agent, like \n[…]\ne; the dep lives here, mirroring the YAML\nRegisterEncoder injection). Detection is per-stream, so a piped stdout stays clean\nwhile a terminal stderr is still colored. Bumps lib-agent-output to v0.5.0.",
          "is_bot": false,
          "headline": "feat: global --color auto|always|never flag",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-21T23:18:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a85a0fcf2b36a94f744d3b8927064a6b6f36e154",
          "body": "Add an 'env' package: a Namespace whose Lookup/Flag resolve {PREFIX}_{KEY}\nfirst, then the family-wide LIB_AGENT_{KEY}. This is the single funnel for\nevery env read in the lib; specific-overrides-general semantics (a per-CLI\nvar wins on presence, so it can even re-enable a behaviour the family var\nd\n[…]\nN as the\nfamily-wide fallback -- no changes needed in any consuming CLI. Add\nNewKeychainWithEnvPrefix for explicit control.\n\nAdditive over v0.7.0's LIB_AGENT_NO_KEYCHAIN (now the documented fallback).",
          "is_bot": false,
          "headline": "feat[lib-agent-cli]: env namespace + per-CLI keychain opt-out",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-21T20:32:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "55d11f5491a5adc97f67e7769a13421a3fd39fc9",
          "body": "…sting)\n\nKeychain.Available() now returns false when LIB_AGENT_NO_KEYCHAIN is set\n(truthy), so callers fall back to the 0600 file store and the macOS security\nCLI — with its GUI authorization prompt — is never invoked. Makes the\ncredential-write path (auth add / project add) testable in CI and headless\nruns, and prevents the prompt-flood that real-binary smoketests hit.",
          "is_bot": false,
          "headline": "feat[creds]: LIB_AGENT_NO_KEYCHAIN opt-out (headless/CI credential te…",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-21T20:01:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a9df8bc2b279830daa4984674291be5b9da299df",
          "body": "NewRoot's --format validator is now command-aware: a command (or group) can\nAllowFormats(cmd, \"transcript\", …) to accept extra format values it renders\nitself, beyond the universal json|yaml|jsonl set. Opted-in values are accepted\non those commands and rejected elsewhere with a structured fixable_by\n[…]\nror that lists the universal set plus the command's extras. Keeps domain\ndisplay formats (e.g. a conversation transcript) out of lib-agent-output's\nuniversal enum while still flowing through --format.",
          "is_bot": false,
          "headline": "feat[cli]: AllowFormats — per-command opt-in extra --format values",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-21T12:21:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb62030526a1be5bb365634b10b6d32194cf37cf",
          "body": "For gets that don't fit EntityGet's 1..N id model (composite-key, singleton,\nmulti-field) but should still default to NDJSON like every other get. One\ncompact NDJSON line by default; the bare object (not a {data:[…]} envelope)\nunder --format json|yaml, since there is exactly one record. Not for raw\npassthrough/content responses.",
          "is_bot": false,
          "headline": "feat[cli]: EmitItem — NDJSON-default render for single-only gets",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-21T11:40:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "88a523c8c1ae3497a23ab92231fcdeb30e6a6f36",
          "body": "Adds EntityGet(w, format, args, resolve): the family's canonical get\nbehavior in one place. 1..N ids resolved in input order; default NDJSON\nemits one line per input (record or {\"@unresolved\":{...}} control line in\nposition); --format json|yaml collapse to a {data:[...],@unresolved:[...]}\nenvelope. \n[…]\n network) bubble to the sink (stderr,\nexit 1) with stdout left empty (buffer-then-write). Classification keys off\n*output.Error.FixableBy. Bumps lib-agent-output pin 0.3.0 -> 0.4.3 to match\nconsumers.",
          "is_bot": false,
          "headline": "feat[cli]: EntityGet — single+multi get contract helper",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-20T23:44:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "589b6039eb79c65ab0df064701cb758694fdf526",
          "body": null,
          "is_bot": false,
          "headline": "ci: uniform build+vet+test+lint workflow (golangci-lint v2.12.1)",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-20T10:32:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2511c9fb0f08492ddc4dae5cdb8f372103214062",
          "body": null,
          "is_bot": false,
          "headline": "docs: add GETTING_STARTED.md from-scratch tutorial",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-20T09:37:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fca0a31472d3e4f50cf796a5a3df92f648d2c324",
          "body": "…for IDs)\n\nJSON decoding yields float64 for every number; yaml.v3 renders large whole\nfloats in scientific notation (1.5e+06), wrong for IDs/counts. Normalize whole\nfloat64s to int64 before encoding — matching the agent-* CLIs that already did\nthis locally, and fixing the ones that didn't.",
          "is_bot": false,
          "headline": "fix(yaml): normalize whole floats to ints (avoid scientific notation …",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-20T09:23:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4771d13bb3323bd2d27306322b60c9a0a7b71af0",
          "body": "…YAML\n\nThe ~10-line yaml.v3 RegisterEncoder block was copy-pasted into ~9 agent-* CLIs.\nMove it here (lib-agent-cli already has deps, so the zero-dep lib-agent-output\nstays dep-free): a CLI gets --format yaml by blank-importing\ngithub.com/shhac/lib-agent-cli/yaml instead of re-vendoring the block.",
          "is_bot": false,
          "headline": "feat(yaml): opt-in YAML encoder package for lib-agent-output's Format…",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-20T09:21:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cdebaa4ddea167427a557cd560883bf5ce29619b",
          "body": null,
          "is_bot": false,
          "headline": "chore: add family .golangci.yml (consistent lint config)",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-20T09:16:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bb9791bff912319bb21ad2766a39dcfec009a590",
          "body": "Replace the simpler dialog with sql's superior design: a swappable Prompter\ninterface (+ Default/SetDefault + dialogtest.Recorder), an InputType enum\n(Text/Password), build-tagged per-platform tested Available, and a NEUTRAL\nCategory + ClassifyError taxonomy so the package no longer imports\nlib-agen\n[…]\nrompt/Available remain as package-level conveniences.\n\nBREAKING: Field.Hidden -> InputType; Spec.Fields -> Spec.Items; Available/Prompt\nno longer return output.Error (use ClassifyError). Docs updated.",
          "is_bot": false,
          "headline": "feat(dialog)!: adopt agent-sql's Prompter design (BREAKING)",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-20T00:00:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4aeae7dacb1c0d8084386376f5aa00a00098a427",
          "body": null,
          "is_bot": false,
          "headline": "chore: relicense under PolyForm Perimeter 1.0.0",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-19T23:49:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "547d34cd9b5d5f7459921f2f5289412237f58e06",
          "body": "Co-locate the account-less 'clear every entry for this service' sweep (used to\npurge orphans not tracked in a CLI's index) in the lib, so callers no longer\nkeep their own security-CLI loop. macOS only; ErrKeychainUnavailable elsewhere.",
          "is_bot": false,
          "headline": "feat(creds): Keychain.DeleteAll removes all secrets for the service",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-19T23:18:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7d2294aed398718f948f2507186f05845afa359a",
          "body": "Keychain mutations used exec Output(), discarding the security CLI's stderr\nwhere its actual diagnostic lives, and returned the bare error. Switch to\nCombinedOutput and wrap Set/Delete failures with the operation, account,\nservice, and the captured diagnostic — so an adopting CLI gets error messages\nat least as useful as the hand-rolled wrappers it replaces. Get is unchanged\n(found/not-found).",
          "is_bot": false,
          "headline": "feat(creds): keychain errors include the security diagnostic + context",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-19T23:08:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3eefd197c09304343abcb685b50cf0b96d98a682",
          "body": "PromptSecret/Prompt could not seed an existing value into the native dialog,\nso a CLI that lets the user edit a stored token (rather than retype it) could\nnot delegate to lib-agent-cli/dialog. Add an optional Field.Initial wired to\nzenity.EntryText; empty keeps the prior behaviour.",
          "is_bot": false,
          "headline": "feat(dialog): Field.Initial pre-fills the prompt entry",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-19T18:07:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0ba0c0289c23afed06d561ecb6672ff3b0e26e8b",
          "body": "…ck to temp\n\nXDG base-directory resolution is a filesystem concern, not a credential one,\nso move ConfigDir/CacheDir/DataDir/StateDir/RuntimeDir (+ the App bundle) out\nof creds into a new xdg package. RuntimeDir now degrades to a per-app temp\nsubdir when XDG_RUNTIME_DIR is unset, matching the reason\n[…]\nle-fallback\nbehaviour the CLIs already rely on rather than returning empty.\n\ncreds keeps only the secret plumbing: Store, Keychain, and the value\nresolvers. Docs and the demo updated to the new split.",
          "is_bot": false,
          "headline": "refactor: split filesystem dirs into xdg package, RuntimeDir falls ba…",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-19T17:19:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ec0bcae577c629512ecd072fe9627733dccf578f",
          "body": "From the agent-vercel migration + Paul's request: contain all XDG base-directory\nresolution (with the spec's fallbacks) in the lib, so a CLI provides its identity\nonce and gets every path back.\n\n- creds.DataDir / StateDir / RuntimeDir join the existing ConfigDir / CacheDir\n  (XDG_DATA_HOME, XDG_STAT\n[…]\nRUNTIME_DIR; RuntimeDir errors when unset,\n  per the spec — no portable fallback).\n- creds.App{Name, KeychainService} bundles them: app.ConfigDir(), app.CacheDir(),\n  …, app.Keychain() from one value.",
          "is_bot": false,
          "headline": "feat: full freedesktop XDG base dirs + App bundle",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-19T17:10:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2199e91f373174e962f77817cb7a68de61dd0c89",
          "body": "… demo\n\nFrom the 14-repo infra sweep — the copied, domain-free CLI scaffolding that\nclears the rule-of-three bar:\n\n- cli.ConfigCommand(keys): get/set/unset/list over a KeyDef-style closure\n  registry (~8 tools hand-roll this); keys are the CLI's domain, the command\n  and dispatch are shared. Unknown\n[…]\n:\nusage-command builder and pagination flag helpers. Rejected with reasons in the\nsweep: HTTP-client do() loop, retry/backoff, api escape-hatch, time parsing,\n--debug logging, mock servers, audit log.",
          "is_bot": false,
          "headline": "feat: ConfigCommand, --yes gate, CacheDir, FirstNonZero; kitchen-sink…",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-19T14:20:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "07cfa813eef7c9d93783c4b46c6bd045692aa838",
          "body": "…ent-cli\n\nCompanion to lib-agent-output's guide: covers creds (XDG dir, 0600 store,\nkeychain, resolution), the cli root builder, and the dialog/--form swap, with a\nsymbol map, the four gotchas (keychain placeholder, 0600 perms, pre-run hook,\nheadless dialog), and verify/cleanup steps.",
          "is_bot": false,
          "headline": "docs: add MIGRATION_HELP.md for migrating a CLI's runtime onto lib-ag…",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-19T13:30:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f974673e77609e17dcf5079863b9f1ec88c59d8e",
          "body": "The --form pattern (native OS dialog so a token never transits argv) is copied\nacross slack/posthog/cloudflare. Bring it in, taking cloudflare's multi-field\nsuperset rather than deferring on convergence:\n\n- dialog.Prompt(ctx, Spec) for multi-field forms (e.g. xoxc + xoxd), with a\n  single-secret Pro\n[…]\nests never open a window.\n- examples/demo gains 'login --form'.\n\nzenity dep is in-character for the runtime lib (already carries cobra); a\ncreds-only consumer never compiles it. Docs + design updated.",
          "is_bot": false,
          "headline": "feat: add dialog package — the --form secret-prompt boilerplate",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-19T12:35:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "10ab123051fb5e9bfe12654911899792ae0ce14d",
          "body": "The CLI runtime shared by agent-first tools, above the lib-agent-output wire\ncontract. Survey showed this layer is more copied than output: byte-identical\nXDG resolver, identical macOS keychain invocation, ~95% identical cobra root.\n\n- creds: ConfigDir (XDG), Store (0600 JSON), Keychain (macOS secur\n[…]\n (token formats, env names, parse-curl, retry, truncation)\nstays in the CLI. dialog (secret prompt) and redact deferred — see design-docs.\n\nLicensed PolyForm Noncommercial 1.0.0, (c) 2026 Paul Somers.",
          "is_bot": false,
          "headline": "feat: initial lib-agent-cli — shared CLI runtime (creds + cli)",
          "author_name": "Paul Somers",
          "author_login": "shhac",
          "committed_at": "2026-06-18T22:00:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        }
      ],
      "releases_count": 26,
      "commits_last_year": 51,
      "latest_release_at": "2026-07-17T15:37:28Z",
      "latest_release_tag": "v0.21.0",
      "releases_from_tags": true,
      "days_since_last_push": 4,
      "active_weeks_last_year": 5,
      "days_since_latest_release": 4,
      "mean_days_between_releases": 2.8
    },
    "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/shhac/lib-agent-cli",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/shhac/lib-agent-cli",
          "is_deprecated": false,
          "latest_version": "v0.21.0",
          "repository_url": "https://github.com/shhac/lib-agent-cli",
          "versions_count": 26,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-17T15:37:28Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 4
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 9183,
      "source_files_sampled": 59,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 3304
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/mattn/go-isatty",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.22"
        },
        {
          "name": "github.com/ncruces/zenity",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.10.14"
        },
        {
          "name": "github.com/shhac/lib-agent-output",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.10.0"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        },
        {
          "name": "github.com/shhac/lib-agent-keyring",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.1.1"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 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": "shhac",
          "commits": 51,
          "avatar_url": "https://avatars.githubusercontent.com/u/2800184?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [
        ".golangci.yml"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 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": 0,
            "reason": "project is not 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": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 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": null,
            "reason": "no releases found",
            "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": 1,
            "reason": "9 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "7c67bc6351abed679124f4805a9fa210e2c0eec4",
        "ran_at": "2026-07-22T03:25:45Z",
        "aggregate_score": 2.3,
        "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-17T15:40:25Z",
      "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/shhac/lib-agent-cli",
    "host": "github.com",
    "name": "lib-agent-cli",
    "owner": "shhac"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 45,
      "inputs": {
        "security": 23,
        "vitality": 68,
        "community": 21,
        "governance": 36,
        "engineering": 68
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "moderate",
        "name": "Vitality",
        "value": 68,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "commits_last_year": 51,
              "human_commit_share": 1,
              "days_since_last_push": 4,
              "active_weeks_last_year": 5
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 4 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "5/52 weeks with commits",
                "points": 3.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "51 commits in the last year",
                "points": 15.4,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 51
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 88,
            "inputs": {
              "releases_count": 26,
              "latest_release_tag": "v0.21.0",
              "releases_from_tags": true,
              "days_since_latest_release": 4,
              "mean_days_between_releases": 2.8
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "26 version tags (no GitHub releases)",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "version_tags_no_releases",
                    "params": {
                      "count": 26
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 4 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~2.8 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 2.8
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "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": 36,
        "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": 53,
            "inputs": {
              "followers": 10,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "shhac",
              "public_repos": 63,
              "account_age_days": 4997
            },
            "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": "10 followers of shhac",
                "points": 7.5,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 10,
                      "login": "shhac"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "63 public repos, account ~13 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 63
                    }
                  },
                  {
                    "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/shhac/lib-agent-cli"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 4
            },
            "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 4 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "26 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 26
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 68,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "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": 80,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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": ".golangci.yml",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".golangci.yml"
                    }
                  }
                ],
                "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": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "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": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "critical",
        "name": "Security",
        "value": 23,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "critical",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 23,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 15,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 3,
              "scorecard_aggregate": 2.3
            },
            "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 not fuzzed",
                "points": 0,
                "status": "missed",
                "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": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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": "9 existing vulnerabilities detected",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 73,
        "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.941,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 3304
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "48 of 51 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 48,
                      "sampled": 51
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 67,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "go.mod (toolchain convention, no task runner)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "toolchain_convention",
                    "params": {
                      "files": "go.mod"
                    }
                  }
                ],
                "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": ".golangci.yml",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".golangci.yml"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 51",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 51
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 9183,
              "source_files_sampled": 59,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/59 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 59,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "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": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-22T03:25:48.985385Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/s/shhac/lib-agent-cli.svg",
  "full_name": "shhac/lib-agent-cli",
  "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.26.0 — metodología completa · wiki de métricas.

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