Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 1.13.0 · 2026-07-24 21:58 UTC

Ripixel-Studio / fitglue-server

FitGlue is a serverless fitness data aggregation and routing platform built on Google Cloud Platform. It ingests workout data from multiple sources (Hevy, Keiser, Fitbit), enriches it with standardized formats (FIT files), and routes it to connected services like Strava.

GoSin licencia detectada★ 1 estrella⑂ 0 forksdesde ene 2026Ver en GitHub ↗

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

56
global / 100
Moderado

Índice de salud del software

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

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

Perfil de puntuación

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

Titularidad

Ripixel StudioOrganización
0 seguidores7 repositorios públicosdesde jul 2026

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

Métricas por categoría

Vitalidad

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

85Excelente · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 1 días
18.7/36Cadencia de commits — 27/52 semanas con commits
18/18Volumen de commits — 1250 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year1250
human_commit_share1
days_since_last_push1
active_weeks_last_year27
Cómo se puntúa
16.2/27Publica versiones — 100 etiquetas de versión (sin releases de GitHub)
36/36Recencia de las versiones — última versión hace 1 días
27/27Cadencia de publicación — una versión cada ~0,6 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count100
latest_release_tagv16.60.2
releases_from_tags
days_since_latest_release1
mean_days_between_releases0,6
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?

22Crítico · 18% del índice global
Cómo se puntúa
0/60Estrellas — 1 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars1
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
0/22.5Licencia — no se detectó ningún archivo de licencia
18/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_licenseno
has_contributing
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sostenibilidad y Gobernanza

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

44En riesgo · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0.1/22.5Distribución de commits — el principal contribuyente firma el 99% de los commits
2.7/13.5Amplitud de contribuyentes — 2 contribuyentes
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Datos de entrada utilizados
bus_factor1
contributors_sampled2
top_contributor_share0,994
Cómo se puntúa
46.8/46.8Resolución de issues — 100% de issues cerradas
34.4/38.3Aceptación de PR — 9/10 PR decididos fusionados
4.5/15OpenSSF Scorecard: Code-Review — Found 9/27 approved changesets -- score normalized to 3
Datos de entrada utilizados
merged_prs9
open_issues0
closed_issues6
issue_closed_ratio1
closed_unmerged_prs1
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
0/25Alcance del propietario — 0 seguidores de Ripixel-Studio
6.6/25Trayectoria — 7 repos públicos, cuenta de ~0 años
Datos de entrada utilizados
followers0
owner_typeOrganization
is_verified
owner_loginRipixel-Studio
public_repos7
account_age_days13

Calidad de Ingeniería

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

73Bueno · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 1 flujo(s) de trabajo
24/24Pruebas presentes
0/16Configuración de linter
0/9.6Hooks de pre-commit
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 9 out of 9 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_configno
has_precommit_configno
Cómo se puntúa
30/30README
25/25Directorio de documentación
15/15Sitio de documentación / página del proyecto — https://fitglue.tech
10/10Descripción del repositorio
0/10Topics
0/10Wiki
Datos de entrada utilizados
topics
has_wikino
homepagehttps://fitglue.tech
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?

53Moderado · 16% del índice global
Cómo se puntúa
6.8/7.5Binary-Artifacts — binaries present in source code
3.8/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 9 out of 9 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
2.2/7.5Code-Review — Found 9/27 approved changesets -- score normalized to 3
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
0/2.5Licencia — license file not detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — sin datos
0.5/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 1
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — sin datos
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
0/7.5Vulnerabilities — 118 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate5,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.

75Bueno · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 100 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share1
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes14.943
Cómo se puntúa
18/18Arranque con un solo comando — Makefile
22/22Pruebas automatizadas
0/11Configuración de lint / formato
11/11Verificación estática de tipos — src/typescript/parkrun-fetcher/tsconfig.json, tsconfig.json
10/10Entorno reproducible — Dockerfile, lockfile
10/10Práctica demostrada con agentes — 38 de los últimos 100 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
1/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 1
Datos de entrada utilizados
has_nixno
has_tests
lockfilesgo.sum, package-lock.json
has_dockerfile
typed_language
bootstrap_filesMakefile
has_devcontainerno
has_linter_configno
typecheck_configssrc/typescript/parkrun-fetcher/tsconfig.json, tsconfig.json
agent_commit_share0,38
toolchain_manifestssrc/go/go.mod
dependency_bot_commit_share0
Cómo se puntúa
45/45Código verificable por tipos — Go (tipado estático)
53.2/55Tamaños de archivo manejables — 20/600 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageGo
largest_source_bytes660.351
source_files_sampled600
oversized_source_files20
Cómo se puntúa
40/40Esquema de API (OpenAPI/GraphQL/proto) — src/openapi/fitbit/swagger.json, src/openapi/github/swagger.json, src/openapi/hevy/swagger.json, src/openapi/oura/swagger.json, src/openapi/polar/swagger.json, src/openapi/spotify/swagger.json, src/openapi/strava/swagger.json, src/openapi/trainingpeaks/swagger.json, src/openapi/wahoo/swagger.json, src/proto/gateway/admin.proto, src/proto/gateway/client.proto, src/proto/gateway/public.proto, src/proto/gateway/webhook.proto, src/proto/google/api/annotations.proto, src/proto/google/api/http.proto, src/proto/models/activity/enrichments.proto, src/proto/models/activity/roundup.proto, src/proto/models/activity/source.proto, src/proto/models/activity/standardized.proto, src/proto/models/activity/uploaded.proto, src/proto/models/events/pipeline.proto, src/proto/models/notification/notification.proto, src/proto/models/pipeline/config.proto, src/proto/models/pipeline/execution.proto, src/proto/models/pipeline/pending_input.proto, src/proto/models/plugin/manifest.proto, src/proto/models/plugin/provider.proto, src/proto/models/user/auth.proto, src/proto/models/user/billing.proto, src/proto/models/user/integration.proto, src/proto/models/user/profile.proto, src/proto/services/activity/activity.proto, src/proto/services/billing/billing.proto, src/proto/services/pipeline/pipeline.proto, src/proto/services/registry/registry.proto, src/proto/services/user/user.proto
0/20Servidor MCP
0/40Ejemplos ejecutables
Datos de entrada utilizados
example_dirs
has_mcp_signalno
api_schema_filessrc/openapi/fitbit/swagger.json, src/openapi/github/swagger.json, src/openapi/hevy/swagger.json, src/openapi/oura/swagger.json, src/openapi/polar/swagger.json, src/openapi/spotify/swagger.json, src/openapi/strava/swagger.json, src/openapi/trainingpeaks/swagger.json, src/openapi/wahoo/swagger.json, src/proto/gateway/admin.proto, src/proto/gateway/client.proto, src/proto/gateway/public.proto, src/proto/gateway/webhook.proto, src/proto/google/api/annotations.proto, src/proto/google/api/http.proto, src/proto/models/activity/enrichments.proto, src/proto/models/activity/roundup.proto, src/proto/models/activity/source.proto, src/proto/models/activity/standardized.proto, src/proto/models/activity/uploaded.proto, src/proto/models/events/pipeline.proto, src/proto/models/notification/notification.proto, src/proto/models/pipeline/config.proto, src/proto/models/pipeline/execution.proto, src/proto/models/pipeline/pending_input.proto, src/proto/models/plugin/manifest.proto, src/proto/models/plugin/provider.proto, src/proto/models/user/auth.proto, src/proto/models/user/billing.proto, src/proto/models/user/integration.proto, src/proto/models/user/profile.proto, src/proto/services/activity/activity.proto, src/proto/services/billing/billing.proto, src/proto/services/pipeline/pipeline.proto, src/proto/services/registry/registry.proto, src/proto/services/user/user.proto

Datos clave

1estrellas de GitHub
2contribuidores
1250commits en los últimos 12 meses
1días desde el último push
100versiones publicadas
1factor bus
0issues abiertas
npmecosistemas de paquetes

Advertencias de recopilación de datos

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • Could not fetch npm package 'fitglue-server' from its registry
  • Could not fetch go package 'github.com/fitglue/server/src/go' from its registry
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Más detalle

OpenSSF Scorecard 5.3 / 10
5.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-24 21:58 UTC

