Registro público
Informe de salud del softwareesquema 0.23.0 · métricas 1.13.0 · 2026-07-21 18:26 UTC

TestSprite / testsprite-cli

Official TestSprite CLI — AI-powered automated testing from your terminal

TypeScriptApache-2.0★ 2415 estrellas⑂ 98 forksdesde jun 2026Ver en GitHub ↗

TestSprite/testsprite-cli tiene un índice de salud de 76 sobre 100, lo que lo sitúa en la banda Bueno. Su puntuación más alta es Engineering Quality (90/100) y la más baja, Security (63/100). Se actualizó por última vez hace 1 día. 5 personas concentran la mayor parte del trabajo reciente.

76
global / 100
Bueno

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

76
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

TestSpriteOrganización
71 seguidores4 repositorios públicosdesde may 2024

Este repositorio está respaldado por una organización: una custodia compartida y responsable que puede sobrevivir a cualquier mantenedor individual.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicaciónEtiquetas
npm@testsprite/testsprite-cli0.4.033746hace 4 díastestspriteclitestingautomation

Métricas por categoría

Vitalidad

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

75Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 1 días
4.2/36Cadencia de commits — 6/52 semanas con commits
17.8/18Volumen de commits — 96 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_year96
human_commit_share0,99
days_since_last_push1
active_weeks_last_year6
Cómo se puntúa
27/27Publica versiones — 5 versiones publicadas
36/36Recencia de las versiones — última versión hace 4 días
27/27Cadencia de publicación — una versión cada ~8,8 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count5
latest_release_tagv0.4.0
releases_from_tagsno
days_since_latest_release4
mean_days_between_releases8,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?

76Bueno · 18% del índice global
Cómo se puntúa
54.9/60Estrellas — 2415 estrellas
16.6/25Forks — 98 forks
1.7/15Observadores — 3 observadores
Datos de entrada utilizados
forks98
stars2415
watchers3
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonwindow_too_short
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (Apache-2.0)
18/18Guía CONTRIBUTING
13.5/13.5Código de conducta
0/7.2Plantilla de issues
6.3/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributing
has_issue_templateno
has_code_of_conduct
has_pull_request_template
Cómo se puntúa
47/80Descargas mensuales — 3374 descargas/mes en npm
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packages@testsprite/testsprite-cli
dependents
ecosystemsnpm
total_downloads
monthly_downloads3374
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

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

75Bueno · 24% del índice global
Cómo se puntúa
45.9/54Factor bus — la mitad de los commits recae en 5 contribuyente(s)
19.7/22.5Distribución de commits — el principal contribuyente firma el 13% de los commits
13.5/13.5Amplitud de contribuyentes — 22 contribuyentes
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Datos de entrada utilizados
bus_factor5
contributors_sampled22
top_contributor_share0,126
Cómo se puntúa
32.8/46.8Resolución de issues — 70% de issues cerradas
21.1/38.3Aceptación de PR — 85/154 PR decididos fusionados
13.5/15OpenSSF Scorecard: Code-Review — Found 26/27 approved changesets -- score normalized to 9
Datos de entrada utilizados
merged_prs85
open_issues29
closed_issues68
issue_closed_ratio0,701
closed_unmerged_prs69
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
13.4/25Alcance del propietario — 71 seguidores de TestSprite
9.4/25Trayectoria — 4 repos públicos, cuenta de ~2 años
Datos de entrada utilizados
followers71
owner_typeOrganization
is_verified
owner_loginTestSprite
public_repos4
account_age_days784
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en npm
35/35Recencia de publicación — última publicación hace 4 días
20/20Historial de versiones — 6 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packages@testsprite/testsprite-cli
ecosystemsnpm
any_deprecatedno
min_days_since_publish4

Calidad de Ingeniería

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

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

Documentación

100Excelente
Cómo se puntúa
30/30README
25/25Directorio de documentación
15/15Sitio de documentación / página del proyecto — https://www.testsprite.com
10/10Descripción del repositorio
10/10Topics — 7 topics
10/10Wiki
Datos de entrada utilizados
topicsai, cli, e2e-testing, playwright, qa, test-automation, testing
has_wiki
homepagehttps://www.testsprite.com
has_readme
has_docs_dir
has_description

Seguridad

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

63Moderado · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
3.8/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 28 out of 28 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
6.8/7.5Code-Review — Found 26/27 approved changesets -- score normalized to 9
0.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/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
4.5/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 9
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — sin datos
6.8/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_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate6,3
Excluidos de la puntuación (sin datos o no aplicable): 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.

69Moderado · 0% del índice global
Cómo se puntúa
0/45Instrucciones para agentes — sin CLAUDE.md / AGENTS.md / reglas de editor
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 94 de 95 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,989
agent_instruction_files
agent_instruction_max_bytes
Cómo se puntúa
0/18Arranque con un solo comando
22/22Pruebas automatizadas
11/11Configuración de lint / formato — eslint.config.mjs
11/11Verificación estática de tipos — tsconfig.json
10/10Entorno reproducible — lockfile
10/10Práctica demostrada con agentes — 9 de los últimos 96 commits con autoría o crédito de agente
8/8Mantenimiento automatizado — 1 de los últimos 96 commits son actualizaciones automáticas de dependencias
9/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 9
Datos de entrada utilizados
has_nixno
has_tests
lockfilespackage-lock.json
has_dockerfileno
typed_language
bootstrap_files
has_devcontainerno
has_linter_config
typecheck_configstsconfig.json
agent_commit_share0,094
toolchain_manifests
dependency_bot_commit_share0,01
Cómo se puntúa
45/45Código verificable por tipos — TypeScript (tipado estático)
52.1/55Tamaños de archivo manejables — 6/115 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageTypeScript
largest_source_bytes441.972
source_files_sampled115
oversized_source_files6

Datos clave

2415estrellas de GitHub
22contribuidores
96commits en los últimos 12 meses
1días desde el último push
5versiones publicadas
5factor bus
29issues abiertas
npmecosistemas de paquetes

Advertencias de recopilación de datos

  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository
  • deps.dev does not index npm:@testsprite/testsprite-cli@0.4.0; advisories assessed against the repository dependency graph instead

Más detalle

Historial de estrellas y forks 2415 ★ / 98 ⇿
2415Estrellas
98Forks
5Versiones

Cuándo se añadió cada estrella y fork, recopilado de GitHub y agrupado por día. El crecimiento acumulado se sitúa justo encima de las adiciones diarias que lo componen, de modo que ambos se leen en conjunto: la acumulación orgánica sostenida no se parece en nada a un pico abrupto y efímero. Cuando esa diferencia es medible, se informa como autenticidad del crecimiento.

Solo se muestra el historial más reciente: este repositorio supera la ventana de recopilación, por lo que no se captura el historial más antiguo.

050010001500200025002415981772026-062026-072026-07
Mayor 0Menor 3Parche 2
OpenSSF Scorecard 6.3 / 10
6.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-21 18:26 UTC