9Binary-Artifactsbinaries present in source code
5Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests9 out of 9 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
3Code-ReviewFound 9/27 approved changesets -- score normalized to 3
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
0Licenselicense file not detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
n/dPackagingpackaging workflow not detected
1Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 1
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
n/dSigned-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
0Vulnerabilities118 existing vulnerabilities detected
Dependencias directas 24
RegistroPaqueteRestricción de versiónManifiesto
npmts-proto^2.8.3package.json
Gocloud.google.com/go/firestorev1.20.0src/go/go.mod
Gocloud.google.com/go/pubsubv1.50.1src/go/go.mod
Gocloud.google.com/go/storagev1.58.0src/go/go.mod
Gofirebase.google.com/go/v4v4.19.0src/go/go.mod
Gogithub.com/GoogleCloudPlatform/functions-framework-gov1.9.2src/go/go.mod
Gogithub.com/cloudevents/sdk-go/v2v2.16.2src/go/go.mod
Gogithub.com/cucumber/godogv0.15.1src/go/go.mod
Gogithub.com/getsentry/sentry-gov0.27.0src/go/go.mod
Gogithub.com/go-chi/chi/v5v5.2.5src/go/go.mod
Gogithub.com/google/generative-ai-gov0.20.1src/go/go.mod
Gogithub.com/google/uuidv1.6.0src/go/go.mod
Gogithub.com/muktihari/fitv0.26.1src/go/go.mod
Gogithub.com/oapi-codegen/runtimev1.1.2src/go/go.mod
Gogithub.com/stretchr/testifyv1.11.1src/go/go.mod
Gogithub.com/stripe/stripe-go/v76v76.25.0src/go/go.mod
Gogolang.org/x/netv0.50.0src/go/go.mod
Gogolang.org/x/oauth2v0.34.0src/go/go.mod
Gogolang.org/x/textv0.38.0src/go/go.mod
Gogoogle.golang.org/apiv0.262.0src/go/go.mod
Gogoogle.golang.org/genproto/googleapis/apiv0.0.0-20251202230838-ff82c1b0f217src/go/go.mod
Gogoogle.golang.org/grpcv1.78.0src/go/go.mod
Gogoogle.golang.org/protobufv1.36.11src/go/go.mod
Gogopkg.in/yaml.v3v3.0.1src/go/go.mod
Todas las dependencias no recopilado

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

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 44614,
      "has_wiki": false,
      "homepage": "https://fitglue.tech",
      "languages": {
        "Go": 3761914,
        "HCL": 129688,
        "HTML": 55635,
        "Shell": 49987,
        "Python": 19181,
        "Gherkin": 807,
        "Makefile": 7887,
        "Dockerfile": 2311,
        "JavaScript": 10744,
        "TypeScript": 54401
      },
      "pushed_at": "2026-07-23T21:12:44Z",
      "created_at": "2026-01-16T15:55:24Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-23T21:12:48Z",
      "description": "FitGlue is a serverless fitness data aggregation and routing platform built on Google Cloud Platform. It ingests workout data from multiple sources (Hevy, Keiser, Fitbit), enriches it with standardized formats (FIT files), and routes it to connected services like Strava.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": null,
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Ripixel Studio",
      "type": "Organization",
      "login": "Ripixel-Studio",
      "company": null,
      "location": null,
      "followers": 0,
      "avatar_url": "https://avatars.githubusercontent.com/u/302310591?v=4",
      "created_at": "2026-07-10T23:03:40Z",
      "is_verified": null,
      "public_repos": 7,
      "account_age_days": 13
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [
        {
          "tag": "v16.60.2",
          "kind": "patch",
          "published_at": "2026-07-23T21:12:43Z"
        },
        {
          "tag": "v16.60.1",
          "kind": "patch",
          "published_at": "2026-07-22T08:47:11Z"
        },
        {
          "tag": "v16.60.0",
          "kind": "minor",
          "published_at": "2026-07-20T22:34:54Z"
        },
        {
          "tag": "v16.59.8",
          "kind": "patch",
          "published_at": "2026-07-20T13:05:29Z"
        },
        {
          "tag": "v16.59.7",
          "kind": "patch",
          "published_at": "2026-07-20T12:38:17Z"
        },
        {
          "tag": "v16.59.6",
          "kind": "patch",
          "published_at": "2026-07-20T10:25:56Z"
        },
        {
          "tag": "v16.59.5",
          "kind": "patch",
          "published_at": "2026-07-19T15:15:05Z"
        },
        {
          "tag": "v16.59.4",
          "kind": "patch",
          "published_at": "2026-07-18T23:59:13Z"
        },
        {
          "tag": "v16.59.3",
          "kind": "patch",
          "published_at": "2026-07-18T23:20:28Z"
        },
        {
          "tag": "v16.59.2",
          "kind": "patch",
          "published_at": "2026-07-18T14:22:02Z"
        },
        {
          "tag": "v16.59.1",
          "kind": "patch",
          "published_at": "2026-07-03T13:11:21Z"
        },
        {
          "tag": "v16.59.0",
          "kind": "minor",
          "published_at": "2026-07-01T22:04:01Z"
        },
        {
          "tag": "v16.58.1",
          "kind": "patch",
          "published_at": "2026-07-01T18:06:16Z"
        },
        {
          "tag": "v16.58.0",
          "kind": "minor",
          "published_at": "2026-06-22T21:21:58Z"
        },
        {
          "tag": "v16.57.4",
          "kind": "patch",
          "published_at": "2026-06-22T11:56:19Z"
        },
        {
          "tag": "v16.57.3",
          "kind": "patch",
          "published_at": "2026-06-20T16:25:19Z"
        },
        {
          "tag": "v16.57.2",
          "kind": "patch",
          "published_at": "2026-06-20T16:08:09Z"
        },
        {
          "tag": "v16.57.1",
          "kind": "patch",
          "published_at": "2026-06-19T09:32:16Z"
        },
        {
          "tag": "v16.57.0",
          "kind": "minor",
          "published_at": "2026-06-19T02:05:11Z"
        },
        {
          "tag": "v16.56.3",
          "kind": "patch",
          "published_at": "2026-06-19T01:26:25Z"
        },
        {
          "tag": "v16.56.2",
          "kind": "patch",
          "published_at": "2026-06-19T00:15:24Z"
        },
        {
          "tag": "v16.56.1",
          "kind": "patch",
          "published_at": "2026-06-18T20:15:01Z"
        },
        {
          "tag": "v16.56.0",
          "kind": "minor",
          "published_at": "2026-06-17T03:49:21Z"
        },
        {
          "tag": "v16.55.3",
          "kind": "patch",
          "published_at": "2026-06-17T01:22:58Z"
        },
        {
          "tag": "v16.55.2",
          "kind": "patch",
          "published_at": "2026-06-17T01:05:17Z"
        },
        {
          "tag": "v16.55.1",
          "kind": "patch",
          "published_at": "2026-06-17T00:57:02Z"
        },
        {
          "tag": "v16.55.0",
          "kind": "minor",
          "published_at": "2026-06-17T00:21:02Z"
        },
        {
          "tag": "v16.54.0",
          "kind": "minor",
          "published_at": "2026-06-16T23:57:32Z"
        },
        {
          "tag": "v16.53.0",
          "kind": "minor",
          "published_at": "2026-06-16T22:24:53Z"
        },
        {
          "tag": "v16.52.0",
          "kind": "minor",
          "published_at": "2026-06-16T16:12:15Z"
        },
        {
          "tag": "v16.51.0",
          "kind": "minor",
          "published_at": "2026-06-16T14:41:53Z"
        },
        {
          "tag": "v16.50.1",
          "kind": "patch",
          "published_at": "2026-06-16T06:29:47Z"
        },
        {
          "tag": "v16.50.0",
          "kind": "minor",
          "published_at": "2026-06-16T00:04:35Z"
        },
        {
          "tag": "v16.49.0",
          "kind": "minor",
          "published_at": "2026-06-15T23:48:54Z"
        },
        {
          "tag": "v16.48.0",
          "kind": "minor",
          "published_at": "2026-06-15T23:09:36Z"
        },
        {
          "tag": "v16.47.0",
          "kind": "minor",
          "published_at": "2026-06-15T22:28:32Z"
        },
        {
          "tag": "v16.46.0",
          "kind": "minor",
          "published_at": "2026-06-15T20:38:39Z"
        },
        {
          "tag": "v16.45.2",
          "kind": "patch",
          "published_at": "2026-06-15T17:06:11Z"
        },
        {
          "tag": "v16.45.1",
          "kind": "patch",
          "published_at": "2026-06-15T15:53:49Z"
        },
        {
          "tag": "v16.45.0",
          "kind": "minor",
          "published_at": "2026-06-15T10:13:27Z"
        },
        {
          "tag": "v16.44.1",
          "kind": "patch",
          "published_at": "2026-06-15T09:19:58Z"
        },
        {
          "tag": "v16.44.0",
          "kind": "minor",
          "published_at": "2026-06-14T16:03:37Z"
        },
        {
          "tag": "v16.43.2",
          "kind": "patch",
          "published_at": "2026-06-10T09:31:27Z"
        },
        {
          "tag": "v16.43.1",
          "kind": "patch",
          "published_at": "2026-06-10T00:35:53Z"
        },
        {
          "tag": "v16.43.0",
          "kind": "minor",
          "published_at": "2026-06-09T22:23:01Z"
        },
        {
          "tag": "v16.42.0",
          "kind": "minor",
          "published_at": "2026-06-09T21:46:08Z"
        },
        {
          "tag": "v16.41.0",
          "kind": "minor",
          "published_at": "2026-06-09T20:54:29Z"
        },
        {
          "tag": "v16.40.2",
          "kind": "patch",
          "published_at": "2026-06-09T20:29:20Z"
        },
        {
          "tag": "v16.40.1",
          "kind": "patch",
          "published_at": "2026-06-09T15:02:34Z"
        },
        {
          "tag": "v16.40.0",
          "kind": "minor",
          "published_at": "2026-06-09T10:18:24Z"
        },
        {
          "tag": "v16.39.0",
          "kind": "minor",
          "published_at": "2026-06-09T00:30:44Z"
        },
        {
          "tag": "v16.38.0",
          "kind": "minor",
          "published_at": "2026-06-08T22:45:09Z"
        },
        {
          "tag": "v16.37.1",
          "kind": "patch",
          "published_at": "2026-06-08T21:15:34Z"
        },
        {
          "tag": "v16.37.0",
          "kind": "minor",
          "published_at": "2026-06-06T20:24:12Z"
        },
        {
          "tag": "v16.36.1",
          "kind": "patch",
          "published_at": "2026-06-03T20:49:40Z"
        },
        {
          "tag": "v16.36.0",
          "kind": "minor",
          "published_at": "2026-06-03T00:58:12Z"
        },
        {
          "tag": "v16.35.4",
          "kind": "patch",
          "published_at": "2026-06-03T00:37:13Z"
        },
        {
          "tag": "v16.35.3",
          "kind": "patch",
          "published_at": "2026-06-02T23:59:37Z"
        },
        {
          "tag": "v16.35.2",
          "kind": "patch",
          "published_at": "2026-06-02T23:14:52Z"
        },
        {
          "tag": "v16.35.1",
          "kind": "patch",
          "published_at": "2026-06-02T22:13:49Z"
        },
        {
          "tag": "v16.35.0",
          "kind": "minor",
          "published_at": "2026-06-02T21:30:21Z"
        },
        {
          "tag": "v16.34.6",
          "kind": "patch",
          "published_at": "2026-06-02T16:16:58Z"
        },
        {
          "tag": "v16.34.5",
          "kind": "patch",
          "published_at": "2026-06-02T11:57:34Z"
        },
        {
          "tag": "v16.34.4",
          "kind": "patch",
          "published_at": "2026-06-02T08:36:43Z"
        },
        {
          "tag": "v16.34.3",
          "kind": "patch",
          "published_at": "2026-06-02T07:57:29Z"
        },
        {
          "tag": "v16.34.2",
          "kind": "patch",
          "published_at": "2026-06-01T23:44:14Z"
        },
        {
          "tag": "v16.34.1",
          "kind": "patch",
          "published_at": "2026-06-01T22:52:13Z"
        },
        {
          "tag": "v16.34.0",
          "kind": "minor",
          "published_at": "2026-06-01T15:05:28Z"
        },
        {
          "tag": "v16.33.0",
          "kind": "minor",
          "published_at": "2026-06-01T11:41:08Z"
        },
        {
          "tag": "v16.32.2",
          "kind": "patch",
          "published_at": "2026-05-31T20:55:37Z"
        },
        {
          "tag": "v16.32.1",
          "kind": "patch",
          "published_at": "2026-05-31T20:43:20Z"
        },
        {
          "tag": "v16.32.0",
          "kind": "minor",
          "published_at": "2026-05-31T20:24:12Z"
        },
        {
          "tag": "v16.31.0",
          "kind": "minor",
          "published_at": "2026-05-31T17:42:02Z"
        },
        {
          "tag": "v16.30.5",
          "kind": "patch",
          "published_at": "2026-05-31T14:27:27Z"
        },
        {
          "tag": "v16.30.4",
          "kind": "patch",
          "published_at": "2026-05-31T10:50:42Z"
        },
        {
          "tag": "v16.30.3",
          "kind": "patch",
          "published_at": "2026-05-31T10:37:17Z"
        },
        {
          "tag": "v16.30.2",
          "kind": "patch",
          "published_at": "2026-05-31T00:58:07Z"
        },
        {
          "tag": "v16.30.1",
          "kind": "patch",
          "published_at": "2026-05-31T00:31:49Z"
        },
        {
          "tag": "v16.30.0",
          "kind": "minor",
          "published_at": "2026-05-31T00:07:34Z"
        },
        {
          "tag": "v16.29.0",
          "kind": "minor",
          "published_at": "2026-05-30T20:22:41Z"
        },
        {
          "tag": "v16.28.0",
          "kind": "minor",
          "published_at": "2026-05-30T19:56:19Z"
        },
        {
          "tag": "v16.27.0",
          "kind": "minor",
          "published_at": "2026-05-30T15:08:26Z"
        },
        {
          "tag": "v16.26.0",
          "kind": "minor",
          "published_at": "2026-05-29T12:18:12Z"
        },
        {
          "tag": "v16.25.5",
          "kind": "patch",
          "published_at": "2026-05-29T12:04:34Z"
        },
        {
          "tag": "v16.25.4",
          "kind": "patch",
          "published_at": "2026-05-28T23:05:05Z"
        },
        {
          "tag": "v16.25.3",
          "kind": "patch",
          "published_at": "2026-05-28T21:45:42Z"
        },
        {
          "tag": "v16.25.2",
          "kind": "patch",
          "published_at": "2026-05-28T20:21:41Z"
        },
        {
          "tag": "v16.25.1",
          "kind": "patch",
          "published_at": "2026-05-28T19:10:16Z"
        },
        {
          "tag": "v16.25.0",
          "kind": "minor",
          "published_at": "2026-05-28T18:49:22Z"
        },
        {
          "tag": "v16.24.3",
          "kind": "patch",
          "published_at": "2026-05-28T15:46:51Z"
        },
        {
          "tag": "v16.24.2",
          "kind": "patch",
          "published_at": "2026-05-27T20:30:04Z"
        },
        {
          "tag": "v16.24.1",
          "kind": "patch",
          "published_at": "2026-05-27T20:05:33Z"
        },
        {
          "tag": "v16.24.0",
          "kind": "minor",
          "published_at": "2026-05-27T19:38:10Z"
        },
        {
          "tag": "v16.23.9",
          "kind": "patch",
          "published_at": "2026-05-27T18:22:33Z"
        },
        {
          "tag": "v16.23.8",
          "kind": "patch",
          "published_at": "2026-05-27T11:52:44Z"
        },
        {
          "tag": "v16.23.7",
          "kind": "patch",
          "published_at": "2026-05-27T00:17:27Z"
        },
        {
          "tag": "v16.23.6",
          "kind": "patch",
          "published_at": "2026-05-26T22:41:05Z"
        },
        {
          "tag": "v16.23.5",
          "kind": "patch",
          "published_at": "2026-05-26T22:05:38Z"
        },
        {
          "tag": "v16.23.4",
          "kind": "patch",
          "published_at": "2026-05-26T21:43:29Z"
        },
        {
          "tag": "v16.23.3",
          "kind": "patch",
          "published_at": "2026-05-26T19:43:07Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "892db28f78e90f9cf3052b6a3013092b69c45429",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.60.2 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-23T21:12:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e90b6130c3251f540bccb10f894b0883803f604a",
          "body": "…c (#16)\n\nShorten roundup \"Where it happened\" place chips to their leading locality (first comma component) and dedup on that short form, so verbose reverse-geocoded address blocks render concisely.\n\nCo-authored-by: Tom (Jarvis) <jarvis.ripixel@gmail.com>",
          "is_bot": false,
          "headline": "The locations we're displaying for \"Where it happened\" although corre…",
          "author_name": "tom-ripixel",
          "author_login": "tom-ripixel",
          "committed_at": "2026-07-23T20:57:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f6671922098f75fb19ac3e2a112f58b589b70840",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.60.1 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-22T08:47:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "01677f0a397a7d3e173d6bbe0ab02ac418549ce0",
          "body": "… (#15)\n\n* When a GPS-tracked activity happens, we should be able to extract the\n\nNow wire the real geocoder in production (`function.go`):\n\n* Fixed the red CircleCI build by correcting the half-wired automatic-location change (blank→named `location_naming` import and a stale test signature), and added HTTP-path tests to keep coverage above the 75% gate.\n\n---------\n\nCo-authored-by: Tom (Jarvis) <jarvis.ripixel@gmail.com>",
          "is_bot": false,
          "headline": "When a GPS-tracked activity happens, we should be able to extract the…",
          "author_name": "tom-ripixel",
          "author_login": "tom-ripixel",
          "committed_at": "2026-07-22T08:32:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "944e6d00ac18b0a0a5be498f28eb71c2afaacb55",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.60.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-20T22:34:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "55603990f6b57b2bd90e7a607362acd71eae71c1",
          "body": "* feat(firestore): persist pending-input source display metadata\n\nRound-trip SourceDisplayName, SourceActivityType, SourceStartTime and SourceActivitySource through the Firestore PendingInput converter, so the web can show which activity a pending input relates to (title/type/when/source) rather tha\n[…]\nde Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Tom <tom@ripixel.studio>\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>\nCo-authored-by: Jay (Jarvis) <jarvis.ripixel@gmail.com>",
          "is_bot": false,
          "headline": "feat(firestore): persist pending-input source display metadata (#14)",
          "author_name": "tom-ripixel",
          "author_login": "tom-ripixel",
          "committed_at": "2026-07-20T22:21:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d24cdc3f73d8349022bcf7b28002d31a9e2fe83d",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.59.8 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-20T13:05:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c48c86af187357dc1aa535d86d538f75927395a4",
          "body": "…p (#13)\n\nAdded an observe-mode `renovate.json` to fitglue-server that labels blast-radius-SAFE updates (devDep patch/minor + GitHub Actions patch/digest) as `automerge-candidate` with a 3-day release-age hold while keeping all auto-merge off, and explicitly marks all runtime deps and majors `needs-human`, so auto-merge can later be enabled with a one-token edit.\n\nCo-authored-by: Tom (Jarvis) <jarvis.ripixel@gmail.com>",
          "is_bot": false,
          "headline": "```Add a renovate json to fitglue-server that classifies dependency u…",
          "author_name": "tom-ripixel",
          "author_login": "tom-ripixel",
          "committed_at": "2026-07-20T12:59:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b343856b8fa20b8a7dd831669747709279753f6f",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.59.7 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-20T12:38:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e8d0b48ae8e61d94be1a07a0a429e425d9f0e739",
          "body": "…e (#12)\n\nAdded a GitHub Actions PR gate (`.github/workflows/ci.yml`, job `build-lint-test`) that mirrors CircleCI's build/lint/test on the Go monorepo, installing from the lockfile and triggering on PRs to main.\n\nCo-authored-by: Tom (Jarvis) <jarvis.ripixel@gmail.com>",
          "is_bot": false,
          "headline": "```Add a GitHub Actions CI workflow to fitglue-server that runs on ev…",
          "author_name": "tom-ripixel",
          "author_login": "tom-ripixel",
          "committed_at": "2026-07-20T12:31:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "87eb9cd157832b702bbbb8427c9ec7ff83f4ce74",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.59.6 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-20T10:25:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dfa590b18935278c51ed66a85b4462300ed8d705",
          "body": "* The iCal title enricher is broken (server)\n\nAPI Error: 529 Overloaded. This is a server-side issue, usually temporary — try again in a moment. If it persists, check https://status.claude.com.\n\n* Fixed the iCal title enricher raising false \"calendar clash\" skips by suppressing a recurring event's original occurrence when a RECURRENCE-ID override (an edited single instance) replaces it.\n\n---------\n\nCo-authored-by: Tom (Jarvis) <jarvis.ripixel@gmail.com>",
          "is_bot": false,
          "headline": "The iCal title enricher is broken (server) (#11)",
          "author_name": "tom-ripixel",
          "author_login": "tom-ripixel",
          "committed_at": "2026-07-20T10:11:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "006a943cebb10f03668c29d8ebf2e3286fa8b068",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.59.5 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-19T15:15:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8a94ddffb035e48ab0f3cebead72af48e935ce15",
          "body": "…ty-to-show\n\nWe added functionality to show pending inputs related to a pipeline run on the pipeline run detail page, but I think if there are multiple then when we submit one, the others lose their reference somehow? Fix this.",
          "is_bot": false,
          "headline": "Merge pull request #10 from Ripixel-Studio/tom/9-we-added-functionali…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-19T15:00:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae9976d2090383ece13d4a910f51f81038b03915",
          "body": "Fixed resolving one of multiple pending inputs orphaning the others by having SubmitInput fall back to the linked activity ID so a non-blocking input's resume reuses the original pipeline run instead of spawning a duplicate.\n\nCloses #9",
          "is_bot": false,
          "headline": "We added functionality to show pending inputs related to a pipeline ru",
          "author_name": "Tom (Jarvis)",
          "author_login": null,
          "committed_at": "2026-07-19T00:08:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5aa2e527311bf271bda9a927708780799b88cd99",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.59.4 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-18T23:59:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "07a63d41628fce93f9090605c4c79bbb2427fe3f",
          "body": "Make sure that when we \"Skip\" a non-blocking pending input, that it does not trigger the pipeline to run. It was non-blocking, so skipping it should be a no-op and the pipeline not run. It is still occuring no matter previous commits or deployments.",
          "is_bot": false,
          "headline": "Merge pull request #8 from Ripixel-Studio/tom/7-make-sure-that-when-we",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-18T23:44:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f6eadbaaa8082d6513c708e19807bf1e88c1e4aa",
          "body": "Persist the `non_blocking` flag on pending inputs in the Firestore converters so that skipping a non-blocking pending input no longer re-runs the pipeline.\n\nCloses #7",
          "is_bot": false,
          "headline": "Make sure that when we \"Skip\" a non-blocking pending input, that it do",
          "author_name": "Tom (Jarvis)",
          "author_login": null,
          "committed_at": "2026-07-18T23:42:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "445739b6a0b44362038903328cbe0412733f2120",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.59.3 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-18T23:20:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "703f7cf210e5c0769428554aa5b4da4fc213f131",
          "body": "…ided\n\nHang on - the user-provided description from when they uploaded the activity will never have a heading though and never should. Wrapping in start and end markers seems a very blunt solution.\n\nCan't we replace over what's there without losing the user",
          "is_bot": false,
          "headline": "Merge pull request #6 from Ripixel-Studio/tom/5-hang-on-the-user-prov…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-18T23:05:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0f59df9c1307813fd50cf4f55c62c79cec39c1eb",
          "body": "Cross-source description merge now replaces over the existing user text when the payload already contains it, instead of appending a duplicate copy — no markers needed.\n\nCloses #5",
          "is_bot": false,
          "headline": "Hang on - the user-provided description from when they uploaded the ac",
          "author_name": "Tom (Jarvis)",
          "author_login": null,
          "committed_at": "2026-07-18T23:01:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "878524caf81fa3d355f149994e5f17a0c042372e",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.59.2 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-18T14:22:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0c7ce40873571482888f7d4f99e9fd239f0115a6",
          "body": "…lue-web project\n\nThe GitHub org (and this repo along with the web repo) moved from FitGlue to\nRipixel-Studio, with the web repo also renamed web -> fitglue-web. The\ncreate-release job's \"Trigger Web Rebuild\" step still posted to the old\ngithub/FitGlue/web CircleCI project, which no longer exists un\n[…]\nGlue CircleCI org id to the new Ripixel-Studio org id, since OIDC tokens\nminted by CI now carry the new org's identity and were being rejected.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ci): point web-rebuild trigger at the renamed Ripixel-Studio/fitg…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-18T13:46:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8fd144746619bc9e2460e4b6d14d3532fe9a3c8e",
          "body": "…7 days\n\nShowcase activity JSON and FIT files were referenced from the ephemeral\npipeline artifacts bucket (payloads/, activities/*.fit), which has a 7-day\nlifecycle delete rule meant for short-lived execution records. Since\nShowcase pages are permanent and public, their backing blob would vanish\naf\n[…]\nhat same durable bucket instead of the ephemeral one.\nMissing-blob fetch failures are now logged at Error so this can't silently\nregress again.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(showcase): stop public showcases from losing activity data after …",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-17T14:42:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "99ae659a47b769829dcd048c68b58c48dee28966",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.59.1 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-03T13:11:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f67bf2515728791774296f61d17bce0f8018f40a",
          "body": "Strava, Intervals, TrainingPeaks and Hevy each reimplemented the same\ncross-source description merge: replace a matching section if one is\nconfigured, otherwise blindly append the whole payload description.\nMost enrichers (e.g. branding's \"Posted via FitGlue\" footer) don't\ndeclare a section header, \n[…]\nin \"Posted by\nFitGlue\".\n\nCentralize the merge logic into description.MergeDescription() and\nskip the append when the payload description is already present\nverbatim in the existing remote description.",
          "is_bot": false,
          "headline": "fix(destination): don't duplicate description on repeated Update() calls",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-03T12:53:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c48a5128e371e831d57d0ae9b9f1611bdf8ba34a",
          "body": "Resolving any pending input republishes the pipeline from the clean\npre-enrichment payload, so fitbit-heart-rate always re-ran and re-queried\nFitbit on every resume — even when a prior run already fetched the\ncorrect, complete stream. If that re-fetch raced Fitbit's own sync lag and\nexhausted retrie\n[…]\nay journal (previously only for name/tags/description/\nenrichments) to also persist and replay the heart rate stream, so a\nresume reuses the already-fetched data instead of re-querying the\nsource API.",
          "is_bot": false,
          "headline": "fix(pipeline): replay heart rate stream on resume instead of re-fetching",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-03T12:53:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dcb87267c3a534af9fa8767faf690055cb0f33a5",
          "body": "The re-run notification suppression relied on a stale isUpdate flag that\nwas only set for non-blocking pending-input resumes, missing same-source-\ndestination updates, blocking-resume refreshes of already-succeeded\ndestinations, and targeted reposts. Those cases re-sent the full \"Activity\nSynced\" no\n[…]\nication instead of being suppressed. Now derives suppression\ndirectly from whether the destination already had a SUCCESS outcome, and\nsends a lighter \"Activity Updated\" notice instead of full silence.",
          "is_bot": false,
          "headline": "fix(destination): correctly suppress/lighten notifications on re-runs",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-03T12:40:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8e575ae2a848895e145ac6435e339ebf0d30d738",
          "body": "…created_at\n\nAdminListPipelineRuns runs an unfiltered CollectionGroup(\"pipeline_runs\")\n.OrderBy(\"created_at\", Desc) query when no status/source filter is given.\nFirestore's automatic single-field indexes only cover COLLECTION scope, not\nCOLLECTION_GROUP, so this query has been failing with FailedPre\n[…]\nA prior\ncomment incorrectly assumed collection-group single-field indexes weren't\nneeded; corrected that assumption in both places it appeared.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(firestore): add missing collection-group index for pipeline_runs.…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-03T12:40:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ecf03e97ee3a18555fde4296d0c2e0704eb32a2b",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.59.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-01T22:04:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e8d3097273235806a0cad4ac648d210a8cb1700c",
          "body": "The showcase profile page's roundup band only ever fetched a fixed\nrecent-N via `limit`, so there was no way to page through older\nroundups. Replace `limit` with `page` on GetRecentPublicRoundups,\nreturning `total_pages`/`current_page` — mirroring the existing\nGetPublicShowcaseProfile activity-feed \n[…]\nups now paginates in-memory over the\n  full list with a fixed page size of 12, matching the profile entries\n  pagination approach.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(activity): add real pagination to recent public roundups",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-01T21:47:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "69069c556e672f52cb817d718c9b7169caffd46a",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.58.1 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-07-01T18:06:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aced70780f39af79adfbc3b20ad1952c1466e791",
          "body": "Recent roundups on the showcase profile were ordered by period_start,\nwhich produces a confusing order when week/month/year roundups are mixed\n(a year roundup starts Jan 1 but covers through Dec 31, yet sorted below a\nDecember week). Order by period_end descending instead, so the roundup\ncovering the most recent dates surfaces first.\n\nUpdate the Firestore composite index (slug ASC, period_end DESC) to match.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(roundups): order showcase roundups by last date covered",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-07-01T17:45:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3d67adfefc8e510f85955ece4b65211f77746c17",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.58.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-22T21:21:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b04ef3911261c4ef1357bc9e8ece89b4e4545103",
          "body": null,
          "is_bot": false,
          "headline": "feat(cors): add public CORS middleware for unauthenticated API access",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-22T21:13:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "73253a5b09c6e74cdb153be86d09920a3e676258",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.57.4 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-22T11:56:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c086ebbfea5b91e1b2185002a601a211c714328d",
          "body": "hDrop includes a sentence like \"Here is your individual activity data:\"\nbefore the opening brace. Strip everything before the first '{' so users\ncan paste the raw export without editing it first.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(hdrop): strip leading prose before JSON object in export",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-22T11:40:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ac48ef2856f7cb68c6afb63704a08f2fff1b52b1",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.57.3 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-20T16:25:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de2a320af0368b0d96d8cdfaf906f6abcfd244f0",
          "body": "…ate related logic",
          "is_bot": false,
          "headline": "refactor(pipeline): remove unused resume_only_enrichers field and upd…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-20T16:10:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c73592ce351893d467fd4c289901850b43d1c098",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.57.2 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-20T16:08:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "486a284c95c12fa32e332641bb36b4d426b9c325",
          "body": "Activities whose exercises map to no recognized muscle group (e.g.\nPilates) previously emitted the \"🔥 Muscle Heatmap:\" header with an\nempty body. Return an empty result in that case so the header-only\nblock is left out of the activity description.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(muscle-heatmap): skip section when no muscle groups have volume",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-20T15:52:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "891cb5505c4d2e5cf004ea951474ca019fe1832c",
          "body": "Strava (and other sources) deliver an entire run as a single lap, which\nhit calculateSplitsFromLaps' \">1100m\" branch and assigned the overall\naverage pace to every kilometre — so the Pace card showed e.g. 4:55/km\nfor all 10 splits. \"Best split\" was also taken from the fastest\ninstantaneous GPS speed\n[…]\ning splits. Lap division remains a fallback\nfor treadmill/structured workouts with no GPS stream. Best split is now the\nfastest real kilometre.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(pace-summary): derive real per-km splits from record stream",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-20T15:51:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "613515c68f518dccc2c8796cad5f7fc2930c735f",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.57.1 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-19T09:32:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3447aba653d9bcd6de03de270eb317e763298e8a",
          "body": "… pipeline config endpoints\n\nThree admin gaps reported from the console:\n\n- Pipeline runs had no user_id, so run-ops (repost/cancel/resolve) were disabled.\n  PipelineRun gains a user_id field; the cross-user admin listing derives it from\n  the run document's owning user (grandparent of the collectio\n[…]\n to the pipeline\n  service for any user; mutations audited).\n\nRegenerated gateway + client types. Tests cover the new handlers; coverage green.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(admin): populate run user_id, resolve identity from Firebase, add…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-19T09:16:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "37e06f611e264f17a1a2f0ade7679d72f87f9cbd",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.57.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-19T02:05:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1aa50f24b829be7f0489ea29d7ba965733a18e20",
          "body": "… and audit\n\nGrow the admin REST contract from a read-only list viewer into a full support\nsurface. New/changed RPCs on AdminGatewayService:\n\n- GetUser now returns an aggregated AdminUserDetail (profile + redacted\n  integration summaries + pipeline summaries + activity/run counts + pending\n  inputs \n[…]\ngateway types + OpenAPI spec. Unit tests cover the new handlers,\nRBAC guards, aggregation helpers and audit serialisation; coverage gate green.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(admin): expand admin gateway with 360° user detail, ops, billing…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-19T01:43:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "484d7e60249e4f5588c0a783b31109bd9276f492",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.56.3 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-19T01:26:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7f766009337a565460fc491295cc7c597cf87a33",
          "body": "… listing\n\nPlatform stats read user docs with the wrong field names/enum values\n(camelCase + \"ATHLETE\" short string) so Athletes, Syncs and the recent-\nexecutions block always reported zero. Read snake_case fields, match the\nfull UserTier enum name (tolerating legacy forms), compare created_at as an\n[…]\neys,\nand skip undecodable documents with a warning instead of failing the request.\nAccept camelCase query params from the generated client too.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(admin): correct platform stats and harden cross-user pipeline-run…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-19T01:11:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cf46ea3f1953236dfd190d02b9b563be68f3b3c3",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.56.2 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-19T00:15:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0a2cf79481d042dad96ad3254440aff5c88cd4f9",
          "body": "…uscle, auto-increment)",
          "is_bot": false,
          "headline": "test(server): cover pure enricher providers (pace, HR, hybrid race, m…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T23:58:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6bdee39ce68eb195a7eb942598754c79b1e32d95",
          "body": "…vy create/update validation",
          "is_bot": false,
          "headline": "test(server): cover sourceplugins HTTP paths, api-public handlers, he…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T23:47:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba39d86e2fd8588ce550a0d777cca3f63b347f1e",
          "body": "…verage\n\ninternal/pipeline/enricher 66->83%, internal/pipeline 52->77%, internal/activity\n75->79%, api-public server 55->94%, plus oauth/personal_records/parkrun round 2.\nOverall 70.4% -> 74.2%.",
          "is_bot": false,
          "headline": "test(server): deepen pipeline/orchestrator/activity and api-public co…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T23:44:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b3efc4bd372bbf16e3a1f91ad1d980ab6ea09073",
          "body": "…th, webhook sources\n\ninternal/activity 39->75%, internal/pipeline/enricher 51->66%, internal/pipeline\n43->52%, oauth 25->49%, plus webhook source FetchActivity/parse paths.\nOverall 65.1% -> 70.4%.",
          "is_bot": false,
          "headline": "test(server): cover activity service RPCs, pipeline orchestrator, oau…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T22:45:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "87022f15ac54b0a8833e32b1fae25d55cec81bcb",
          "body": "…nfra\n\nAdds tests (test files only, no production changes) raising coverage in:\n- pkg/storage/firestore converters (~93%), pkg/domain/file_generators (~98%),\n  fit_parser (~85%), pkg/parkrun (~83%)\n- services/api-client (~80%), api-admin (~76%), destination executor (~79%),\n  destination uploaders, \n[…]\n distance_milestones,\n  goal_tracker, muscle_heatmap_image, location_naming, parkrun, ai_banner)\n\nOverall hand-written coverage 47.8% -> 65.1%.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(server): broad unit-test coverage across services, domain, and i…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:22:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2d35b8e8d50e0c246064c30a12fd6366bf87880a",
          "body": "…ty stores\n\ncheck-coverage.sh now excludes main.go entrypoints from the percentage too (not\njust the per-file floor), keeping the metric focused on unit-testable logic.\nAdds dead-Firestore smoke coverage across all internal/activity store methods.",
          "is_bot": false,
          "headline": "test(server): exclude main.go from coverage metric; smoke-test activi…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:08:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c31d6382a7ab40c73c6a4f7471b520ff420cdebb",
          "body": "…, mocks\n\nClears the remaining 0%-coverage files: photo_upload scaleToMax + skip paths,\nParkrunChecker constructor/handler, FCM empty-token early return, activity GCS\nblob delegation, and the shared test mock implementations.",
          "is_bot": false,
          "headline": "test(server): cover photo_upload, parkrun checker, fcm, activity blob…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:05:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "787ae6de2ca101df158d53015203bc6a53664fb0",
          "body": "… intervals source\n\nAdds coverage for the Sentry handler/capture helpers, the typed Firestore\ncollection accessors, SMTP/PubSub/database/billing/pipeline store constructors\nand error paths, the GCS blob URI validation, and the Intervals webhook parser.",
          "is_bot": false,
          "headline": "test(server): cover sentry, storage/firestore, infra clients, webhook…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:05:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "135e5a86a3f5c1a10f9647869471f4ab1df12a09",
          "body": "…oader",
          "is_bot": false,
          "headline": "test(server): cover strava webhook parser, intervals client, mock upl…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:05:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ce104000a4eb3765569231e13360f40a59a1870a",
          "body": "…mock uploader\n\n- internal/infra: logger, GCP handler options, component handler, gRPC logging\n  interceptor, HTTP logging middleware, GRPCDial, InitSentry.\n- pkg/infrastructure/oauth: Transport 401-retry/token-error paths, error-logging\n  transport, client constructor.\n- pkg/notificationpub: Enqueue publish + error.\n- destination mock uploader: Create/Update/Name.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(server): cover infra logging, oauth transport, notificationpub, …",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:05:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5287b0e52624762aa7a0b6924277dac1a400b757",
          "body": "…dlers\n\nMockable gRPC paths for AdminListPipelineRuns and user-data deletion, plus\nFirestore error-path coverage for stats and activity deletion via an\nunreachable emulator client.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(server): cover api-admin pipeline-runs, user-data, and stats han…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:05:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e6b719c23f9d7de734bda223fb11791131878e75",
          "body": "…plugins\n\n- pkg/domain/email: full coverage of layout + all notification templates.\n- pkg/domain/apikey: ingress key generation + hashing.\n- pkg/framework: TerminalError.\n- services/api-public: WriteJSON/WriteError gRPC-code mapping.\n- pkg/sourceplugins: registry lookup + not-configured error paths for all providers.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(server): cover email templates, apikey, framework errors, source…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:05:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2c3551922691e30c65d0914672b1a478f22ee72e",
          "body": "- api-client server: exercise library, showcase view stats, repost, FCM token,\n  activity stats handlers + NewAPIServer wiring; Firestore store constructors.\n- internal/activity: roundup period key/bounds, period-key parsing, export-job\n  map round-trip, toInt64, FIT-parse validation, export-trigger request parsing.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(server): cover api-client handlers and internal/activity pure logic",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:05:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fa59f5e5a978bfc7765e1064f220dae6189eb0cf",
          "body": "…vy tests\n\n- check-coverage.sh now strips generated (DO NOT EDIT) files from the metric,\n  raises the threshold to 75%, and adds a per-file floor (every hand-written\n  file except main.go entrypoints must have some coverage).\n- Add unit tests for distanceeffort, best_efforts, temperature_summary,\n  ai_activity_type, manual_workout_entry, mock, the providers registry/errors,\n  and the Hevy uploader mapper + template resolver.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(server): exclude generated code from coverage; add enricher + he…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T21:05:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d2bcc510ff4354f822bd467bff58921ada30d364",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.56.1 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-18T20:15:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a7824044e2d4250e64aec6955eaea2eb5137606f",
          "body": "…ents and replay key stripping",
          "is_bot": false,
          "headline": "test(enricher): add tests for non-idempotent provider's typed enrichm…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T20:00:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "514e1f4432b35597364a361e92dfc9f1842fdf68",
          "body": "…resume",
          "is_bot": false,
          "headline": "fix(enricher): restore and persist typed enrichments during pipeline …",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T19:58:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a781c5b9284f01dd1ea9b73be0edcd78ee840a10",
          "body": "A retry-destination / missed-destination Magic Action reuses the original\npipeline run. The executor's idempotency guard skips any destination that\nalready has a SUCCESS outcome on that run (\"Skipping already-uploaded\ndestination\"), so the targeted repost was a silent no-op: no new upload was\nmade a\n[…]\nFunc hook to the shared MockDatabase and a\nregression test asserting the guard skips a normal redelivery but is bypassed\nfor a targeted repost.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(destination): let targeted reposts bypass the already-uploaded guard",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T19:55:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cbf99a85814e63a64c8c1d8f7320b88bc589f69b",
          "body": "… failures\n\nTwo-layer fix:\n\n1. Code: non-retryable orchestrator errors now wrap in framework.TerminalError\n   so the CloudEvents wrapper ACKs the message instead of NACKing. The pipeline\n   run is already marked FAILED in Firestore — retrying is pointless and causes\n   the endless re-run behaviour s\n[…]\nletter) as a safety net for any error type that\n   slips past the code-level terminal handling. Also raise minimum_backoff\n   from 10s → 30s.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(pipeline): prevent infinite Pub/Sub retries on permanent enricher…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T19:42:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "32075e3bf33bc0d7ce38253226cd9e23c3759770",
          "body": "The router wrote updated_at via protojson.Format(timestamppb.Now()), which\nyields a quote-wrapped JSON string (\"2026-...Z\"). Firestore persisted that\nstring verbatim, and it then failed to decode back into the PipelineRun proto\n(\"invalid google.protobuf.Timestamp value\"). Any reader using decodeProt\n[…]\ncorrupt string as the final\nstate. Write timestamppb.Now() directly so the Firestore client stores a\nnative timestamp that round-trips cleanly.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(pipeline): store pipeline-run updated_at as a proto Timestamp",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T19:34:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b88ff4286087e7615d012ee8db4af780084f4a2b",
          "body": "Skipping a non-blocking pending input routed through SubmitInput, which\nrepublished the resume event and re-ran the whole pipeline. Non-blocking\ninputs never pause the pipeline, so destinations already ran on the first\npass — a data-less skip only triggered a no-op Update to every destination.\n\nShor\n[…]\ns with no input data: mark\nthe input complete and return without republishing. Blocking inputs still\nresume so the activity can finish syncing.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(pipeline): skip pipeline re-run when dismissing non-blocking input",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T19:33:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6e794828b8917a7a4f48f8c9195faa8a33ebab5d",
          "body": "Real hDrop exports have sweatRate and sodiumConcentration as JSON\nstrings, and timeseries sweatRate/fluidLoss as null during warm-up.\nFixes parse failure with: cannot unmarshal string into Go struct field\n.metadata.sweatRate of type float64.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(hdrop): handle string numeric fields and null timeseries values",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-18T19:20:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c2bf7e17c115d9def74e67ac7b46657a01aa1541",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.56.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-17T03:49:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "af80a28d41adb64c8b448f1e22d64ecb33e9705b",
          "body": "Adds a new \"location-pinner\" enricher that matches an activity by a title\nkeyword and attaches a real-world location for GPS-less workouts (gym\nclasses, home sessions). The pinned point is carried on a new transient\nStandardizedActivity.hint_location field — NOT written to records — so it\nfeeds the \n[…]\nn present\n- never overrides real GPS or an earlier enricher's location (force flag to override)\n- registry manifest entry + provider unit tests\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(enricher): add location-pinner to map titles to real places",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-17T03:28:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f0653f4896686392d7a6fae509aec164cfb68745",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.55.3 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-17T01:22:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "24dc6957048256150bde1c9a0738c345bb433285",
          "body": "…generation",
          "is_bot": false,
          "headline": "fix(roundup-ai): increase timeout and output token limit for summary …",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-17T01:09:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "adf96d66d8cc6fee6968ef6214a8945e52215491",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.55.2 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-17T01:05:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4407fd7d1982f67783a008be03122cde08af9ec1",
          "body": "Roundups show empty Best Efforts / Muscles / Places / Weather and zero\nElevation for any period whose showcase_profile_entry docs were created before\nthe enrichment-summary projection landed (commit f1cf530, 2026-06-16). Those\nfields are only projected at showcase time, so older entries lack them an\n[…]\ntion_name,\ncountry, temp_c, weather_description and elevation_gain_m back onto the entry.\nRoundups must then be recomputed to pick the data up.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(showcase): backfill enrichment summaries onto pre-existing entries",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-17T00:58:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2aae946679285d540253c9eb48be957b372d4df6",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.55.1 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-17T00:57:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "654714ebcf4ba76d417ab0494093cb9abf38039f",
          "body": "…nput resumes\n\nResolving two pending inputs at once created two Strava activities. Each\nresume published a fresh event that minted a new pipeline_execution_id, so\nthe per-execution idempotency guards couldn't see their sibling and both\nran Create.\n\nTwo-layer fix:\n\n- Resume now reuses the original pi\n[…]\ntinationCreate/ReleaseDestinationCreate to the Database\ninterface (Firestore impl + mocks) and wires the guard into the executor's\nCreate path.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(destination): prevent duplicate creates from concurrent pending-i…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-17T00:41:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "34b80b7c9e2d60071984e484dfd39f7cfcb29340",
          "body": "…y on resume\n\nPartial Fitbit HR pulls were being stretched to fill the whole session:\n\n- GPS path: the elastic alignment mapped each GPS point to a *relative*\n  position in the HR timeline, so a partial pull (e.g. first 20 min of a\n  60 min ride) was stretched across the entire track. Switch to abso\n[…]\nicher config and the enricher re-arms the data-lag retry on resume,\ngiving Fitbit time to finish syncing before committing to partial coverage.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(fitbit-hr): anchor HR to GPS by absolute time and re-arm lag retr…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-17T00:41:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "acb9579cdd48f3e4c3f05f4dbfa0276d5c439396",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.55.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-17T00:21:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "551f87f6458568257b7e49760fc211bdd41132ea",
          "body": "Tracks the showcase_id of the activity behind each \"ceiling raised\"\nhighlight — longest session, highest burn rate, peak avg HR, furthest,\nmost calories and heaviest volume — so the front-end can link each peak\nstraight to the session that set it. computeSessionPeaks now returns the\nsource ids alongside the values.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(roundup): record source session for each single-session peak",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-17T00:05:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1aaee3577cfcf3800bac43815ff657a8a478100c",
          "body": "…list\n\nA single pipeline_run with a malformed timestamp caused ListPipelineRuns to\nabort the entire page, which crashed the whole-account export worker (job\nmarked FAILED, UI showed an error). Skip records that fail to decode so one\ncorrupt row no longer breaks exports or activity listings.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(activity): skip undecodable pipeline runs instead of failing the …",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-17T00:05:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cdb653c6446d169662d099f16e12d989838d8165",
          "body": "The \"records broken\" callout linked to the first entry on the peak-PR\n*day* — wrong when that day had multiple sessions — and its \"in one\nsession\" count was actually per-day. Now PRs are attributed to the\nsession whose time window contains each record; the callout reports and\nlinks the session that set the most. When timestamps can't disambiguate,\nit degrades to the period aggregate with no link rather than a wrong one.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(roundup): attribute PR callout to the right session, not the day",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T23:57:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "571cbc15895cd15ad61766e6b8f8fa6e39968d03",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.54.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-16T23:57:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "afd17e3cf7d3b0e00c1771310f93e04a6ed58c91",
          "body": "Adds showcase_id to RoundupPhoto and RoundupRoute, populated in\ncollectRoundupMedia from the source entry, so the photo mosaic and route\nwall can link each item through to its activity.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(roundup): carry showcase_id on wall photos and routes",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T23:41:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7b6c62439f289d865d6bdf285902ab65a6f3f953",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.53.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-16T22:24:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b70cc7c18e52364843e972a4bb9c90b1326381eb",
          "body": "- Implemented ExportData RPC to enqueue asynchronous whole-account GDPR export jobs.\n- Added GetExportJob RPC to retrieve the current state of an export job.\n- Introduced ExportPipelineRun RPC for synchronous per-run ZIP generation.\n- Created Pub/Sub topic and subscription for handling data export t\n[…]\negration for managing export job records.\n- Updated API routes and client methods to support new export functionalities.\n- Enhanced notification system to inform users when their data export is ready.",
          "is_bot": false,
          "headline": "feat(activity): add data export functionality with job management",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T22:09:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a397220889d9c3615edb5b4f051c2f52772377dc",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.52.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-16T16:12:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a276786244f504e2ef4d590bd0596ea2476bca99",
          "body": "- Introduced GetShowcaseRoundupViewStats method in ClientGatewayService.\n- Updated ClientGatewayServiceClient and ClientGatewayServiceServer interfaces.\n- Implemented handler for GetShowcaseRoundupViewStats in APIServer.\n- Added ShowcaseId field to ShowcaseCalloutActivity for mapping to source showc\n[…]\nodified ListShowcaseViewStatsResponse to include roundups.\n- Updated API routes and protobuf definitions accordingly.\n- Adjusted Terraform configuration for environment variables related to enrichers.",
          "is_bot": false,
          "headline": "feat: add GetShowcaseRoundupViewStats RPC and related functionality",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T15:56:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b745d24d34a5721f33353245b54078bf1112765f",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.51.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-16T14:41:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1f42c5f622184856f016c667f8c5f0fb1b531c74",
          "body": "Adds owner-facing view/visitor analytics for public showcase surfaces\n(activity pages, profile, roundups) without storing raw IPs.\n\n- proto: RecordShowcaseView, GetShowcaseViewStats, ListShowcaseViewStats on\n  ActivityService; public fire-and-forget beacons on PublicGatewayService;\n  ShowcaseViewSta\n[…]\niew-salt secret, showcase_view_dedup TTL field,\n  api-public secret accessor + VIEW_SALT_SECRET env\n- regenerated pb.go stubs and OpenAPI specs\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(showcase): add privacy-preserving view & visitor metrics",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T14:21:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a9a0c754f311572ac3ecfa7b88b44ce2da623218",
          "body": "…nput updates\n\nResolving a non-blocking pending input triggers an update post to destinations.\nPreviously each resolution re-sent a PIPELINE_SUCCESS notification even though\nthe user was already notified at the initial sync. Thread a nonBlockingUpdate\nflag through UpdateStatus and suppress the succe\n[…]\non-blocking input remains (already prompted via PENDING_INPUT), so it should be\na \"Activity Synced\" notification, not a \"Partial Sync\" failure.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(destination): stop duplicate sync notifications on non-blocking i…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T14:21:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4f93f9514875d1a36c45bf39b78b05c091351283",
          "body": "…er doc is empty\n\nEmail notifications never sent because the notification service read the\nrecipient from users/{uid}.email, but that field is only ever written empty\nat creation (EmitUnpopulated) and never populated — profile.Email is set only\nin-memory in the admin ListUsers path. dispatchEmail th\n[…]\n active, to avoid an Auth\nround-trip on the common push-only path. Fixes all existing users with no\nbackfill. Adds unit tests for resolveEmail.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(notification): resolve recipient email from Firebase Auth when us…",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T14:17:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "962f8a94254ea2d8d4c23bb3de4a5de468e52888",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(roundup): mark Phase 5 polish (reel + 3D tilt) complete",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T14:01:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "313c87420e6b60f178911c44ec7ee0538bd9f1e9",
          "body": "The mobile app's notification handler navigates its embedded web view to\ndata[\"path\"], but the notification service never populated it, so push\nnotifications didn't deep-link on mobile at all.\n\nCompute an SPA-relative path (no /app prefix) per notification type in the\npush dispatch — pending input a\n[…]\ntivity/run detail page, connection actions to the connection, etc. Web\nclients are unaffected (they derive their own target from data[\"type\"]).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(notifications): emit deep-link path for mobile push navigation",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T13:48:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cc5b96df1d4567461b77373e7a7bbc80d1fbdbde",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.50.1 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-16T06:29:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7bed69f397ac6c7e1e68f9bee0c27b7743afa812",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(roundup): mark Phase 8 shareables v2 complete",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-16T06:20:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "658513e2393e200bccc6fc8d16e430c4ce5911bb",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 16.50.0 [skip ci]",
          "author_name": "CircleCI Bot",
          "author_login": null,
          "committed_at": "2026-06-16T00:04:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f1cf530034ca5aa3c9647c9c8dd9c1af281c078f",
          "body": "Projects enrichment summaries onto each ShowcaseProfileEntry at creation\ntime (AddShowcaseEntry, from the GCS-hydrated ActivityEnrichments):\nelevation gain, location/country, weather, best efforts and primary\nmuscles (entry fields 21-27).\n\ngenerateRoundup then aggregates them into ShowcaseRoundup:\n-\n[…]\nes worked, by frequency\n\nData accrues forward — only activities synced after this ships carry the\nprojected summaries (no historical backfill).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(roundup): aggregate enrichment data for new roundup sections",
          "author_name": "James King",
          "author_login": "ripixel",
          "committed_at": "2026-06-15T23:49:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 100,
      "commits_last_year": 1250,
      "latest_release_at": "2026-07-23T21:12:43Z",
      "latest_release_tag": "v16.60.2",
      "releases_from_tags": true,
      "days_since_last_push": 1,
      "active_weeks_last_year": 27,
      "days_since_latest_release": 1,
      "mean_days_between_releases": 0.6
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 37,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": []
    },
    "popularity": {
      "forks": 0,
      "stars": 1,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [
        "src/openapi/fitbit/swagger.json",
        "src/openapi/github/swagger.json",
        "src/openapi/hevy/swagger.json",
        "src/openapi/oura/swagger.json",
        "src/openapi/polar/swagger.json",
        "src/openapi/spotify/swagger.json",
        "src/openapi/strava/swagger.json",
        "src/openapi/trainingpeaks/swagger.json",
        "src/openapi/wahoo/swagger.json",
        "src/proto/gateway/admin.proto",
        "src/proto/gateway/client.proto",
        "src/proto/gateway/public.proto",
        "src/proto/gateway/webhook.proto",
        "src/proto/google/api/annotations.proto",
        "src/proto/google/api/http.proto",
        "src/proto/models/activity/enrichments.proto",
        "src/proto/models/activity/roundup.proto",
        "src/proto/models/activity/source.proto",
        "src/proto/models/activity/standardized.proto",
        "src/proto/models/activity/uploaded.proto",
        "src/proto/models/events/pipeline.proto",
        "src/proto/models/notification/notification.proto",
        "src/proto/models/pipeline/config.proto",
        "src/proto/models/pipeline/execution.proto",
        "src/proto/models/pipeline/pending_input.proto",
        "src/proto/models/plugin/manifest.proto",
        "src/proto/models/plugin/provider.proto",
        "src/proto/models/user/auth.proto",
        "src/proto/models/user/billing.proto",
        "src/proto/models/user/integration.proto",
        "src/proto/models/user/profile.proto",
        "src/proto/services/activity/activity.proto",
        "src/proto/services/billing/billing.proto",
        "src/proto/services/pipeline/pipeline.proto",
        "src/proto/services/registry/registry.proto",
        "src/proto/services/user/user.proto"
      ],
      "has_devcontainer": false,
      "typecheck_configs": [
        "src/typescript/parkrun-fetcher/tsconfig.json",
        "tsconfig.json"
      ],
      "toolchain_manifests": [
        "src/go/go.mod"
      ],
      "largest_source_bytes": 660351,
      "source_files_sampled": 600,
      "oversized_source_files": 20,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 14943
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "ts-proto",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.8.3"
        },
        {
          "name": "cloud.google.com/go/firestore",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.20.0"
        },
        {
          "name": "cloud.google.com/go/pubsub",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.50.1"
        },
        {
          "name": "cloud.google.com/go/storage",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.58.0"
        },
        {
          "name": "firebase.google.com/go/v4",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v4.19.0"
        },
        {
          "name": "github.com/GoogleCloudPlatform/functions-framework-go",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.9.2"
        },
        {
          "name": "github.com/cloudevents/sdk-go/v2",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.16.2"
        },
        {
          "name": "github.com/cucumber/godog",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.15.1"
        },
        {
          "name": "github.com/getsentry/sentry-go",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.27.0"
        },
        {
          "name": "github.com/go-chi/chi/v5",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v5.2.5"
        },
        {
          "name": "github.com/google/generative-ai-go",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.20.1"
        },
        {
          "name": "github.com/google/uuid",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.0"
        },
        {
          "name": "github.com/muktihari/fit",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.26.1"
        },
        {
          "name": "github.com/oapi-codegen/runtime",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.2"
        },
        {
          "name": "github.com/stretchr/testify",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.11.1"
        },
        {
          "name": "github.com/stripe/stripe-go/v76",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v76.25.0"
        },
        {
          "name": "golang.org/x/net",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.50.0"
        },
        {
          "name": "golang.org/x/oauth2",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.34.0"
        },
        {
          "name": "golang.org/x/text",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.38.0"
        },
        {
          "name": "google.golang.org/api",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.262.0"
        },
        {
          "name": "google.golang.org/genproto/googleapis/api",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0-20251202230838-ff82c1b0f217"
        },
        {
          "name": "google.golang.org/grpc",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.78.0"
        },
        {
          "name": "google.golang.org/protobuf",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.36.11"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "src/go/go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 9,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 6,
        "closed_unmerged_prs": 1
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "ripixel",
          "commits": 1010,
          "avatar_url": "https://avatars.githubusercontent.com/u/3977605?v=4"
        },
        {
          "type": "User",
          "login": "tom-ripixel",
          "commits": 6,
          "avatar_url": "https://avatars.githubusercontent.com/u/302311516?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.994
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum",
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 9,
            "reason": "binaries present in source code",
            "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": "9 out of 9 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": 3,
            "reason": "Found 9/27 approved changesets -- score normalized to 3",
            "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": 0,
            "reason": "license file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 1,
            "reason": "dependency not pinned by hash detected -- score normalized to 1",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "118 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "892db28f78e90f9cf3052b6a3013092b69c45429",
        "ran_at": "2026-07-24T21:58:35Z",
        "aggregate_score": 5.3,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-23T21:12:45Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-23T20:57:56Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/Ripixel-Studio/fitglue-server",
    "host": "github.com",
    "name": "fitglue-server",
    "owner": "Ripixel-Studio"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 56,
      "inputs": {
        "security": 53,
        "vitality": 85,
        "community": 22,
        "governance": 44,
        "engineering": 73
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 85,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 83,
            "inputs": {
              "commits_last_year": 1250,
              "human_commit_share": 1,
              "days_since_last_push": 1,
              "active_weeks_last_year": 27
            },
            "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": "27/52 weeks with commits",
                "points": 18.7,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 27
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "1250 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1250
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 88,
            "inputs": {
              "releases_count": 100,
              "latest_release_tag": "v16.60.2",
              "releases_from_tags": true,
              "days_since_latest_release": 1,
              "mean_days_between_releases": 0.6
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "100 version tags (no GitHub releases)",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "version_tags_no_releases",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~0.6 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0.6
                    }
                  }
                ],
                "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": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 1,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 1 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 22,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 1,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "1 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "at_risk",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 45,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "no license file detected",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "license_absent",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "at_risk",
        "name": "Sustainability & Governance",
        "value": 44,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 15,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.994
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 99% of commits",
                "points": 0.1,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 99
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "2 contributors",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "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": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 86,
            "inputs": {
              "merged_prs": 9,
              "open_issues": 0,
              "closed_issues": 6,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 1
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "9/10 decided PRs merged",
                "points": 34.4,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 9,
                      "decided": 10
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 9/27 approved changesets -- score normalized to 3",
                "points": 4.5,
                "status": "partial",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 37,
            "inputs": {
              "followers": 0,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "Ripixel-Studio",
              "public_repos": 7,
              "account_age_days": 13
            },
            "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": "0 followers of Ripixel-Studio",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 0,
                      "login": "Ripixel-Studio"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "7 public repos, account ~0 yr old",
                "points": 6.6,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 7
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 73,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "9 out of 9 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": "https://fitglue.tech",
              "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://fitglue.tech",
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 53,
        "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": 53,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 5.3
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "binaries present in source code",
                "points": 6.8,
                "status": "partial",
                "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": "9 out of 9 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 9/27 approved changesets -- score normalized to 3",
                "points": 2.2,
                "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 not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 1",
                "points": 0.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 not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "118 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 1
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 75,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 14943
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 72,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum",
                "package-lock.json"
              ],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "src/typescript/parkrun-fetcher/tsconfig.json",
                "tsconfig.json"
              ],
              "agent_commit_share": 0.38,
              "toolchain_manifests": [
                "src/go/go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "src/typescript/parkrun-fetcher/tsconfig.json, tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "src/typescript/parkrun-fetcher/tsconfig.json, tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile, lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile, lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "38 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 38,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 1",
                "points": 1,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 98,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 660351,
              "source_files_sampled": 600,
              "oversized_source_files": 20
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "20/600 source files over 60KB",
                "points": 53.2,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 600,
                      "oversized": 20
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [],
              "has_mcp_signal": false,
              "api_schema_files": [
                "src/openapi/fitbit/swagger.json",
                "src/openapi/github/swagger.json",
                "src/openapi/hevy/swagger.json",
                "src/openapi/oura/swagger.json",
                "src/openapi/polar/swagger.json",
                "src/openapi/spotify/swagger.json",
                "src/openapi/strava/swagger.json",
                "src/openapi/trainingpeaks/swagger.json",
                "src/openapi/wahoo/swagger.json",
                "src/proto/gateway/admin.proto",
                "src/proto/gateway/client.proto",
                "src/proto/gateway/public.proto",
                "src/proto/gateway/webhook.proto",
                "src/proto/google/api/annotations.proto",
                "src/proto/google/api/http.proto",
                "src/proto/models/activity/enrichments.proto",
                "src/proto/models/activity/roundup.proto",
                "src/proto/models/activity/source.proto",
                "src/proto/models/activity/standardized.proto",
                "src/proto/models/activity/uploaded.proto",
                "src/proto/models/events/pipeline.proto",
                "src/proto/models/notification/notification.proto",
                "src/proto/models/pipeline/config.proto",
                "src/proto/models/pipeline/execution.proto",
                "src/proto/models/pipeline/pending_input.proto",
                "src/proto/models/plugin/manifest.proto",
                "src/proto/models/plugin/provider.proto",
                "src/proto/models/user/auth.proto",
                "src/proto/models/user/billing.proto",
                "src/proto/models/user/integration.proto",
                "src/proto/models/user/profile.proto",
                "src/proto/services/activity/activity.proto",
                "src/proto/services/billing/billing.proto",
                "src/proto/services/pipeline/pipeline.proto",
                "src/proto/services/registry/registry.proto",
                "src/proto/services/user/user.proto"
              ]
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": "src/openapi/fitbit/swagger.json, src/openapi/github/swagger.json, src/openapi/hevy/swagger.json, src/openapi/oura/swagger.json, src/openapi/polar/swagger.json, src/openapi/spotify/swagger.json, src/openapi/strava/swagger.json, src/openapi/trainingpeaks/swagger.json, src/openapi/wahoo/swagger.json, src/proto/gateway/admin.proto, src/proto/gateway/client.proto, src/proto/gateway/public.proto, src/proto/gateway/webhook.proto, src/proto/google/api/annotations.proto, src/proto/google/api/http.proto, src/proto/models/activity/enrichments.proto, src/proto/models/activity/roundup.proto, src/proto/models/activity/source.proto, src/proto/models/activity/standardized.proto, src/proto/models/activity/uploaded.proto, src/proto/models/events/pipeline.proto, src/proto/models/notification/notification.proto, src/proto/models/pipeline/config.proto, src/proto/models/pipeline/execution.proto, src/proto/models/pipeline/pending_input.proto, src/proto/models/plugin/manifest.proto, src/proto/models/plugin/provider.proto, src/proto/models/user/auth.proto, src/proto/models/user/billing.proto, src/proto/models/user/integration.proto, src/proto/models/user/profile.proto, src/proto/services/activity/activity.proto, src/proto/services/billing/billing.proto, src/proto/services/pipeline/pipeline.proto, src/proto/services/registry/registry.proto, src/proto/services/user/user.proto",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "src/openapi/fitbit/swagger.json, src/openapi/github/swagger.json, src/openapi/hevy/swagger.json, src/openapi/oura/swagger.json, src/openapi/polar/swagger.json, src/openapi/spotify/swagger.json, src/openapi/strava/swagger.json, src/openapi/trainingpeaks/swagger.json, src/openapi/wahoo/swagger.json, src/proto/gateway/admin.proto, src/proto/gateway/client.proto, src/proto/gateway/public.proto, src/proto/gateway/webhook.proto, src/proto/google/api/annotations.proto, src/proto/google/api/http.proto, src/proto/models/activity/enrichments.proto, src/proto/models/activity/roundup.proto, src/proto/models/activity/source.proto, src/proto/models/activity/standardized.proto, src/proto/models/activity/uploaded.proto, src/proto/models/events/pipeline.proto, src/proto/models/notification/notification.proto, src/proto/models/pipeline/config.proto, src/proto/models/pipeline/execution.proto, src/proto/models/pipeline/pending_input.proto, src/proto/models/plugin/manifest.proto, src/proto/models/plugin/provider.proto, src/proto/models/user/auth.proto, src/proto/models/user/billing.proto, src/proto/models/user/integration.proto, src/proto/models/user/profile.proto, src/proto/services/activity/activity.proto, src/proto/services/billing/billing.proto, src/proto/services/pipeline/pipeline.proto, src/proto/services/registry/registry.proto, src/proto/services/user/user.proto"
                    }
                  }
                ],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "Could not fetch npm package 'fitglue-server' from its registry",
    "Could not fetch go package 'github.com/fitglue/server/src/go' from its registry",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-24T21:58:47.485904Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/r/Ripixel-Studio/fitglue-server.svg",
  "full_name": "Ripixel-Studio/fitglue-server",
  "license_state": "absent",
  "license_spdx": null
}

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

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

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