10Binary-Artifactsno binaries found in the repo
5Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests28 out of 28 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
9Code-ReviewFound 26/27 approved changesets -- score normalized to 9
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
n/dPackagingpackaging workflow not detected
9Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 9
0SASTSAST tool is not run on all commits -- score normalized to 0
10Security-Policysecurity policy file detected
n/dSigned-Releasesno releases found
9Token-Permissionsdetected GitHub workflow tokens with excessive permissions
1Vulnerabilities9 existing vulnerabilities detected
Dependencias directas 3
RegistroPaqueteRestricción de versiónManifiesto
npmcommander^12.1.0package.json
npmundici^7.16.0package.json
npmvalibot^1.4.1package.json
Todas las dependencias no recopilado

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

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [
        "ai",
        "cli",
        "e2e-testing",
        "playwright",
        "qa",
        "test-automation",
        "testing"
      ],
      "is_fork": false,
      "size_kb": 1097,
      "has_wiki": true,
      "homepage": "https://www.testsprite.com",
      "languages": {
        "JavaScript": 17913,
        "TypeScript": 2624471
      },
      "pushed_at": "2026-07-20T05:56:13Z",
      "created_at": "2026-06-11T10:44:15Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-21T18:05:28Z",
      "description": "Official TestSprite CLI — AI-powered automated testing from your terminal",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript"
      ]
    },
    "owner": {
      "blog": "https://www.testsprite.com/",
      "name": "TestSprite",
      "type": "Organization",
      "login": "TestSprite",
      "company": null,
      "location": "United States of America",
      "followers": 71,
      "avatar_url": "https://avatars.githubusercontent.com/u/170984515?v=4",
      "created_at": "2024-05-27T22:17:51Z",
      "is_verified": null,
      "public_repos": 4,
      "account_age_days": 784
    },
    "license": {
      "state": "standard",
      "spdx_id": "Apache-2.0",
      "raw_spdx": "Apache-2.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-07-17T02:41:43Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-07-09T23:21:09Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-07-09T00:57:20Z"
        },
        {
          "tag": "v0.1.2",
          "kind": "patch",
          "published_at": "2026-06-20T03:56:02Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-06-12T02:18:03Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "2708a4069fba72822f94906d05001b4d19e66d9c",
          "body": "Add --skip-if-configured to testsprite setup (and the deprecated init\nalias). When the active profile already has a saved API key and no\nexplicit key source (--api-key or --from-env) is given, the interactive\nprompt is skipped and the existing key is reused.\n\nMotivation: re-running setup to refresh \n[…]\nxt + JSON)\n- proceeds to prompt when no credentials exist\n- allows isTTY=false CI runs when skip applies\n- --api-key overwrites despite skip flag\n- --from-env overwrites despite skip flag\n\nCloses #206",
          "is_bot": false,
          "headline": "fix(init): skip API key prompt when credentials already exist (#234)",
          "author_name": "Tasfia Chowdhury",
          "author_login": "Tasfia-17",
          "committed_at": "2026-07-18T00:04:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5fe0b0012c7a16209caaeee2bb0771ea0da4d39c",
          "body": "…#233)",
          "is_bot": false,
          "headline": "fix(config): normalize empty/whitespace TESTSPRITE_PROFILE to unset (…",
          "author_name": "Shalahuddin Al-Ayyubi",
          "author_login": "0xshalah",
          "committed_at": "2026-07-18T00:03:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "326fa97aae538a3069395f7aa06e51a0e5d6df3c",
          "body": "Co-authored-by: Lexiie <28455136+Lexiie@users.noreply.github.com>",
          "is_bot": false,
          "headline": "test(test): guard status filter validation order (#222)",
          "author_name": "Lex",
          "author_login": "Lexiie",
          "committed_at": "2026-07-18T00:02:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9d4af09af285ad9863c9c1bc9106d968d3d1bf05",
          "body": "* feat(cli): add text list column controls\n\n* fix(cli): address list column review feedback",
          "is_bot": false,
          "headline": "feat(cli): add text list column controls (#165) (#252)",
          "author_name": "nopp",
          "author_login": "naufalfx805-source",
          "committed_at": "2026-07-18T00:01:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8db1882964b93db3dcd9b7de526cc7d179cd6619",
          "body": "…e dashboard (#226)\n\n* feat(test): add \"test open <test-id>\" to jump from the terminal to the dashboard\n\n* fix(open): derive the dry-run URL via resolvePortalUrl and handle async spawn ENOENT\n\n* fix(browser): map non-http(s) URL rejection to exit 5 (validation error)\n\nopenInBrowser threw a plain Err\n[…]\nthrough localValidationError so it is classified as VALIDATION_ERROR and maps to the documented exit code 5, matching every other bad-argument path. Test asserts the exit code, not the message string.",
          "is_bot": false,
          "headline": "feat(test): add \"test open <test-id>\" to jump from the terminal to th…",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-18T00:00:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eaf0585dd29b960161fe3d160adb23ce0e6040ad",
          "body": null,
          "is_bot": false,
          "headline": "fix(flaky): propagate auth trigger errors (#217)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-18T00:00:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "45dcd0895f10b406646333e537c658f2b3cd0b41",
          "body": null,
          "is_bot": false,
          "headline": "fix(agent): update verify skill auth commands (#216)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-17T23:54:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "759a1c7df81b926c70ab125b16754460e47055dd",
          "body": "Emit a shell completion script for bash, zsh, or fish. Command names,\nsubcommands, and global flags are derived from the fully-assembled Commander\ntree at call time (buildCompletionSpec walks program.commands), so the script\ncan never drift from the real command surface. The shell auto-detects from\n$SHELL when the argument is omitted.\n\nFixes #74",
          "is_bot": false,
          "headline": "feat(cli): add \"testsprite completion\" for bash/zsh/fish (#227)",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-17T23:54:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "34f5d430797437ab2f67910fe356c3732ea0be57",
          "body": null,
          "is_bot": false,
          "headline": "fix(http): avoid retrying keyless writes (#256)",
          "author_name": "nopp",
          "author_login": "naufalfx805-source",
          "committed_at": "2026-07-17T23:54:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "94f78ad88b427bcdf87079705ae3723019cd67d5",
          "body": "* fix(auth): tighten Windows credentials ACL\n\n* docs(auth): document credential permission tightening",
          "is_bot": false,
          "headline": "fix(auth): tighten Windows credentials ACL (#104) (#253)",
          "author_name": "nopp",
          "author_login": "naufalfx805-source",
          "committed_at": "2026-07-17T23:53:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "36e5b14fd1e2983bdacadd895313e0ef5881b9cd",
          "body": "Co-authored-by: Lexiie <28455136+Lexiie@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(init): debug log whoami fallback (#223)",
          "author_name": "Lex",
          "author_login": "Lexiie",
          "committed_at": "2026-07-17T23:53:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3c3a2e05b976abc7f4e5f823a55a78c9cf16ad25",
          "body": "… @SahilRakhaiya05) (#246)\n\n* fix(bundle): atomic re-commit via per-entry aside with rollback\n\n* fix(bundle): move meta.json aside before other bundle entries during commit\n\n---------\n\nCo-authored-by: SahilRakhaiya05 <sahil.rakhaiya117814@marwadiuniversity.ac.in>",
          "is_bot": false,
          "headline": "Recovered: fix(bundle): atomic re-commit via per-entry aside (#196 by…",
          "author_name": "Joseph Jang",
          "author_login": "jangjos-128",
          "committed_at": "2026-07-17T23:53:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3abcf2d501533caa2e803b922825ab0d5239caa4",
          "body": "Co-authored-by: Yazan-O <mohamad.yazan@ou.edu>",
          "is_bot": false,
          "headline": "fix(doctor): validate output mode (#251)",
          "author_name": "Joseph Jang",
          "author_login": "jangjos-128",
          "committed_at": "2026-07-17T23:52:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d2f0357ec1f9f08419768a40bd89beead8bc7cb3",
          "body": "…te check (#260)\n\nGitHub's runner infra force-upgrades actions/github-script@v7 to Node 24,\nwhere the script-side require('@actions/github') can no longer resolve.\nEvery recent PR shows a red 'gate' check with 'Cannot find module\n@actions/github' regardless of whether it links an issue.\n\n- Pin actio\n[…]\nn #257 — thank you! This lands\nseparately with a SHA pin and a require-free client construction.\n\nCo-authored-by: Zeshi Du <duke.zeshi@gmail.com>\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ci): migrate github-script to v8 — repair the repo-wide broken ga…",
          "author_name": "zeshi-du",
          "author_login": "zeshi-du",
          "committed_at": "2026-07-17T23:44:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7b4937bd903fcd201b30a7e7ee4dc8f3af4d871c",
          "body": "release: v0.4.0",
          "is_bot": false,
          "headline": "Merge pull request #259 from TestSprite/release/v0.4.0",
          "author_name": "Fangyuan Zhang",
          "author_login": "fyZhang66",
          "committed_at": "2026-07-17T00:43:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e91c5a107867f16ca183b11684c84d953d972cbf",
          "body": "Private-Snapshot-RevId: afa3bf501545df536cfa638a86ae096fb7c34880",
          "is_bot": false,
          "headline": "release: v0.4.0",
          "author_name": "zeshi-du",
          "author_login": "zeshi-du",
          "committed_at": "2026-07-16T21:56:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "60d55e47883e924ff1a5f0ab1fe67a25bc3b0877",
          "body": "release: v0.3.0",
          "is_bot": false,
          "headline": "Merge pull request #230 from TestSprite/release/v0.3.0",
          "author_name": "Joseph Jang",
          "author_login": "jangjos-128",
          "committed_at": "2026-07-09T23:02:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3d65ff5a0e25399a7b87e8c75b6f8eb90f0ef2f8",
          "body": "Private-Snapshot-RevId: d22d9f18f5d9712921097d5829c28d056e3ffd31",
          "is_bot": false,
          "headline": "release: v0.3.0",
          "author_name": "zeshi-du",
          "author_login": "zeshi-du",
          "committed_at": "2026-07-09T22:29:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3305dfa57ab258b11311d15197a80dd9eb654911",
          "body": "… or backend skeleton (#180)",
          "is_bot": false,
          "headline": "feat(test): add \"test scaffold\" to emit a schema-correct starter plan…",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-06T20:14:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "946f5b326453b55aaeac97dffb5bac2aa844901f",
          "body": "* feat(cli): graceful termination signals + broken-pipe guard\n\nInstall handlers for SIGINT/SIGTERM/SIGHUP that print a one-line explanation\n(any started run keeps executing server-side; resume with `testsprite test list`\nor `testsprite test wait <runId>`) and exit with the conventional 128+signum\nco\n[…]\ndefault stderr\nwriter now uses fs.writeSync (best-effort, guarded against EPIPE) so the hint is\nreliably emitted. Added a test mocking fs.writeSync to assert the synchronous\nwrite on the default path.",
          "is_bot": false,
          "headline": "feat(cli): graceful termination signals + broken-pipe guard (#185)",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-06T20:13:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "edc31c8e0e82599a9b95d15ba761eede61683517",
          "body": "* feat(cli): add \"testsprite doctor\" environment diagnostic\n\nOne-shot preflight: checks CLI version, Node runtime, profile, API endpoint,\ncredentials, live connectivity (GET /me), and verify-skill install. Prints an\nOK/WARN/FAIL report and exits non-zero when any check fails, so it gates a CI\nstep o\n[…]\ned input instead of\n  silently defaulting, matching the other commands.\n- The --output json test asserts the API key never appears in the JSON path\n  (distinct from the text renderer already covered).",
          "is_bot": false,
          "headline": "feat(cli): add \"testsprite doctor\" environment diagnostic (#183)",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-06T20:13:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e819e4543e5993f7548965b15cd9a03c1ee87b95",
          "body": "* feat(agent): add GitHub Copilot as an install target\n\nAdds `copilot` to the agent-install targets. GitHub Copilot reads\npath-specific custom instructions from `.github/instructions/*.instructions.md`\n(VS Code / Visual Studio / Copilot Chat), with YAML frontmatter carrying an\n`applyTo` glob. The sk\n[…]\ner targets but\nomitted Kiro (a pre-existing gap), leaving it inconsistent with the\n`--target` help text and the docs. Align the description with the\n`--target` list so every supported target is named.",
          "is_bot": false,
          "headline": "feat(agent): add GitHub Copilot as an install target (#194)",
          "author_name": "Awokoya Olawale Davidson",
          "author_login": "Davidson3556",
          "committed_at": "2026-07-06T20:12:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8ac2ff0132e01c2c63e4a411ba4c0fbfc48a7a1d",
          "body": "… invocation (#178)\n\n* feat(test): make \"test wait\" variadic — attach to several runs in one invocation\n\n* fix(wait): honor the shared deadline for queued members and hint only resumable runs",
          "is_bot": false,
          "headline": "feat(test): make \"test wait\" variadic — attach to several runs in one…",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-06T20:12:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "108a91315762ccb8c1c157cbc5e15fb1914a7401",
          "body": "…an-out (#154)\n\n* fix(batch): classify RequestTimeoutError as timeout in --all --wait fan-out\n\nWhen test run --all --wait or test rerun --all --wait hit a per-request timeout\nduring batch fan-out polling, RequestTimeoutError rejected the fan-out before\nout.print(). Classify it as status:'timeout' in\n[…]\nCursor <cursoragent@cursor.com>\n\n* Remove unused readFileSync import from test file\n\n---------\n\nCo-authored-by: Contributor <contributor@testsprite.com>\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "fix(batch): classify RequestTimeoutError as timeout in --all --wait f…",
          "author_name": "Muath Awad",
          "author_login": "Awad-de",
          "committed_at": "2026-07-06T20:11:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "78ad224ba55231d383f7bc44f949b8ad016235d7",
          "body": "Bumps [marocchino/sticky-pull-request-comment](https://github.com/marocchino/sticky-pull-request-comment) from 2.9.4 to 3.0.5.\n- [Release notes](https://github.com/marocchino/sticky-pull-request-comment/releases)\n- [Commits](https://github.com/marocchino/sticky-pull-request-comment/compare/773744901\n[…]\nirect:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(ci): bump marocchino/sticky-pull-request-comment (#187)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-06T20:10:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c6d37b7e5cfc85cd56b3ac2f5d39c7177e019a46",
          "body": "* fix(http): clear per-attempt timeout timers\n\n* fix(http): preserve timeout race classification",
          "is_bot": false,
          "headline": "fix(http): clear per-attempt timeout timers (#137)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-06T20:10:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7b10b724442b81b46275a51b4f0a37051ba19af",
          "body": "* fix(config): treat empty env vars as unset in loadConfig\n\n* test: address review — dry-run whoami uses offline client; fix whitespace env key expectation",
          "is_bot": false,
          "headline": "fix(config): treat empty env vars as unset in loadConfig (#8)",
          "author_name": "Sahil Rakhaiya",
          "author_login": "SahilRakhaiya05",
          "committed_at": "2026-07-06T20:09:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b9e9601c4926e21c89066d30d56312524036ecb0",
          "body": "* feat(test): add \"test lint\" offline plan/steps validator\n\n* fix(lint): report physical JSONL line numbers (blank lines no longer shift them)",
          "is_bot": false,
          "headline": "feat(test): add \"test lint\" offline plan/steps validator (#176)",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-05T22:28:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4b724619e27a360a00e6c578db3e5068bb566d91",
          "body": "* feat(cli): add 'test flaky' repeat-run flaky-test detector\n\n* fix(flaky): cap --runs at 10 per maintainer scope (#115)\n\nRescope the flaky detector's --runs bound from 1-100 to 1-10 as requested in the #115 triage: uncapped FE replays amplify free executions. Updates the MAX_FLAKY_RUNS constant (wh\n[…]\nine rendered in the test flaky --help output. Regenerate the snapshot so the help snapshot test stays green on CI.\n\n* docs(changelog): resolve leftover merge-conflict markers (keep JUnit + flaky 1-10)",
          "is_bot": false,
          "headline": "feat(cli): add 'test flaky' repeat-run flaky-test detector (#132)",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-05T22:27:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c6f946e574dc402abf2be1f5d8f56a3a219393cb",
          "body": "…m check, opt-out, CI-safe) (#181)",
          "is_bot": false,
          "headline": "feat(cli): non-blocking \"new version available\" notice (24h-cached np…",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-05T22:27:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "768da46510d4c4d15ce2a70ff50acc7ef0c4c245",
          "body": "… CI proxies (#169)\n\n* feat(cli): honor HTTPS_PROXY/HTTP_PROXY/NO_PROXY behind corporate and CI proxies\n\n* fix(proxy): degrade to default dispatcher when proxy agent init fails instead of crashing startup\n\n* fix(proxy): pin undici to ^7.16.0 for Node 20 compatibility (8.x requires Node >=22.19)",
          "is_bot": false,
          "headline": "feat(cli): honor HTTPS_PROXY/HTTP_PROXY/NO_PROXY behind corporate and…",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-05T22:27:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8eb4acff70e216ed6b63bfd19fb1fde7107b5c7f",
          "body": "Windsurf (Cascade) reads workspace rules from `.windsurf/rules/*.md`. Add it\nas an own-file agent target so `testsprite agent install --target windsurf`\n(and `setup --agent windsurf`) installs the TestSprite skills into a Windsurf\nproject. Reworked onto the v0.2.0 multi-skill agent-targets API (path\n[…]\ns (incl.\nCascade-frontmatter and per-skill budget tests), the e2e matrix guards /\ncontent-integrity (gated on compactBody), and the README/DOCUMENTATION target\nlists (incl. the --force own-file list).",
          "is_bot": false,
          "headline": "feat(agent): add windsurf as an install target (#29)",
          "author_name": "Awokoya Olawale Davidson",
          "author_login": "Davidson3556",
          "committed_at": "2026-07-05T22:27:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2ddb03d5674ed4bfd7d0e7655170ce8b8d2bdd54",
          "body": "… (#11)\n\n* feat(cli): add runtime Node.js version check with clear error message\n\n* refactor(version-guard): extract to a documented module tested against the real implementation",
          "is_bot": false,
          "headline": "feat(cli): add runtime Node.js version check with clear error message…",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-05T19:41:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d72290d6d92d2806b33608d67af304782597f753",
          "body": "* fix(test): validate artifact run id default path\n\n* fix(test): reject windows dot artifact run ids\n\n* fix(test): reject windows dot-suffix artifact run ids\n\n* style(test): format artifact run id guard\n\n---------\n\nCo-authored-by: Lexiie <28455136+Lexiie@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(test): guard default artifact run id path (#172)",
          "author_name": "Lexiie",
          "author_login": "Lexiie",
          "committed_at": "2026-07-05T19:41:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "17650be02c06d9fef2742039a16bb678595bdf89",
          "body": "* block artifact download redirects\n\n* redact artifact download urls\n\n---------\n\nCo-authored-by: merlinsantiago982-cmd <merlinsantiago982-cmd@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix: harden failure bundle artifact downloads (#60)",
          "author_name": "merlinsantiago982-cmd",
          "author_login": "merlinsantiago982-cmd",
          "committed_at": "2026-07-05T19:38:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ff639978187dc521aecf344de132dfbc5db0ed1",
          "body": "…t pure) (#31)\n\nInteractive prompts (`prompt.ts` — the API-key prompt during `setup`/`auth\nconfigure`, the target prompt during `agent install`) wrote the question and\nmasking to STDOUT, and the \"Configuring profile …\" prelude defaulted to\nstdout too. On the interactive path that mixes UI text into \n[…]\ned.\nCallers that inject explicit streams are unaffected.\n\nAdds regression tests: promptText writes the question to stderr by default,\nand the configure prelude lands on stderr (not the result stdout).",
          "is_bot": false,
          "headline": "fix(cli): route interactive prompts and prelude to stderr (keep stdou…",
          "author_name": "Awokoya Olawale Davidson",
          "author_login": "Davidson3556",
          "committed_at": "2026-07-05T19:38:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "759e85c2e046af365c7904376ab577d9e38e0cb3",
          "body": "The 'testsprite usage' command help text listed three examples but\nomitted the --debug flag (a global option useful for diagnosing auth\nand network issues). It also didn't document the exit codes, which\nmatters for CI/CD scripts that gate on the return value.\n\nThis PR adds:\n- A --debug example showi\n[…]\n the CLI know what to expect.\n\nPure documentation improvement — no behavioral change, no new deps.\nTested: existing unit tests pass (npm test).\n\nCo-authored-by: MOAAMN SAYED <moaamnsayed560@gmail.com>",
          "is_bot": false,
          "headline": "docs(usage): add --debug example + exit codes to help text (#171)",
          "author_name": "mo01115285816-cyber",
          "author_login": "mo01115285816-cyber",
          "committed_at": "2026-07-05T19:34:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "93c621c6ba021dc513c31506c35fd632c394b536",
          "body": "…al without --all (#163)\n\nTwo silent-footgun gaps in test rerun's flag validation:\n\n1. Explicit test IDs combined with --all silently discarded the listed\n   IDs — the --all branch resolves the full project test set and\n   overwrites them — so 'rerun test_abc --all' dispatched a batch rerun\n   of EV\n[…]\nth reject with VALIDATION_ERROR (exit 5) before any network dispatch.\n\nFixes #160\n\nCo-authored-by: Kshitij Bhardwaj <tothemoon202154@outlook.com>\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(rerun): reject explicit IDs with --all and --status/--skip-termin…",
          "author_name": "kshitij-heizen",
          "author_login": "kshitij-heizen",
          "committed_at": "2026-07-05T19:34:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f732fdb1663b4dddb3a75db6e471359fed6fa054",
          "body": "… files in --out dir (#162)\n\ncommitBundle's stale-file sweep removed EVERY directory entry not part\nof the fresh bundle, so 'test failure get --out <dir>' / 'test artifact\nget --out <dir>' pointed at a pre-existing, populated directory silently\ndeleted the user's unrelated files (exit 0, no warning)\n[…]\nwrites code.ts — but\nforeign files and directories are never touched.\n\nFixes #159\n\nCo-authored-by: Kshitij Bhardwaj <tothemoon202154@outlook.com>\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(bundle): only sweep bundle-owned files in commit, preserving user…",
          "author_name": "kshitij-heizen",
          "author_login": "kshitij-heizen",
          "committed_at": "2026-07-05T19:34:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "011208c46f3d132e98cb3138b0b36770eb05e639",
          "body": "…d \"agent status\" (#177)",
          "is_bot": false,
          "headline": "feat(agent): stamp installed skills with a version/hash marker and ad…",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-05T19:34:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9457583f27b8c4e57541933db9ed45e554dc9ad2",
          "body": "…ressions (#168)\n\n* feat(test): add \"test diff <run-a> <run-b>\" to isolate run-to-run regressions\n\n* test(diff): cover runDiff --dry-run branch (offline canned sample)",
          "is_bot": false,
          "headline": "feat(test): add \"test diff <run-a> <run-b>\" to isolate run-to-run reg…",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-05T19:33:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dcbcbee16c868e8fb96dc84824d0596e6f1c2703",
          "body": null,
          "is_bot": false,
          "headline": "fix(steps): surface run-scoped per-step error text and stepType (#167)",
          "author_name": "Andy",
          "author_login": "Andy00L",
          "committed_at": "2026-07-05T19:33:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3fd703ffac59a38b6b5c227befdaf2510497b308",
          "body": "…nd test wait (#153)\n\nApply the fix in src/commands/ (the compiled CLI path). When the overall\n--timeout polling deadline is exceeded, emit {runId, status:\"running\"} to\nstdout before exit 7 so JSON agents can chain into test wait.\n\nCo-authored-by: Contributor <contributor@testsprite.com>\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "fix(poll): emit partial run to stdout on TimeoutError in run --wait a…",
          "author_name": "Muath Awad",
          "author_login": "Awad-de",
          "committed_at": "2026-07-05T19:32:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e1d00f1816cd87fd2f64337708f2ed8849456efa",
          "body": "* feat(agent): add kiro as an install target\n\nAdds kiro as an own-file agent target on the current multi-skill model: AgentTarget union, a pathFor('kiro') case landing at .kiro/skills/<skill>/SKILL.md, and a TARGETS entry (experimental, own-file, wrapSkill frontmatter like claude/antigravity). Kiro \n[…]\nde the new kiro target. Add kiro (own-file, between cline and codex to match TARGETS order) to both guards, and add kiro to the multi-target install e2e so the target is actually exercised end-to-end.",
          "is_bot": false,
          "headline": "feat(agent): add kiro as an install target (#10)",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-05T19:32:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "38e0f190666267e2c9b5d526424f7b5a9682db0e",
          "body": "…n (#33)\n\npollAccepted in runTestRerun hardcoded exitCode:1 on ApiError, causing\nthe auth-escalation find(r => r.error?.exitCode === 3) to always return\nundefined -- auth failures silently exited 1 instead of 3.\n\n- preserve err.exitCode in pollAccepted (mirrors runTestRunAll fix)\n- add auth escalation block before generic exit-1 throw\n- bound initial chunk idempotency key to <=256 chars (mirrors retry path)",
          "is_bot": false,
          "headline": "fix(rerun): preserve exit code and escalate auth errors in batch reru…",
          "author_name": "Rahul Joshi",
          "author_login": "crypticsaiyan",
          "committed_at": "2026-07-05T19:32:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b675630b852e73b1f474d905a060cbb9eeb40b0a",
          "body": "* feat(test): JUnit XML report export for batch --wait runs\n\n* fix(ci): prettier formatting and help snapshot alignment for report flags\n\n* fix(test): address CodeRabbit review on JUnit report export\n\n* fix(test): add projectId to CliBatchRunFreshResult for JUnit inference",
          "is_bot": false,
          "headline": "feat(test): JUnit XML report export for batch --wait runs (#96)",
          "author_name": "Sahil Rakhaiya",
          "author_login": "SahilRakhaiya05",
          "committed_at": "2026-07-05T19:31:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0de372c51d1282d61ccf11b1c3c7b1f1a0d22398",
          "body": "A successful (200) response whose body is not JSON — a misconfigured\nendpoint, a proxy / captive-portal / login page returning HTML with a\nsuccess status, or an empty body — caused the OK path to call raw\n`response.json()`, whose SyntaxError escaped to the top-level handler.\nThat produced an opaque \n[…]\n\npoints the operator at their endpoint config; details include the HTTP\nstatus, content-type, and underlying parse message. Abort/timeout\nerrors mid-read keep their existing classification.\n\nFixes #94",
          "is_bot": false,
          "headline": "fix(http): map non-JSON 200 responses to a typed error envelope (#166)",
          "author_name": "Awokoya Olawale Davidson",
          "author_login": "Davidson3556",
          "committed_at": "2026-07-05T19:31:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c0b52f852394e0199e663ddf02262ad2feb9fe51",
          "body": null,
          "is_bot": false,
          "headline": "fix(setup): validate endpoint before key check (#149)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-05T19:30:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b5879de422891208a9b5a57fec8d45d04267c587",
          "body": null,
          "is_bot": false,
          "headline": "fix: reject malformed api keys (#141)",
          "author_name": "nopp",
          "author_login": "naufalfx805-source",
          "committed_at": "2026-07-05T19:30:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "87a6dff24e5f9744a1c5f6c9335100e60961e000",
          "body": null,
          "is_bot": false,
          "headline": "fix: reject directory code output paths (#140)",
          "author_name": "nopp",
          "author_login": "naufalfx805-source",
          "committed_at": "2026-07-05T19:30:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25ed285cbadb7c1a7a56cac1fd2ec25f8cdb437f",
          "body": null,
          "is_bot": false,
          "headline": "fix: reject blank project passwords (#139)",
          "author_name": "nopp",
          "author_login": "naufalfx805-source",
          "committed_at": "2026-07-05T19:30:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "495db2f9f098b30cbb9db3bd7fe809332150cf7b",
          "body": null,
          "is_bot": false,
          "headline": "fix(test): validate list status before client setup (#152)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-05T19:29:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "06d2c4deb5c2e51123ca6358673af782f2fb56a6",
          "body": null,
          "is_bot": false,
          "headline": "fix(project): validate list flags before client setup (#150)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-05T19:29:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "205b1fb37f2778bf7a3ddaf7c1ab458dec9ae119",
          "body": "* fix(paginate): break loop on empty items with non-null nextToken\n\npaginate() in pagination.ts entered an infinite loop when the API\nreturned { items: [], nextToken: 'cursor' }. The loop only checked\nnextToken !== null, never whether items was empty. Any filtered list\ncommand returning zero results\n[…]\n remains >=80% on all 4 metrics (lines/statements/functions/branches).\n\n* fix(paginate): bound cursor loops without dropping empty pages\n\n---------\n\nSigned-off-by: Aldo Rizona <aldorizona10@gmail.com>",
          "is_bot": false,
          "headline": "fix(paginate): bound cursor loops without dropping empty pages (#48)",
          "author_name": "Aldo Rizona",
          "author_login": "aldorizona10-glitch",
          "committed_at": "2026-07-05T19:29:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6b90ff405006ff0731c944bec961ae7d120c2250",
          "body": "* feat(cli): respect NO_COLOR environment variable per no-color.org\n\n* fix(ticker): treat empty NO_COLOR as color-enabled per no-color.org",
          "is_bot": false,
          "headline": "feat(cli): respect NO_COLOR environment variable per no-color.org (#12)",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-05T19:29:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dc4d3375dc6ff0cff0a9104bbc1776898f14ed5d",
          "body": "…ON_ERROR (#27)",
          "is_bot": false,
          "headline": "fix(test): guard parseDuration --since against overflow with VALIDATI…",
          "author_name": "Rahul Joshi",
          "author_login": "crypticsaiyan",
          "committed_at": "2026-07-05T19:28:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6e7f2b3f0aafa61328c01daf276497b3030b192a",
          "body": "…test create) (#39)\n\n* fix(test): reject whitespace-only --name in test update (parity with test create)\n\n* style: run prettier on src/commands/test.ts",
          "is_bot": false,
          "headline": "fix(test): reject whitespace-only --name in test update (parity with …",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-05T19:27:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e53257d00887b636a05f0aad09828c13eb28e83c",
          "body": "… (#17)\n\n`parseRequestTimeoutFlag` was copy-pasted byte-for-byte into five command\nfiles (auth, project, usage, init, test). Every copy silently returned\n`undefined` for an invalid value, so an explicit `--request-timeout 30s`\n(a natural \"30 seconds\" typo) resolved to undefined and the command ran\nw\n[…]\nay global env var should not hard-fail every command).\n\nAdds unit coverage for parseRequestTimeoutFlag and a subprocess\nregression that `--request-timeout 30s` exits 5 instead of falling back\nto 120s.",
          "is_bot": false,
          "headline": "fix(cli): validate --request-timeout flag and de-duplicate its parser…",
          "author_name": "Awokoya Olawale Davidson",
          "author_login": "Davidson3556",
          "committed_at": "2026-07-02T20:48:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8da07fb4b11bf003e9bc62c5d479424c663350b2",
          "body": null,
          "is_bot": false,
          "headline": "fix(project): avoid password file reads in dry-run update (#54)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-02T20:48:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "76fff29c91c95f0900ba3ea2dd14f75e69396042",
          "body": "…rd (#37)\n\nassertNotLocal lowercased the hostname but did not strip a trailing dot, so http://localhost. (the FQDN form of localhost, RFC 6761) and http://localhost%2e bypassed the host === 'localhost' loopback check. IP literals are already dot-normalized by the WHATWG URL parser, so only named hosts were affected. Strips one trailing dot before the comparison. Adds 4 regression tests (3 blocked variants + 1 public-FQDN no-false-positive).",
          "is_bot": false,
          "headline": "fix(target-url): treat trailing-dot hostnames as loopback in SSRF gua…",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-02T20:48:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7b7d80db786068b50e4f44b7f200ed3556e31a1f",
          "body": "…131)",
          "is_bot": false,
          "headline": "fix(credentials): strip CR/LF from values to prevent INI injection (#…",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-02T20:46:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03251d744a0d5324eac177f2c42a1eb7e7f3277b",
          "body": "…ared deadline (#130)\n\nrunTestRunAll computes each member's poll budget as\nMath.max(1, ceil(batchDeadlineMs - now)), so a run whose turn arrives\nafter the shared --timeout deadline still gets a fresh >=1s poll. With\n--max-concurrency bounding the fan-out, a batch could overshoot the\ndocumented share\n[…]\n poll and asserts the second member\nis never polled and reports 'timeout'.\n\nCo-authored-by: ahndohun <19940813+ahndohun@users.noreply.github.com>\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(test): stop run --all --wait from polling queued runs past the sh…",
          "author_name": "안도훈",
          "author_login": "ahndohun",
          "committed_at": "2026-07-02T20:46:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "03c4f11ae8ef14251299863d521e49d1e4f10a80",
          "body": "…alls (#129)\n\nThe codex managed-section branch already runs inspectTargetPath during\n--dry-run ([P2]) so a planted symlink is refused the same way the real\ninstall refuses it. The own-file targets (claude, cursor, cline,\nantigravity) skipped that guard in dry-run and reported the write as\nsuccessful\n[…]\noth the\nsymlinked-target and symlinked-parent cases with regression tests.\n\nCo-authored-by: ahndohun <19940813+ahndohun@users.noreply.github.com>\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(agent): apply symlink fail-close guard to own-file --dry-run inst…",
          "author_name": "안도훈",
          "author_login": "ahndohun",
          "committed_at": "2026-07-02T20:45:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "be9784a639931fb602b00cb00624793db35f6557",
          "body": "…run and run --all (#128)\n\ntest run, test create, create-batch, plan put, code put, update, and\ndelete all print the auto-minted idempotency key to stderr under\n--output json (as well as --verbose / --debug) so JSON-mode automation\ncan capture the key and replay a retry safely. test rerun and\ntest r\n[…]\n the JSON-mode emission (and the text-mode silence)\nwith regression tests.\n\nCo-authored-by: ahndohun <19940813+ahndohun@users.noreply.github.com>\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(test): emit auto-minted idempotency-key under --output json in re…",
          "author_name": "안도훈",
          "author_login": "ahndohun",
          "committed_at": "2026-07-02T20:45:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dfdee5a3e051987c0ce090512c6d197532f4deb1",
          "body": "Co-authored-by: cmdr-chara <249489759+cmdr-chara@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(prompt): preserve buffered input between prompts (#118)",
          "author_name": "Chara",
          "author_login": "cmdr-chara",
          "committed_at": "2026-07-02T20:45:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5e0f7c4db423885eb2b442e9627643bd6f8c6199",
          "body": "* fix(test): reject empty code get --out and strip code-file BOM\n\nWhen test code get --out receives an empty inline body, closeOutputFile left a zero-byte file with exit 0 — scripts and agents treated that as a successful download. Abort the sink, unlink any artifact, and surface VALIDATION_ERROR in\n[…]\n5)\n- abortOutputFile: wait for stream close before unlinking tmpPath\n- BOM test: use .py code-file (assertPythonCodeFile from v0.2.0)\n- CI: build before test + fileParallelism false (dist/ race flake)",
          "is_bot": false,
          "headline": "fix(test): reject empty code get --out and strip code-file BOM (#34)",
          "author_name": "Sahil Rakhaiya",
          "author_login": "SahilRakhaiya05",
          "committed_at": "2026-07-02T20:45:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "000c196375883e2df773a55c53df79ff7f67412f",
          "body": null,
          "is_bot": false,
          "headline": "ci: add Node 20 to test and build matrix (#133)",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-02T20:45:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "21dc760f1bcc898d300ba5c4d873ad807cdde7b8",
          "body": "Only `test` and `project` validated the global `--output` flag. The\n`auth`, `usage`, `agent`, and `init` command groups resolved it with\n`globals.output ?? 'text'`, so an unrecognised value (e.g. a typo like\n`--output josn`) was silently coerced to text mode instead of being\nrejected. A coding agent\n[…]\nywhere. This also unifies the error\nwording, which previously differed between `test`\n(\"Flag `--output` is invalid: must be one of: json, text.\") and\n`project` (\"--output must be one of: json, text\").",
          "is_bot": false,
          "headline": "fix(cli): validate --output uniformly across all command groups (#14)",
          "author_name": "Awokoya Olawale Davidson",
          "author_login": "Davidson3556",
          "committed_at": "2026-07-02T20:45:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9aa7ba9d6767b64234b28de044cec76bf15aee6e",
          "body": "…e (#36)\n\nproject create/update validated --name with the action handler's if (!name) check, which a whitespace-only string passes (a non-empty string is truthy). The blank name was then sent verbatim, creating a junk-named project. The sibling \test create already rejects this via the requireString whitespace guard (dogfood P1 fix #1); this aligns project create/update with that behavior. Adds 2 regression tests.",
          "is_bot": false,
          "headline": "fix(project): reject empty/whitespace-only --name in create and updat…",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-02T20:45:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "497bf62e3e444f8e0d8e4eda15a8b9a275eb2809",
          "body": null,
          "is_bot": false,
          "headline": "fix(pagination): reject fractional pagination flags (#40)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-02T20:45:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a524702e75b24d563b351b9a1c6c9aa70d45796b",
          "body": null,
          "is_bot": false,
          "headline": "fix: align documented Node engine floor (#84)",
          "author_name": "nopp",
          "author_login": "naufalfx805-source",
          "committed_at": "2026-07-02T20:44:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2fd8f4cb78ca1cc100b634880383a8a4270ea64d",
          "body": "* fix(skill-nudge): require complete Codex managed section\n\n* docs(skill-nudge): document helper contracts\n\n---------\n\nCo-authored-by: ahndohun <19940813+ahndohun@users.noreply.github.com>",
          "is_bot": false,
          "headline": "fix(skill-nudge): require complete Codex managed section (#90)",
          "author_name": "안도훈",
          "author_login": "ahndohun",
          "committed_at": "2026-07-02T20:44:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "33b78482203a15fc7c2fb9473d6be9f50994befd",
          "body": "…ils (#38)",
          "is_bot": false,
          "headline": "fix(auth): preserve typed API error envelope when key verification fa…",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-02T20:43:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "91024301832cbba0e4beb2ef34ad72a8d85712cd",
          "body": "…rd (#37)\n\nassertNotLocal lowercased the hostname but did not strip a trailing dot, so http://localhost. (the FQDN form of localhost, RFC 6761) and http://localhost%2e bypassed the host === 'localhost' loopback check. IP literals are already dot-normalized by the WHATWG URL parser, so only named hosts were affected. Strips one trailing dot before the comparison. Adds 4 regression tests (3 blocked variants + 1 public-FQDN no-false-positive).",
          "is_bot": false,
          "headline": "fix(target-url): treat trailing-dot hostnames as loopback in SSRF gua…",
          "author_name": "Resque",
          "author_login": "lxcario",
          "committed_at": "2026-07-02T20:43:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "547b5be45799f5c8287638eb0ebc6a8bdef4cecb",
          "body": null,
          "is_bot": false,
          "headline": "fix(history): reject fractional page sizes (#55)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-02T20:43:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5f7dba1ca26d1bd3b45d1a6eaeabc0f5c4622e80",
          "body": null,
          "is_bot": false,
          "headline": "fix(auth): honor request timeout during configure (#52)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-02T20:43:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7928b5ce2f026f397c107bf4172469a1bba2f4b0",
          "body": null,
          "is_bot": false,
          "headline": "fix(help): include request-timeout in global flag guidance (#41)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-02T20:43:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a8a5cdfad3765f28665299b71d2eb6b364a43a6",
          "body": null,
          "is_bot": false,
          "headline": "docs(project): fix create URL flag example (#42)",
          "author_name": "JerryNee",
          "author_login": "JerryNee",
          "committed_at": "2026-07-02T20:43:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3ab8136d509eb99eddd121b3a29e2fd773a1f316",
          "body": "New issue form for hackathon submissions — auto-applies the `hackathon`\nlabel and captures the submitter's Discord identity for reward payout\ncoordination.",
          "is_bot": false,
          "headline": "feat(github): add Hackathon Improvement issue template",
          "author_name": "zeshi-du",
          "author_login": "zeshi-du",
          "committed_at": "2026-06-30T21:24:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c4ebb9ce16dbfe183b75b14399b549a1ecb43cce",
          "body": null,
          "is_bot": false,
          "headline": "release: v0.2.0",
          "author_name": "zeshi-du",
          "author_login": "zeshi-du",
          "committed_at": "2026-06-30T01:33:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "15e95de321a64b3393ec30f58ab34e315480ab87",
          "body": "…t json (#22)\n\nWhen a subcommand fired a parse error (unknown command, missing required\nargument, invalid option), Commander's outputError callback wrote plain\ntext to stderr immediately and the catch block exited 5 with no further\noutput. A machine consumer that always parses stderr as JSON receive\n[…]\nbedding. Four subprocess\nregression tests in the [fix-5] block cover missing-arg, unknown subcommand,\nargv-fallback, and text-mode no-regression paths.\n\nCo-authored-by: zeshi-du <zeshi@testsprite.com>",
          "is_bot": false,
          "headline": "fix(cli): emit JSON envelope for Commander parse errors under --outpu…",
          "author_name": "Rahul Joshi",
          "author_login": "crypticsaiyan",
          "committed_at": "2026-06-25T23:35:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b2fae59ba810fd76abc695d777a723f516a10ef3",
          "body": "…on (#21)\n\nA profile name (`--profile` / `TESTSPRITE_PROFILE`) is written verbatim as\nan INI section header (`[name]`) in `~/.testsprite/credentials`, but was\nnever validated. A name containing the characters that break that grammar\nsilently corrupted the file:\n\n  --profile \"prod]\"   -> serialises t\n[…]\nd of\nsilently corrupting or failing to persist credentials.\n\nAdds unit coverage for the guard and the three entry points, plus a\nsubprocess regression.\n\nCo-authored-by: Zeshi Du <duke.zeshi@gmail.com>",
          "is_bot": false,
          "headline": "fix(cli): validate profile names to prevent credentials-file corrupti…",
          "author_name": "Awokoya Olawale Davidson",
          "author_login": "Davidson3556",
          "committed_at": "2026-06-25T23:35:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "97c04a4ce935baafa3690b4f1430193b80be16c9",
          "body": "… (#23)\n\nCo-authored-by: zeshi-du <zeshi@testsprite.com>",
          "is_bot": false,
          "headline": "fix(bundle): add retry loop to streamUrlToFile for transport failures…",
          "author_name": "Rahul Joshi",
          "author_login": "crypticsaiyan",
          "committed_at": "2026-06-25T23:35:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1f37de11097e4f4c67510fd302b059d695bde1b5",
          "body": "runFailureGet now resolves and validates --out via resolveBundleDir and assertOutDirParentExists before calling GET /tests/{id}/failure, matching runArtifactGet and runCodeGet fast-fail behavior.\n\nAdds regression tests asserting zero fetch calls on empty --out and missing parent dir paths.",
          "is_bot": false,
          "headline": "fix(test): validate failure get --out before API fetch (#26)",
          "author_name": "Sahil Rakhaiya",
          "author_login": "SahilRakhaiya05",
          "committed_at": "2026-06-25T23:19:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3b7ce0729c00bd2f8fdd5285f5efbdafb38d6271",
          "body": "…RROR (#19)\n\nA malformed API endpoint produced an opaque or misleading failure instead\nof a clear config error:\n\n  --endpoint-url \"not a url\"   -> `Error: Invalid URL` (exit 1, a raw\n                                  `new URL()` throw with no guidance)\n  --endpoint-url \"localhost:3000\" (missing sche\n[…]\nxisting\nself-hosted/CI configs and the test suite's localhost mock backend are\nunaffected.\n\nAdds unit coverage for assertValidEndpointUrl and the two makeHttpClient\npaths, plus subprocess regressions.",
          "is_bot": false,
          "headline": "fix(cli): reject a malformed --endpoint-url with a clear VALIDATION_E…",
          "author_name": "Awokoya Olawale Davidson",
          "author_login": "Davidson3556",
          "committed_at": "2026-06-25T23:19:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4dac1d68388d8413be66e07cd5f25204a7c96453",
          "body": "Batch-rerun chunks (>50 testIds) were dispatched concurrently via\nPromise.all. The backend's producer/teardown closure dedup happens\nper-request, not across requests, so two concurrent chunks sharing a\nproject's producer could each independently decide to trigger it,\ndouble-running the producer or t\n[…]\nd layer, warning on stderr if a duplicate trigger is\ndetected.\n\nFixed a pre-existing test whose fixture relied on the old\ndouble-counting behavior (same accepted entry returned from every\nretry call).",
          "is_bot": false,
          "headline": "fix(test): dedupe and serialize chunked batch-rerun dispatch (#9)",
          "author_name": "Rahul Joshi",
          "author_login": "crypticsaiyan",
          "committed_at": "2026-06-25T23:18:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1963461d4bb1d43ce7385e88a9791553c8305701",
          "body": "…(#7)\n\ntest code get --out <path> opened (truncated) the destination file\nbefore the network request. If the GET then failed, or hit the\n\"no code generated yet\" branch which writes nothing, the user's\npre-existing --out file was left emptied with no way to recover it.\n\nWrite to a sibling temp file i\n[…]\ndle.ts already uses for multi-file bundles.\n\nAdd regression tests for both failure modes: a failing fetch and\nthe no-code-yet branch. Both reproduce the truncation on the old\ncode and pass on the fix.",
          "is_bot": false,
          "headline": "fix(test): atomic write for code get --out, no truncate before fetch …",
          "author_name": "Rahul Joshi",
          "author_login": "crypticsaiyan",
          "committed_at": "2026-06-25T23:18:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5ebcba856f9afe56b477bceaa97574c59c6c1a30",
          "body": "fix(test): prevent batch-run scheduler from serializing after first wave",
          "is_bot": false,
          "headline": "Merge pull request #6 from crypticsaiyan/fix/batch-run-concurrency",
          "author_name": "ruili-testsprite",
          "author_login": "ruili-testsprite",
          "committed_at": "2026-06-25T22:37:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fc928772ae22e3d294f98fab9b990afb4d1ae9b5",
          "body": "create-batch --run launched its first concurrencyLimit triggers in\nparallel, but the steady-state loop awaited each subsequent job to\nfully finish (trigger + full --wait poll) before launching the next\none. Effective concurrency dropped to 1 after the initial wave\nregardless of --max-concurrency.\n\nS\n[…]\n(), never await a whole job inline.\n\nAdd a regression test using equal-delay trigger responses so the\nfirst wave settles in the same microtask batch, which is the exact\ncondition that exposed the bug.",
          "is_bot": false,
          "headline": "fix(test): batch-run scheduler serializes after first wave",
          "author_name": "Rahul Joshi",
          "author_login": "crypticsaiyan",
          "committed_at": "2026-06-23T10:55:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "18f6e6ee1c0dd131b5015bf58d56a2496086f8a6",
          "body": "- Onboarding consolidated into `testsprite setup` (formerly `init`); the\n  granular auth commands remain as hidden, deprecated aliases.\n- CLI reports its version in the User-Agent header.\n- README: the launch video no longer renders as a bare URL on npm.",
          "is_bot": false,
          "headline": "release: v0.1.2",
          "author_name": "zeshi-du",
          "author_login": "zeshi-du",
          "committed_at": "2026-06-20T03:43:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4b33601285a95e8ffe346eb87c572ee708d007d0",
          "body": "ci(release): switch npm publish to OIDC trusted publishing",
          "is_bot": false,
          "headline": "Merge pull request #3 from TestSprite/ci/trusted-publishing",
          "author_name": "ruili-testsprite",
          "author_login": "ruili-testsprite",
          "committed_at": "2026-06-12T05:04:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1dce20e73d1004b55e03d45d700d64d7d0be25a1",
          "body": "NPM_TOKEN secret was never configured, so tag-triggered releases failed\nwith ENEEDAUTH. Auth now uses npm trusted publishing (configured on\nnpmjs.com for this repo + release.yaml):\n\n- drop NODE_AUTH_TOKEN env (empty token would shadow OIDC auth)\n- upgrade npm to >= 11.5.1 (trusted publishing requirement; Node 22 bundles 10.x)\n- bump checkout/setup-node to v5 ahead of the June 16 Node 20 runner cutoff",
          "is_bot": false,
          "headline": "ci(release): switch npm publish to OIDC trusted publishing",
          "author_name": "Rui Li",
          "author_login": "ruili-testsprite",
          "committed_at": "2026-06-12T04:59:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a8c5e2741498571b5a8c8c30391a07ff9e7cf650",
          "body": "- prettier-clean the README video block (fixes CI format:check on main)\n- bump version to 0.1.1\n- CHANGELOG: add [0.1.1] docs-only entry\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): v0.1.1 — README launch-video patch (#2)",
          "author_name": "dukeduke2016",
          "author_login": "dukeduke2016",
          "committed_at": "2026-06-12T02:11:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "941cc368c22737894dc1d0ed7b454744e8c91064",
          "body": "Updated the README with a new link and added a video description.",
          "is_bot": false,
          "headline": "Update README with new link and video information",
          "author_name": "ruili-testsprite",
          "author_login": "ruili-testsprite",
          "committed_at": "2026-06-12T01:14:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25aac12d1666df9b7f8501e0b0c5e93f0863847a",
          "body": "The Lint & Format job runs prettier --check over workflow YAML; the\naligned trailing comment failed it on every push.",
          "is_bot": false,
          "headline": "chore(ci): prettier-clean release.yaml comment spacing",
          "author_name": "zeshi-du",
          "author_login": "zeshi-du",
          "committed_at": "2026-06-11T12:01:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2ae63aadc09b7218da865aa95514d47c2b66f961",
          "body": null,
          "is_bot": false,
          "headline": "chore: initial public snapshot v0.1.0",
          "author_name": "zeshi-du",
          "author_login": "zeshi-du",
          "committed_at": "2026-06-11T11:49:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 5,
      "commits_last_year": 96,
      "latest_release_at": "2026-07-17T02:41:43Z",
      "latest_release_tag": "v0.4.0",
      "releases_from_tags": false,
      "days_since_last_push": 1,
      "active_weeks_last_year": 6,
      "days_since_latest_release": 4,
      "mean_days_between_releases": 8.8
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 100,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@testsprite/testsprite-cli",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "testsprite",
            "cli",
            "testing",
            "automation"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@testsprite/testsprite-cli",
          "is_deprecated": false,
          "latest_version": "0.4.0",
          "repository_url": "https://github.com/TestSprite/testsprite-cli",
          "versions_count": 6,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 4,
          "monthly_downloads": 3374,
          "first_published_at": "2026-06-11T12:07:27.101000Z",
          "latest_published_at": "2026-07-17T01:34:13.879000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 4
        }
      ]
    },
    "popularity": {
      "forks": 98,
      "stars": 2415,
      "watchers": 3,
      "fork_history": {
        "days": [
          {
            "date": "2026-06-12",
            "count": 2
          },
          {
            "date": "2026-06-13",
            "count": 4
          },
          {
            "date": "2026-06-15",
            "count": 2
          },
          {
            "date": "2026-06-16",
            "count": 2
          },
          {
            "date": "2026-06-17",
            "count": 5
          },
          {
            "date": "2026-06-18",
            "count": 1
          },
          {
            "date": "2026-06-19",
            "count": 5
          },
          {
            "date": "2026-06-20",
            "count": 2
          },
          {
            "date": "2026-06-21",
            "count": 4
          },
          {
            "date": "2026-06-22",
            "count": 1
          },
          {
            "date": "2026-06-23",
            "count": 7
          },
          {
            "date": "2026-06-24",
            "count": 4
          },
          {
            "date": "2026-06-25",
            "count": 3
          },
          {
            "date": "2026-06-26",
            "count": 2
          },
          {
            "date": "2026-06-27",
            "count": 3
          },
          {
            "date": "2026-06-28",
            "count": 1
          },
          {
            "date": "2026-06-29",
            "count": 4
          },
          {
            "date": "2026-06-30",
            "count": 1
          },
          {
            "date": "2026-07-01",
            "count": 9
          },
          {
            "date": "2026-07-02",
            "count": 4
          },
          {
            "date": "2026-07-03",
            "count": 2
          },
          {
            "date": "2026-07-04",
            "count": 2
          },
          {
            "date": "2026-07-05",
            "count": 1
          },
          {
            "date": "2026-07-06",
            "count": 1
          },
          {
            "date": "2026-07-07",
            "count": 5
          },
          {
            "date": "2026-07-08",
            "count": 3
          },
          {
            "date": "2026-07-09",
            "count": 2
          },
          {
            "date": "2026-07-10",
            "count": 4
          },
          {
            "date": "2026-07-11",
            "count": 1
          },
          {
            "date": "2026-07-12",
            "count": 1
          },
          {
            "date": "2026-07-13",
            "count": 1
          },
          {
            "date": "2026-07-14",
            "count": 1
          },
          {
            "date": "2026-07-16",
            "count": 2
          },
          {
            "date": "2026-07-18",
            "count": 1
          },
          {
            "date": "2026-07-19",
            "count": 2
          },
          {
            "date": "2026-07-20",
            "count": 1
          },
          {
            "date": "2026-07-21",
            "count": 2
          }
        ],
        "complete": true,
        "collected": 98,
        "total_forks": 98
      },
      "star_history": {
        "days": [
          {
            "date": "2026-07-01",
            "count": 58
          },
          {
            "date": "2026-07-02",
            "count": 78
          },
          {
            "date": "2026-07-03",
            "count": 70
          },
          {
            "date": "2026-07-04",
            "count": 145
          },
          {
            "date": "2026-07-05",
            "count": 177
          },
          {
            "date": "2026-07-06",
            "count": 100
          },
          {
            "date": "2026-07-07",
            "count": 78
          },
          {
            "date": "2026-07-08",
            "count": 70
          },
          {
            "date": "2026-07-09",
            "count": 60
          },
          {
            "date": "2026-07-10",
            "count": 45
          },
          {
            "date": "2026-07-11",
            "count": 18
          },
          {
            "date": "2026-07-12",
            "count": 9
          },
          {
            "date": "2026-07-13",
            "count": 6
          },
          {
            "date": "2026-07-14",
            "count": 4
          },
          {
            "date": "2026-07-15",
            "count": 6
          },
          {
            "date": "2026-07-16",
            "count": 5
          },
          {
            "date": "2026-07-17",
            "count": 14
          },
          {
            "date": "2026-07-18",
            "count": 11
          },
          {
            "date": "2026-07-19",
            "count": 9
          },
          {
            "date": "2026-07-20",
            "count": 10
          },
          {
            "date": "2026-07-21",
            "count": 27
          }
        ],
        "complete": false,
        "collected": 1000,
        "total_stars": 2415
      },
      "open_issues_and_prs": 45
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 441972,
      "source_files_sampled": 115,
      "oversized_source_files": 6,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "commander",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^12.1.0"
        },
        {
          "name": "undici",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^7.16.0"
        },
        {
          "name": "valibot",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.4.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": 16,
        "merged_prs": 85,
        "open_issues": 29,
        "closed_ratio": 0.701,
        "closed_issues": 68,
        "closed_unmerged_prs": 69
      },
      "bus_factor": 5,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "Andy00L",
          "commits": 12,
          "avatar_url": "https://avatars.githubusercontent.com/u/89641810?v=4"
        },
        {
          "type": "User",
          "login": "JerryNee",
          "commits": 12,
          "avatar_url": "https://avatars.githubusercontent.com/u/37407632?v=4"
        },
        {
          "type": "User",
          "login": "lxcario",
          "commits": 11,
          "avatar_url": "https://avatars.githubusercontent.com/u/208051869?v=4"
        },
        {
          "type": "User",
          "login": "Davidson3556",
          "commits": 8,
          "avatar_url": "https://avatars.githubusercontent.com/u/99369614?v=4"
        },
        {
          "type": "User",
          "login": "zeshi-du",
          "commits": 8,
          "avatar_url": "https://avatars.githubusercontent.com/u/257381225?v=4"
        },
        {
          "type": "User",
          "login": "crypticsaiyan",
          "commits": 7,
          "avatar_url": "https://avatars.githubusercontent.com/u/186129212?v=4"
        },
        {
          "type": "User",
          "login": "naufalfx805-source",
          "commits": 7,
          "avatar_url": "https://avatars.githubusercontent.com/u/266911045?v=4"
        },
        {
          "type": "User",
          "login": "SahilRakhaiya05",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/144577420?v=4"
        },
        {
          "type": "User",
          "login": "ahndohun",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/19940813?v=4"
        },
        {
          "type": "User",
          "login": "ruili-testsprite",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/170984446?v=4"
        }
      ],
      "contributors_sampled": 22,
      "top_contributor_share": 0.126
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "backport-dispatch.yml",
        "ci-nudge.yml",
        "ci.yml",
        "issue-triage.yml",
        "pr-triage.yml",
        "release.yaml",
        "stale.yml",
        "test-coverage.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        "eslint.config.mjs"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 5,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 9,
            "reason": "Found 26/27 approved changesets -- score normalized to 9",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "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": 9,
            "reason": "dependency not pinned by hash detected -- score normalized to 9",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file 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": 9,
            "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": "2708a4069fba72822f94906d05001b4d19e66d9c",
        "ran_at": "2026-07-21T18:26:19Z",
        "aggregate_score": 6.3,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": true
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/TestSprite/testsprite-cli",
    "host": "github.com",
    "name": "testsprite-cli",
    "owner": "TestSprite"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 76,
      "inputs": {
        "security": 63,
        "vitality": 75,
        "community": 76,
        "governance": 75,
        "engineering": 90
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 75,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 58,
            "inputs": {
              "commits_last_year": 96,
              "human_commit_share": 0.99,
              "days_since_last_push": 1,
              "active_weeks_last_year": 6
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "6/52 weeks with commits",
                "points": 4.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "96 commits in the last year",
                "points": 17.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 96
                    }
                  }
                ],
                "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": 100,
            "inputs": {
              "releases_count": 5,
              "latest_release_tag": "v0.4.0",
              "releases_from_tags": false,
              "days_since_latest_release": 4,
              "mean_days_between_releases": 8.8
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "5 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "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 ~8.8 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 8.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": "good",
        "name": "Community & Adoption",
        "value": 76,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "good",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 73,
            "inputs": {
              "forks": 98,
              "stars": 2415,
              "watchers": 3,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "window_too_short"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "2,415 stars",
                "points": 54.9,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 2415
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "98 forks",
                "points": 16.6,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 98
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "3 watchers",
                "points": 1.7,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "excellent",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 92,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": true,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (Apache-2.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "Apache-2.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 13.5,
                "status": "met",
                "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": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 59,
            "inputs": {
              "packages": [
                "@testsprite/testsprite-cli"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 3374
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "3,374 downloads/month across npm",
                "points": 47,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 3374,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "good",
        "name": "Sustainability & Governance",
        "value": 75,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "good",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "bus_factor": 5,
              "contributors_sampled": 22,
              "top_contributor_share": 0.126
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "5 contributor(s) cover half of all commits",
                "points": 45.9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 13% of commits",
                "points": 19.7,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 13
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "22 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 22
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "moderate",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 67,
            "inputs": {
              "merged_prs": 85,
              "open_issues": 29,
              "closed_issues": 68,
              "issue_closed_ratio": 0.701,
              "closed_unmerged_prs": 69
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "70% of issues closed",
                "points": 32.8,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 70
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "85/154 decided PRs merged",
                "points": 21.1,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 85,
                      "decided": 154
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 26/27 approved changesets -- score normalized to 9",
                "points": 13.5,
                "status": "partial",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 53,
            "inputs": {
              "followers": 71,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "TestSprite",
              "public_repos": 4,
              "account_age_days": 784
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "71 followers of TestSprite",
                "points": 13.4,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 71,
                      "login": "TestSprite"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "4 public repos, account ~2 yr old",
                "points": 9.4,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 4
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 2
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@testsprite/testsprite-cli"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 4
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "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": "6 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 6
                    }
                  }
                ],
                "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": "excellent",
        "name": "Engineering Quality",
        "value": 90,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 84,
            "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": "8 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 8
                    }
                  }
                ],
                "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": "eslint.config.mjs",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.mjs"
                    }
                  }
                ],
                "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": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "topics": [
                "ai",
                "cli",
                "e2e-testing",
                "playwright",
                "qa",
                "test-automation",
                "testing"
              ],
              "has_wiki": true,
              "homepage": "https://www.testsprite.com",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://www.testsprite.com",
                "points": 15,
                "status": "met",
                "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": "7 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "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": "moderate",
        "name": "Security",
        "value": 63,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 63,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 6.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 is not maximal on development and all release branches",
                "points": 3.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 26/27 approved changesets -- score normalized to 9",
                "points": 6.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "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 9",
                "points": 4.5,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "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": 6.8,
                "status": "partial",
                "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": 5
            },
            "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": "moderate",
        "name": "AI Readiness",
        "value": 69,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.989,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "94 of 95 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 94,
                      "sampled": 95
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 81,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "package-lock.json"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "tsconfig.json"
              ],
              "agent_commit_share": 0.094,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0.01
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "eslint.config.mjs",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.mjs"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "9 of the last 96 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 9,
                      "sampled": 96
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "1 of the last 96 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 1,
                      "sampled": 96
                    }
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 9",
                "points": 9,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 97,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 441972,
              "source_files_sampled": 115,
              "oversized_source_files": 6
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "6/115 source files over 60KB",
                "points": 52.1,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 115,
                      "oversized": 6
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
    "deps.dev does not index npm:@testsprite/testsprite-cli@0.4.0; advisories assessed against the repository dependency graph instead"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-21T18:26:46.106861Z",
  "schema_version": "0.23.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/t/TestSprite/testsprite-cli.svg",
  "full_name": "TestSprite/testsprite-cli",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

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.23.0 — metodología completa · wiki de métricas.

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