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

nathanramoscfa / roadmodel

Recommends the right AI model, platform, and settings for any prompt — grounded in public benchmarks and per-category ratings. BYO-key CLI, MCP server, and web app.

Python · TypeScriptApache-2.0★ 1 estrella⑂ 1 forkdesde may 2026Ver en GitHub ↗

nathanramoscfa/roadmodel tiene un índice de salud de 61 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Engineering Quality (86/100) y la más baja, Security (41/100). Se actualizó por última vez hoy. Una sola persona concentra la mayor parte del trabajo reciente.

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

61
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

Nathan Ramos, CFACuenta personal
25 seguidores21 repositorios públicosdesde jun 2021

Este repositorio pertenece a una cuenta personal. Un proyecto con un único propietario conlleva más riesgo de continuidad que uno respaldado por una organización.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicaciónEtiquetas
PyPIroadmodel0.2.29-34hace 0 díasaianthropiccligeminillmmodel-selectionopenai

Métricas por categoría

Vitalidad

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

76Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
7.6/36Cadencia de commits — 11/52 semanas con commits
18/18Volumen de commits — 391 commits en el último año
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Datos de entrada utilizados
commits_last_year391
human_commit_share0,83
days_since_last_push0
active_weeks_last_year11
Cómo se puntúa
27/27Publica versiones — 36 versiones publicadas
36/36Recencia de las versiones — última versión hace 0 días
27/27Cadencia de publicación — una versión cada ~1,9 días
8/10OpenSSF Scorecard: Signed-Releases — 5 out of the last 5 releases have a total of 5 signed artifacts.
Datos de entrada utilizados
releases_count36
latest_release_tagv0.2.29
releases_from_tagsno
days_since_latest_release0
mean_days_between_releases1,9

Comunidad y Adopción

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

43En riesgo · 18% del índice global
Cómo se puntúa
0/60Estrellas — 1 estrellas
0/25Forks — 1 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks1
stars1
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (Apache-2.0)
18/18Guía CONTRIBUTING
13.5/13.5Código de conducta
0/7.2Plantilla de issues
6.3/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributing
has_issue_templateno
has_code_of_conduct
has_pull_request_template

Sostenibilidad y Gobernanza

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

54Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
34.9/46.8Resolución de issues — 75% de issues cerradas
37.1/38.3Aceptación de PR — 354/365 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs354
open_issues24
closed_issues71
issue_closed_ratio0,747
closed_unmerged_prs11
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
10.2/25Alcance del propietario — 25 seguidores de nathanramoscfa
19.9/25Trayectoria — 21 repos públicos, cuenta de ~5 años
Datos de entrada utilizados
followers25
owner_typeUser
is_verified
owner_loginnathanramoscfa
public_repos21
account_age_days1854
Excluidos de la puntuación (sin datos o no aplicable): Dominio verificado. Los pesos restantes se han renormalizado.
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en pypi
35/35Recencia de publicación — última publicación hace 0 días
20/20Historial de versiones — 34 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesroadmodel
ecosystemspypi
any_deprecatedno
min_days_since_publish0

Calidad de Ingeniería

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

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

Documentación

90Excelente
Cómo se puntúa
30/30README
25/25Directorio de documentación
15/15Sitio de documentación / página del proyecto — https://roadmodel-web.vercel.app
10/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepagehttps://roadmodel-web.vercel.app
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?

41En riesgo · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — sin datos
2.5/2.5CI-Tests — 30 out of 30 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
5/5Packaging — packaging workflow detected
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
5/5Security-Policy — security policy file detected
6/7.5Signed-Releases — 5 out of the last 5 releases have a total of 5 signed artifacts.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0.8/7.5Vulnerabilities — 9 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate4,1
Excluidos de la puntuación (sin datos o no aplicable): branch_protection. 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.

53Moderado · 0% del índice global
Cómo se puntúa
0/45Instrucciones para agentes — sin CLAUDE.md / AGENTS.md / reglas de editor
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 83 de 83 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
Cómo se puntúa
0/18Arranque con un solo comando
22/22Pruebas automatizadas
11/11Configuración de lint / formato — .eslintrc.json
11/11Verificación estática de tipos — web/tsconfig.json
10/10Entorno reproducible — Dockerfile, lockfile
10/10Práctica demostrada con agentes — 84 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
lockfilespackage-lock.json
has_dockerfile
typed_languageno
bootstrap_files
has_devcontainerno
has_linter_config
typecheck_configsweb/tsconfig.json
agent_commit_share0,84
toolchain_manifests
dependency_bot_commit_share0
Cómo se puntúa
27/45Código verificable por tipos — Python con configuración de verificación de tipos (web/tsconfig.json)
55/55Tamaños de archivo manejables — 0/237 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languagePython
largest_source_bytes51.420
source_files_sampled237
oversized_source_files0
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
20/20Servidor MCP
0/40Ejemplos ejecutables
Datos de entrada utilizados
example_dirs
has_mcp_signal
api_schema_files

Datos clave

1estrellas de GitHub
1contribuidores
391commits en los últimos 12 meses
0días desde el último push
36versiones publicadas
1factor bus
24issues abiertas
npm, PyPIecosistemas de paquetes

Advertencias de recopilación de datos

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • Could not fetch pypi package 'roadmodel-service' from its registry
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository
  • deps.dev does not index pypi:roadmodel@0.2.29; advisories assessed against the repository dependency graph instead

Más detalle

OpenSSF Scorecard 4.1 / 10
4.1agregado

Evaluación de seguridad independiente y agnóstica en cuanto a herramientas, procedente del proyecto de código abierto OpenSSF Scorecard. Cada comprobación premia una práctica de seguridad, no la herramienta de un proveedor concreto. Las comprobaciones que Scorecard no pudo determinar se marcan como n/d y se excluyen de la puntuación de seguridad (nunca se cuentan como cero).Scorecard v5.5.0 · 2026-07-22 19:07 UTC

10Binary-Artifactsno binaries found in the repo
n/dBranch-Protectioninternal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
10CI-Tests30 out of 30 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
10Packagingpackaging workflow detected
1Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 1
0SASTSAST tool is not run on all commits -- score normalized to 0
10Security-Policysecurity policy file detected
8Signed-Releases5 out of the last 5 releases have a total of 5 signed artifacts.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
1Vulnerabilities9 existing vulnerabilities detected
Dependencias directas 15
RegistroPaqueteRestricción de versiónManifiesto
PyPIclick>=8.3.3pyproject.toml
PyPIroadmodel>=0.2.29,<0.3service/pyproject.toml
PyPIfastapi>=0.110service/pyproject.toml
PyPIuvicorn>=0.27service/pyproject.toml
PyPIpydantic>=2.6service/pyproject.toml
npm@google/genai^2.6.0web/package.json
npm@supabase/ssr^0.10.3web/package.json
npm@supabase/supabase-js^2.106.0web/package.json
npm@upstash/ratelimit^2.0.8web/package.json
npm@upstash/redis^1.38.0web/package.json
npmlucide-react^0.511.0web/package.json
npmnext^15.3.2web/package.json
npmreact^19.1.0web/package.json
npmreact-dom^19.1.0web/package.json
npmzod^3.25.28web/package.json
Todas las dependencias no recopilado

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

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 3620,
      "has_wiki": true,
      "homepage": "https://roadmodel-web.vercel.app",
      "languages": {
        "CSS": 973,
        "Shell": 142540,
        "Python": 1109485,
        "PLpgSQL": 17050,
        "Dockerfile": 813,
        "JavaScript": 5482,
        "TypeScript": 615065
      },
      "pushed_at": "2026-07-22T17:59:20Z",
      "created_at": "2026-05-07T16:58:09Z",
      "owner_type": "User",
      "updated_at": "2026-07-22T17:59:44Z",
      "description": "Recommends the right AI model, platform, and settings for any prompt — grounded in public benchmarks and per-category ratings. BYO-key CLI, MCP server, and web app.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "Python",
      "significant_languages": [
        "Python",
        "TypeScript"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Nathan Ramos, CFA",
      "type": "User",
      "login": "nathanramoscfa",
      "company": null,
      "location": null,
      "followers": 25,
      "avatar_url": "https://avatars.githubusercontent.com/u/86393277?v=4",
      "created_at": "2021-06-24T03:26:51Z",
      "is_verified": null,
      "public_repos": 21,
      "account_age_days": 1854
    },
    "license": {
      "state": "standard",
      "spdx_id": "Apache-2.0",
      "raw_spdx": "Apache-2.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.2.29",
          "kind": "patch",
          "published_at": "2026-07-22T17:37:36Z"
        },
        {
          "tag": "v0.2.28",
          "kind": "patch",
          "published_at": "2026-07-21T22:03:55Z"
        },
        {
          "tag": "v0.2.27",
          "kind": "patch",
          "published_at": "2026-07-19T21:49:41Z"
        },
        {
          "tag": "v0.2.26",
          "kind": "patch",
          "published_at": "2026-07-19T15:45:00Z"
        },
        {
          "tag": "v0.2.25",
          "kind": "patch",
          "published_at": "2026-07-17T00:32:55Z"
        },
        {
          "tag": "v0.2.24",
          "kind": "patch",
          "published_at": "2026-07-16T16:47:41Z"
        },
        {
          "tag": "v0.2.23",
          "kind": "patch",
          "published_at": "2026-07-16T14:34:20Z"
        },
        {
          "tag": "v0.2.22",
          "kind": "patch",
          "published_at": "2026-07-16T04:49:45Z"
        },
        {
          "tag": "v0.2.21",
          "kind": "patch",
          "published_at": "2026-07-16T03:52:56Z"
        },
        {
          "tag": "v0.2.20",
          "kind": "patch",
          "published_at": "2026-07-05T05:46:54Z"
        },
        {
          "tag": "v0.2.19",
          "kind": "patch",
          "published_at": "2026-07-05T02:00:08Z"
        },
        {
          "tag": "v0.2.18",
          "kind": "patch",
          "published_at": "2026-07-04T19:29:25Z"
        },
        {
          "tag": "v0.2.17",
          "kind": "patch",
          "published_at": "2026-07-04T18:51:22Z"
        },
        {
          "tag": "v0.2.16",
          "kind": "patch",
          "published_at": "2026-07-04T16:02:53Z"
        },
        {
          "tag": "v0.2.15",
          "kind": "patch",
          "published_at": "2026-07-04T03:22:53Z"
        },
        {
          "tag": "v0.2.14",
          "kind": "patch",
          "published_at": "2026-07-03T23:25:30Z"
        },
        {
          "tag": "v0.2.13",
          "kind": "patch",
          "published_at": "2026-07-03T13:48:46Z"
        },
        {
          "tag": "v0.2.12",
          "kind": "patch",
          "published_at": "2026-07-02T04:38:26Z"
        },
        {
          "tag": "v0.2.11",
          "kind": "patch",
          "published_at": "2026-06-29T04:24:31Z"
        },
        {
          "tag": "v0.2.10",
          "kind": "patch",
          "published_at": "2026-06-29T02:40:49Z"
        },
        {
          "tag": "v0.2.9",
          "kind": "patch",
          "published_at": "2026-06-15T01:01:22Z"
        },
        {
          "tag": "v0.2.8",
          "kind": "patch",
          "published_at": "2026-06-15T00:16:05Z"
        },
        {
          "tag": "v0.2.7",
          "kind": "patch",
          "published_at": "2026-06-13T23:39:07Z"
        },
        {
          "tag": "v0.2.6",
          "kind": "patch",
          "published_at": "2026-06-13T21:43:39Z"
        },
        {
          "tag": "v0.2.5",
          "kind": "patch",
          "published_at": "2026-06-06T04:27:09Z"
        },
        {
          "tag": "v0.2.4",
          "kind": "patch",
          "published_at": "2026-06-04T05:00:54Z"
        },
        {
          "tag": "v0.2.3",
          "kind": "patch",
          "published_at": "2026-06-01T02:20:04Z"
        },
        {
          "tag": "v0.2.2",
          "kind": "patch",
          "published_at": "2026-05-31T15:46:55Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2026-05-31T13:59:36Z"
        },
        {
          "tag": "v0.3.0-phase-3",
          "kind": "prerelease",
          "published_at": "2026-05-20T15:53:16Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-05-17T00:21:14Z"
        },
        {
          "tag": "v0.1.2-pypi",
          "kind": "prerelease",
          "published_at": "2026-05-16T03:43:03Z"
        },
        {
          "tag": "v0.1.1-pypi",
          "kind": "prerelease",
          "published_at": "2026-05-15T05:14:23Z"
        },
        {
          "tag": "v0.1.0-pypi",
          "kind": "prerelease",
          "published_at": "2026-05-15T03:57:01Z"
        },
        {
          "tag": "v0.0.0-r1",
          "kind": "prerelease",
          "published_at": "2026-05-15T03:48:58Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-05-09T01:47:48Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "abfe10fed33b3b85daaf7f8193e193f0ad16e99a",
          "body": "… pick (#487)\n\nRoot cause of the self-contradictory \"Fable 5 is the strongest model your\ndeclared access can run; Claude Fable 5 was outside your access and was not\nrecommendable\" rationale — a DETERMINISTIC AccessGuard rewrite, not the engine:\n\n- The engine emits \"Claude Fable 5\" (maker prefix) but\n[…]\n root cause.\n\nRegression tests: is_accessible(\"Claude Opus\") is True; enforce() leaves a\nmaker-prefixed accessible pick untouched.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(service): AccessGuard no longer self-substitutes a maker-prefixed…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-22T17:59:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0dd79c26ac5bfce0bdfb8c6309558da768bc890c",
          "body": "* chore(service): bump roadmodel floor to >=0.2.29\n\nPulls the 0.2.29 rationale fix (no self-contradictory \"returned pick is\noutside your access\" narration) into the deployed service.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* chore: re-trigger CI after PyPI 0.2.29 propagation\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): bump roadmodel floor to >=0.2.29 (#485)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-22T17:44:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f49acb6c3d5204b96b4cff4ded7739eb72756bc2",
          "body": "…ss (0.2.29) (#484)\n\nThe <availability-context> substitution example literally used \"Fable 5\" as its\nunavailable-model example, so when the engine picked Fable 5 it parroted the\nexample verbatim — producing the self-contradictory rationale seen in prod\n(\"Fable 5 is the strongest fit ... Fable 5 was \n[…]\n rationales, contradiction gone. Version 0.2.29;\nmodel-selector.md regenerated. Service floor bump follows after the PyPI publish.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: rationale never calls the returned pick unavailable/outside-acce…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-22T17:33:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9bf2693e1f69a67d31065164811f26ec56c60300",
          "body": "Pulls the 0.2.28 engine into the deployed service: the RUN->EFFORT rationale\nrename (\"Why this effort\") + the Opus 4.8 frontier-anchor fix. Separate PR\nafter the PyPI publish so the Vercel preview can resolve the version.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): bump roadmodel floor to >=0.2.28 (#482)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-21T22:09:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bb6a6952d041a29eb5255c6305e1b9a7893fc914",
          "body": "…r (0.2.28) (#481)\n\nStage 2 of the /recommend declutter + the ladder fix.\n\nWhy this effort (RUN -> EFFORT):\n- The recommender answers WHAT to run + with which settings, not HOW to run\n  it. The third labelled RATIONALE segment is repurposed from RUN: (funding /\n  how-to-invoke) to EFFORT: — a justif\n[…]\nersion 0.2.28; docs/model-selector.md regenerated. Service floor bump to\n>=0.2.28 follows in a separate PR after the PyPI publish.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: rationale 'Why this effort' (RUN->EFFORT) + Opus frontier ancho…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-21T22:00:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7ba575e81f5088b4175345900046745e15c57192",
          "body": "Added mention of 2.1.216's sandbox.filesystem.disabled setting to the claude-code method's best-for text, extending the existing versioned change log there. Versions 2.1.211-2.1.215 were already covered in the current best-for content and produced no additional edits. No changes to <thinking-context\n[…]\n no-op: --forward-subagent-text flag and CLAUDE_CODE_FORWARD_SUBAGENT_TEXT env var already documented in existing best-for text.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-21 (#477)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-21T17:43:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f49107e05951ffe460bee1786c0db85b103b7d0e",
          "body": "…ackup (#476)\n\nroadmodel answers WHAT to run + with which settings, not HOW to run it —\nthe user knows how to run the model. Stage 1 (frontend-only) of the\ndeclutter:\n\n- WhyDisclosure: drop the engine's third \"run\" rationale segment (\"How to\n  run it\": funding/how-to-invoke) from the \"Why {model}?\" \n[…]\n assert the \"How to run it\" heading + text are gone.\n\nFocus stays on model, platform, effort, and thinking — not run instructions.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(web): declutter /recommend output — drop \"how to run it\", trim b…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-21T01:20:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "87a74aa52652343ef16630891b0f3a3237afebf3",
          "body": "…=0) (#470)\n\ngpt-5* at default effort reasons ~33s and can empty the output budget; minimal\n(tb=0 -> reasoning.effort=minimal per #469) runs ~7s, the validated fast/cheap\nanon config. (The harness itself shipped via #469's index carry-over.)\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "tooling: run gpt-5 eval engines at minimal reasoning (thinking_budget…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-20T03:33:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d2edbd6665a3782cda02ed3f1ad24cf07c327910",
          "body": "…#474)\n\nCompletes the eval-backed engine cutover (anon canary verified in prod).\nresolveRecommenderEngine's frontier branch now returns gpt-5-mini on the\nOpenAI key (force_provider openai-gpt-5-mini) instead of gemini-2.5-pro —\nthe 2026-07-19 differential eval (scripts/eval_recommend_engines.py) gav\n[…]\nc.ts: assert the new frontier\n  engine / generated-by label\n- engine-overrides.ts: note both tiers now share the gpt-5-mini engine\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(web): flip signed-in frontier recommender engine to GPT-5 mini (…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-20T02:59:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "97fdc256a0a6b510e4b9243f43df50b9a7eaba89",
          "body": "…er) (#472)\n\nEval-backed engine move (differential harness): GPT-5 mini has the best\ninstruction-adherence (1.0 no-cost-demotion vs Gemini 0.83-0.92), is structurally\nflawless, and is ~3x cheaper with OpenAI automatic prefix caching (~$0.005/call).\n\n- service: add 'openai-gpt-5-mini' to _PROVIDER_HI\n[…]\ngpt-5-mini to ENGINE_RATES.\n\nCanary-first: this flips only the anon tier. Verify cost + adherence in prod,\nthen flip the frontier.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(recommend): canary the recommender engine to GPT-5 mini (anon ti…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T21:56:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "65c7349fb9fd51ba7f5a87cabdc99d48a9b3059a",
          "body": "Carries the OpenAI provider reasoning.effort fix (#469) to PyPI so the service\ncan use GPT-5 mini as a recommender engine. Bumps 0.2.26 -> 0.2.27 (pyproject +\n__init__ + packaging test). Service floor bump lands in a follow-up after publish\n(the service Vercel preview resolves roadmodel from PyPI).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): roadmodel 0.2.27 (#471)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T21:45:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "73f3240cb8871fcfa39ad072511c849f15e0563a",
          "body": "…size (#468)\n\nThe per-call engine-cost ledger used STATIC_PROMPT_TOKENS=20000, but the real\nheader+selector+tier-cost prompt measures ~39,526 tokens (google\nusage_metadata.prompt_token_count, 2026-07). So audit_log.cost_usd — and the\ndaily spend-guard (web/lib/spend-guard.ts) that returns 503 at the\n[…]\nince Gemini implicit caching is present but unreliable per\nthe probe). Real cached-token capture from the provider is a follow-up.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(web): correct engine-cost estimate to the measured ~39.5k prompt …",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T20:34:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "406272a260b3b5dfcc12f6c80fc39ace15fc0b73",
          "body": "…text (#469)\n\nOpenAI reasoning models (gpt-5*) count reasoning tokens against\nmax_output_tokens. The provider set max_output_tokens but never capped\nreasoning, so on a real recommend call the reasoning consumed the ENTIRE budget\nand returned NO visible text (observed: gpt-5-mini 32s, empty output) —\n[…]\natic prefix caching). Temperature stays unforwarded\n(reasoning models reject it); Gemini-only thinking_config keys are never sent.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(providers): cap reasoning.effort on gpt-5* models so they return …",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T20:13:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "837ba73383ba63748c9d0516cc854a0052245340",
          "body": "No changes detected. The current selector's OpenAI/Codex reasoning-effort content already matches <docs_facts> exactly: the thinking-context OpenAI bullet enumerates minimal/low/medium/high/xhigh (noting the plan-mode `none` variant), and the output mapping covers minimal→Off, low→Low, medium→Medium\n[…]\nsity vocabularies which are out of scope for the reasoning-effort narrative and were intentionally not surfaced in the selector.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Codex refresh: 2026-07-19 (#465)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-19T18:29:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4c9e6260a233b0e6a665329e41fb9db4285ac4aa",
          "body": "…ill (#464)\n\nThe rounded-full accent pills on the /recommend matrix wrapped long labels\n(\"ChatGPT (web / desktop)\", \"Claude Code · Extra high\") inside the balloon on\nnarrow columns, hurting readability. Drop the pill chrome (rounded bg + padding)\nand render the platform as plain accent-colored subti\n[…]\next with leading-snug,\nso a long label flows to a clean second line instead of a two-line balloon. No\ndata hidden; works on touch.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(web): render pick/backup platform as plain text, not a wrapping p…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T17:56:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dc1b0f205d395129b4e23b33b13bcae491a1cf96",
          "body": "Processed Claude Code CHANGELOG versions 2.1.210–2.1.215. All five entries are Claude Code polish (bug fixes, tool-call elapsed-time counter, `--forward-subagent-text` flag, `/fork`/`/subtask`/`/resume` background sessions, EndConversation tool, Podman daemon-redirect prompts, `/verify` and `/code-r\n[…]\nntion the live elapsed-time counter on long-running tool calls and the Write/NotebookEdit/Glob permission-rule startup warnings.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-19 (#463)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-19T17:35:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "324d4c517cfdcfd556a5da284fdd36daa4dee86b",
          "body": "Adds a /docs section: effort is a separate axis from model choice; roadmodel\nkeeps it high and lowers it only when it saves real cost, so each pick can run\nat full effort while differing by model. Documents the Settings control\n(Automatic / Always maximum / Scale to save budget) and notes the backup follows\nthe same setting.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(web): explain the Reasoning effort setting (#461)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T16:27:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "71903f8bf6688564e05cdb7e765b0abb57edcb86",
          "body": "* chore(service): floor roadmodel[recommend]>=0.2.26\n\n0.2.26 is now on PyPI, so the service can require it — this is what actually\ncarries the backup backstop + OpenAI-API display fix to prod (they ship via the\npackage, not service code). Split from the release PR because bumping the floor\nbefore pu\n[…]\nore: retrigger CI (PyPI 0.2.26 index propagation)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): floor roadmodel[recommend]>=0.2.26 (#460)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T15:51:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0afd8d0ae5efa6c14e0e2511211fa1f6cb97fc3c",
          "body": "Carries the merged package changes to PyPI so the recommender service can pick\nthem up (they reach prod only via release, not merge):\n- Backup backstop: benched / region-blocked cross-provider backups rejected\n  deterministically (+ cost.model_jurisdiction / cost.model_id_of).\n- OpenAI direct API re\n[…]\nLLOW-UP PR after 0.2.26 is on PyPI —\nbumping it here fails the service's Vercel preview (uv can't resolve an\nunpublished version).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): roadmodel 0.2.26 (#459)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T15:41:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2b0039a785ba78984fec928d0ee9c05cc4b0097c",
          "body": "* feat(recommend): consumption-headroom effort axis (keep effort maxed when it costs nothing)\n\nReasoning EFFORT and capability TIER are separate axes, but the\nbudget-priority ladder scaled both down together for the Cost pick. Scaling\neffort only helps when effort actually costs the user something —\n[…]\nict[str,str]) with _resolve_id's str|None return.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(recommend): consumption-headroom effort axis (#457)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T06:48:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8247c87ba414b37f1170dfa4133de3a3ec52942e",
          "body": "… cross-provider backups (#456)\n\n* fix(recommend): deterministic jurisdiction + availability backstop on cross-provider backups\n\nThe Step 7 BACKUP is only kept as-is when it is genuinely usable. The\nsame-maker case was always enforced deterministically, but the\navailability (Step 0a) and jurisdictio\n[…]\nmat test_backup_guard.py (CI ruff version reflow)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): deterministic jurisdiction + availability backstop on…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-19T06:37:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6ab6e24fb9343957252a179d255faa4da1777f01",
          "body": "Processed CHANGELOG version 2.1.214. Extended the `<method id=\"claude-code\">` best-for text to note the 2.1.214 additions: the EndConversation tool (agent-initiated session end for abusive/jailbreak cases) and Podman/docker daemon-redirect permission prompts. No thinking-context reconciliation neede\n[…]\nnt. No max-mode-context change (no Claude Code Max-Mode equivalent shipped). Cursor-owned `supports-models` attribute untouched.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-18 (#455)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-18T18:07:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "81160b90986e0dd991388b88cb67b1891b71fd4b",
          "body": "…sive app default (#445) (#453)\n\nForward migration setting the profiles.allowed_jurisdictions COLUMN DEFAULT to\ninclude 'cn', matching the app default flipped in #452 (web\nDEFAULT_PROFILE.allowed_jurisdictions). DEFAULT ONLY — no backfill, since\nexisting rows hold each user's explicit selection and \n[…]\negacy infra/migrations/ is frozen\n(no api_providers/model_availability migrations); infra/supabase/migrations/ is\nthe live Supabase-tracked dir.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(db): align profiles.allowed_jurisdictions default with cn-inclu…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-18T16:32:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "50e6ad21ebc7d83be14e9b82cd94f4f672ddd40f",
          "body": "…stricted (#445) (#452)\n\nTwo coupled Settings changes so the access filter (#451) matches user intent:\n\n1. Flip the default: \"Restrict to low-risk jurisdictions\" now ships OFF, so\n   Chinese open-weight models (DeepSeek, GLM via z.ai) are available by\n   default. DEFAULT_PROFILE.allowed_jurisdiction\n[…]\nt; the app always\nsends allowed_jurisdictions on onboarding so it's never the effective value —\naligning the DB default is a cosmetic follow-up.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(web): jurisdiction default includes cn + hide cn vendors when re…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-18T15:23:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ea3e65c391559c055ef133a8f2ce590d44534bee",
          "body": "…ls (#445) (#451)\n\nWhen the user declares any funding, recommendations must only surface models\nthey can actually run. Two layers, both service-side (no package release):\n\n1. Bias: build_user_context appends a HARD \"Access restriction\" allowlist of\n   the accessible model NAMES (models reachable via\n[…]\nccessible, honest pay-per-token notes) instead of Fable 5 / Sonnet /\nComposer. 17 new unit tests; ruff + mypy --strict + 77 service tests green.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(service): restrict recommendations to the user's accessible mode…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-17T21:43:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7334de9730c797f36f2cce40c55f1cc509452042",
          "body": "Extended the claude-code access-method `best-for` to note the 2.1.212 additions: `/fork` for background-session copies, `/subtask` for the in-session subagent, the `/resume` picker, per-session WebSearch and subagent caps, and long-running MCP auto-backgrounding. Scopes 1 (thinking-context) and 2 (m\n[…]\nS_WRAPPER`, and rendering fixes — none materially change Claude Code's positioning fact set relative to the existing `best-for`.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-17 (#450)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-17T18:17:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2dce61473c34c1a1571e2ac4307fb04193c73f4d",
          "body": "…ription\") (#444) (#448)\n\nPost-deploy prod probe surfaced a guard escape: \"This uses the ChatGPT\nsubscription via the Codex CLI\" carries no \"your\", so the possessive claim\npatterns missed it. Add a verb+\"the\" alternation (uses/on/via/through/with/by\nthe ... subscription|plan|pool); the honest \"requi\n[…]\nscription or API\nkey\" phrasing stays unmatched (article \"a\", no verb+\"the\"). Regression tests\npin the exact prod string and the honest phrasing.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(service): catch possessive-free funded claims (\"the ChatGPT subsc…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-17T14:04:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "13e279e40a06db6fa73e9e73b3aefb67b0a52088",
          "body": "…s (#444) (#447)\n\nThe engine intermittently narrates funding the user never declared (\"This\nruns on your claude.ai Max subscription\") even though the per-user context\nsays \"None declared\" / \"do not assume\". Enforce it in code, like the\nTHINKING=N/A override (#188) and the BACKUP guard: when the pick\n[…]\nxt is injected; anon/bundled path untouched; selection never changed.\n\nRider: z.ai renders as \"z.ai\" in the funding doc, not the \"Zai\" fallback.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(service): deterministic funded-platform honesty guard on run-note…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-17T04:40:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "41d8ac05d04cf6e03ca11cd77abc23ca00db7961",
          "body": "Bumps the service floor to the release that carries the 2026-07-15 catalog\nrefresh (40 models; grok-4.3 retained as provider-direct via xai-api). The\nselector + catalog.json ship inside the wheel, so the deployed service only\npicks these models up once its floor forces the new release at build time.\n[…]\nheck 13 pins\nroadmodel[recommend]>=0.2.x,<0.3); roadmodel 0.2.25 is live on PyPI (wheel +\nsdist, trusted-publishing attestations).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel[recommend]>=0.2.25 (#443)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T22:53:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "57209e0b85736822e7f4d6e27260f8c575f23cec",
          "body": "…-direct (#442)\n\nShips the 2026-07-15 catalog refresh (#427) to PyPI. The selector and\ncatalog.json ride inside the wheel, so a release is what carries these models\nto the CLI, MCP read_catalog, and the recommender service.\n\n- Catalog → 40 models: adds Claude Sonnet 5, GPT-5.6 Sol/Terra/Luna, GPT-5.\n[…]\n, so this cannot recur.\n\nVerified: full suite 492 passed, ruff clean, verify-macos --fast green, wheel\nbuilds as roadmodel-0.2.25.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: roadmodel 0.2.25 — 40-model catalog + grok-4.3 kept provider…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T22:39:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e4cfbabfb4911ce3ea8870b01d75bf2744beaa51",
          "body": "* Automated catalog refresh: 2026-07-15\n\nCost-scale refresh 2026-07-15: added new models visible on Cursor's pricing page — Claude Sonnet 5 ($3/$15, High), GPT-5.6 Sol ($5/$30, Very High), GPT-5.6 Terra ($2.50/$15, High), GPT-5.6 Luna ($1/$6, Low), GPT-5.2 Codex ($1.75/$14, Medium), GPT-5.1 Codex Ma\n[…]\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>\nCo-authored-by: Nathan Ramos <nathan.ramos.github@gmail.com>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": true,
          "headline": "Automated catalog refresh: 2026-07-15 (#427)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-16T22:29:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "47c355050b0d09695da5ed4afa736ffe2af19600",
          "body": "Codex reasoning-effort conformance touch-up.\n- <thinking-context> OpenAI bullet: no vocabulary change (already enumerates minimal/low/medium/high/xhigh, matching the docs' `reasoning_effort` set); added a short trailing note that Codex's plan-mode reasoning-effort variant additionally accepts `none`\n[…]\ne synonym for the 'xhigh' config token in the OpenAI mapping bullet, per the scope instructions — docs_facts only lists 'xhigh'.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Codex refresh: 2026-07-16 (#441)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-16T19:11:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "020b5ac81d4993778a4526e71be19a3b41c73d7e",
          "body": "Updated the Claude Code method best-for in <access-methods> to mention the 2.1.211 addition of the `--forward-subagent-text` flag and `CLAUDE_CODE_FORWARD_SUBAGENT_TEXT` environment variable for including subagent text and thinking in stream-json output. Reviewed versions 2.1.207–2.1.211: all other \n[…]\nare out-of-catalog anyway; existing default-permission-mode Manual note in claude-code best-for already covers 2.1.200 defaults.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-16 (#437)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-16T18:17:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5576b158951fe6f48b6e8e2c4addd786dff77bd8",
          "body": "…rs (0.2.24) (#435)\n\n* feat(mcp): ship the per-surface settings-display rules to offline consumers (0.2.24)\n\nThe selector emits platform-neutral axes (MAX MODE / THINKING /\nORCHESTRATION). Turning those into a surface's REAL controls lives in\nrecommend._structured_settings and is deliberately NOT in\n[…]\ninclude list broke package-smoke on every Python.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(mcp): ship per-surface settings-display rules to offline consume…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T16:44:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "149f4d6d24ba5c633180a253d1f8e3dd38896730",
          "body": "…p (0.2.23) (#434)\n\nUsing roadmodel across many projects meant per-project installs and a\nplanning/ folder exported (and re-exported on every catalog change) into\neach repo. That scales with project count and is pure toil.\n\nThe MCP server already solves it — `read_catalog` serves the whole\nselector \n[…]\n/--force/--dry-run; actionable errors when the mcp extra or\nthe `claude` CLI is missing (prints the exact command to run instead).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cli): add `roadmodel setup-mcp` — one-command, machine-wide setu…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T14:30:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "195e769c90b3155009b50d96127b006908ed7a09",
          "body": "* chore(service): require roadmodel[recommend]>=0.2.22\n\nroadmodel 0.2.22 made the provider SDKs an opt-in `recommend` extra. The\nservice serves live recommendations, so it must pull that extra — pin\n`roadmodel[recommend]>=0.2.22,<0.3` so the deployed service installs\nanthropic/openai/google-genai. N\n[…]\nd-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* chore: retrigger service deploy (0.2.22 PyPI propagation)\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel[recommend]>=0.2.22 (#433)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T05:01:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1a0d7e88e70a79a49a6b732148c938fbfb078c24",
          "body": "…22) (#432)\n\nBase `pip install roadmodel` no longer forces anthropic/openai/\ngoogle-genai — the only hard runtime dep is now click. Those three SDKs\nmove to a `recommend` optional-extra, needed ONLY for `roadmodel\nrecommend` (live API calls). The offline planning-kit workflow\n(export-kit, catalog, c\n[…]\nlls `.[recommend]` (mirrors prod).\n\nService floor bump to `roadmodel[recommend]` follows in a separate PR\nafter 0.2.22 is on PyPI.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(packaging): make provider SDKs an opt-in [recommend] extra (0.2.…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T04:46:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2434e905cf299fbd7c3d5a85be96e97bdec3b909",
          "body": "….json (#431)\n\nCloses the gap that left Fable 5 benched in the offline CLI + planning\nkit for two weeks after the runtime layer autonomously un-benched it\n(2026-07-02). The autonomous un-bench only ever updated the runtime\npath (Supabase → web /api/recommend); the bundled static\n<availability-contex\n[…]\n kit still needs a package release to pick the change up\n(offline is offline), but the human no longer edits the selector by hand.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(availability): auto-sync static fallback from model-availability…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T04:07:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1b9540d7509b8a052576536b01d67c76d5b352bc",
          "body": "Requires the release that ships the un-benched static availability\nfallback (#428/#429, roadmodel 0.2.21 on PyPI) so the deployed service\ncarries the corrected bundled selector.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): bump roadmodel floor to >=0.2.21 (#430)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T04:00:49Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dab7fba92eb3587f87f7e29ae4b57e4b743feff0",
          "body": "…ck (#429)\n\nShips #428 (empty <availability-context> cold-start fallback) to the CLI\nand planning-kit consumers. Selector-data change only; the runtime\nauthoritative path was already correct since 2026-07-02.\n\nBumps pyproject.toml + __init__.py + test_packaging.py pin; CHANGELOG entry.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: roadmodel 0.2.21 — un-bench Fable 5 in bundled static fallba…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T03:47:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bc824acf2c2afcdb2021e8ca7791359bec6bec93",
          "body": "…#428)\n\nThe runtime availability layer autonomously un-benched Fable 5 on\n2026-07-02 (grounded AI verification cleared the export-control bar,\nconf 0.93 / 5 sources; #341), so prod /api/recommend recommends it\nagain. But the bundled <availability-context> cold-start fallback in\ndocs/model-selector.t\n[…]\nf-heals) while still validating any\nids that are present.\n\nPropagates to the bundle on the next PyPI release + service floor bump.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(selector): un-bench Fable 5 in the static availability fallback (…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-16T03:29:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "beab0016ef31cf62b491b23b6a8986837b72b597",
          "body": "…cron) (#419)\n\nCursor delisted its entire xAI section on 2026-07-14, so the Opus refresh\ncorrectly drops the \"Grok 4.3\" row from docs/model-tier-cost-scale.md. But\ngrok-4.3 stayed in SELECTOR_TO_COST_SCALE_NAME, so merge_catalog's cost-scale\noverlay hard-failed (\"no table row found for 'Grok 4.3'\").\n[…]\ned (post-Opus state) the overlay raises\nno fatal flag and grok-4.3 stays in the snapshot price map; full suite green\n(456 passed).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(catalog): exempt delisted grok-4.3 from cost-scale sync (unblock …",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-15T20:04:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7e7f0278a0bce9c9115ba3c6a3243dd5b5100c9a",
          "body": "…s (#420)\n\nThe Claude Code effort docs list a row's models as \"Sonnet 5, Opus 4.8, and\nOpus 4.7\" (Oxford comma). parse_effort_table split on \" and \" only, mangling\nthat into the bogus model name \"Sonnet 5, Opus 4.8,\" which the tracker then\nflagged as a brand-new model. Dedup used `gh issue list --se\n[…]\nce gate PASS, macOS verify --fast PASS, full suite\n457 passed; new dedup matches the existing dup title via REST (proven offline).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cc-tracker): parse Oxford-comma model lists; stop daily dup issue…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-15T19:59:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6f909b365e272271bd5311f22e9041d6f3a3a818",
          "body": "…codex/deepseek) (#425)\n\nThe Gemini, Codex, and DeepSeek refresh crons dedup their \"docs introduced\nmodel / level / effort\" tracking issues with `gh issue list --search\n'... in:title'`. GitHub's search index lags, so the search returned empty\nmid-run and a fresh DUPLICATE was filed almost every day \n[…]\n three YAMLs parse; the new exact-title dedup matches the live\nGemini dup title offline (would skip); no `--search` dedup remains.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(trackers): dedup new-model issues via REST + exact title (gemini/…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-15T19:53:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2258b1b5ff47fa55086f6f6e35156c1ad53b2a38",
          "body": "… 3.2 (#424)\n\nThe pre-push hook (added in #391) crashed on every push where git config\nroadmodel.prepushphases is unset (the default): line 57 expanded a bare\n\"${phase_args[@]}\" under `set -u`, and macOS /usr/bin/env bash is 3.2, where an\nempty-array \"${arr[@]}\" raises \"unbound variable\". Every push\n[…]\n ref on stdin with no prepushphases config;\nit cleared line 57 and ran verify-macos.sh --fast to a clean pass instead of\ncrashing.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(githooks): guard empty phase_args so pre-push works on macOS bash…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-15T19:47:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a582fb559496f62738b775e5e4d4da9444aee14e",
          "body": "… builds (#423)\n\nCI's `type-check` (mypy --strict src update) has been red repo-wide: the\ninstalled pyarrow ships no py.typed marker, so `import pyarrow.parquet` in\nupdate/update_models.py raises import-untyped, and the read_table\n`# type: ignore[no-untyped-call]` is then flagged unused. This blocke\n[…]\nitions (pyarrow stubs\npresent, and pyarrow unresolved so the override forces Any): Success both ways.\nFull test suite: 456 passed.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ci): treat pyarrow as untyped so mypy --strict passes on stubless…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-15T19:33:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a1a690e641066cf8d63df6b8753ca3aba526696a",
          "body": "Processed Claude Code CHANGELOG version 2.1.205. The release is editorial/bugfix-focused (auto-mode transcript-tampering rule, `Claude Browser` MCP name reservation, `/doctor` becoming a full setup checkup, various fixes). None of the changes add new effort/thinking levels, orchestration primitives,\n[…]\ns 4.8,. This tracker only FLAGS new models; do NOT add them to selector model lists here. Open an issue for the catalog refresh.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-09 (#407)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-09T19:02:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b0bb9244f4333145d3b73454df5fa80a8d925cc6",
          "body": "Reviewed Claude Code CHANGELOG entries 2.1.204 and 2.1.203. Both releases are bug fixes and reliability improvements (background session recovery, MCP roots/list, session token handling, `claude agents` polish, VSCode remote-control toggle) with no material changes to Claude Code's effort dial, thin\n[…]\ns 4.8,. This tracker only FLAGS new models; do NOT add them to selector model lists here. Open an issue for the catalog refresh.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-08 (#404)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-08T18:28:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8f92e89189d10dc154c542e43e9e94749655aa5d",
          "body": "Reinforced the OpenAI/Codex reasoning-effort description against the config-reference docs (`reasoning_effort`: minimal/low/medium/high/xhigh):\n- Added an explicit clarification in the <thinking-context> Output mapping that OpenAI's scale tops out at `xhigh`, so no OpenAI level maps to `Max` (which \n[…]\nd to codex-cli's best-for; if these deserve first-class surfacing, a future prompt-scope expansion should cover them explicitly.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Codex refresh: 2026-07-07 (#400)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-07T19:56:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3e4f852cb934784f3a88bc84498862bb84553b0f",
          "body": "Processed Claude Code 2.1.202. In scope: the release adds a `/config` \"Dynamic workflow size\" setting (small/medium/large agent counts, advisory only) that touches the Claude Code Ultracode surface. Extended the claude-code `<method>` `best-for` with a parenthetical noting the 2.1.202 advisory guide\n[…]\ns 4.8,. This tracker only FLAGS new models; do NOT add them to selector model lists here. Open an issue for the catalog refresh.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-07 (#399)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-07T19:13:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2722fff4f8fb88f7282b17a57a2d4799f21fcd76",
          "body": "…io (#391)\n\nroadmodel is a public repo, so its Linux GitHub Actions minutes are free\n(covered by the public-repo discount). macOS runners are NOT covered and\nwere the only paid Actions minutes on this project — driven by the 10 macOS\njobs per run in phase-verify.yml (every push + PR) and 3 in verify\n[…]\n add workflow_dispatch to re-verify\nmain on demand.\n\nCONTRIBUTING.md documents the pre-push hook, its bypasses, and the rationale.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(ci): move paid macOS verification off Actions to local Mac Stud…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-06T18:13:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3c89d4e9089555f861b611587cbc0dafc38e7b62",
          "body": "Scope 3 (best-for on <method id=\"claude-code\">): folded in 2.1.197's introduction of Claude Sonnet 5 as Claude Code's new default model with a native 1M-token context window — a materially new positioning fact for the Claude Code surface. Scopes 1 and 2 unchanged: <thinking-context> already reconcil\n[…]\ns 4.8,. This tracker only FLAGS new models; do NOT add them to selector model lists here. Open an issue for the catalog refresh.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-05 (#394)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-05T18:14:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "05b9d7e12ec8c236579683285da0a99d5f3b946b",
          "body": "…dropping rows) (#390)\n\nEvery caller does `void writeAudit(...)` and returns the response immediately,\nso on Vercel the function could be torn down after the response but BEFORE the\nSupabase insert committed — silently DROPPING audit rows. Observed live: across\nseveral rapid /api/recommend diag requ\n[…]\nbest-effort void. The test-sink path is unchanged.\nFixes every call site (recommend + roadmap routes, withRateLimit) in one place.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(web): flush fire-and-forget audit writes with Next `after` (stop …",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-05T15:52:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "65724c30b94c86f4592653384193bd27f53467ad",
          "body": "…+ floor >=0.2.20 (#389)\n\nWires the cross-provider backup substitution (roadmodel 0.2.20) end to end:\n- funding.resolve_allowed_jurisdictions(context): the forwarded allowed set or\n  the baseline the selector already uses.\n- recommend() + recommend_ladder() forward it to recommend_structured /\n  rec\n[…]\nss_provider_backup).\n- test fakes accept allowed_jurisdictions (the signature-contract line already\n  landed with the package PR).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(service): forward allowed_jurisdictions for backup substitution …",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-05T05:49:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8a13a5ea6dfdaea34927238ff8f876bd75dff051",
          "body": "…] (#388)\n\n* feat(recommend): cross-provider backup SUBSTITUTION (0.2.20)\n\nThe 0.2.19 same-provider backup guard DROPPED a same-maker backup (e.g.\nFable 5 -> Opus 4.8, both Anthropic) because the package couldn't see the\nuser's jurisdiction. Realize 0.2.17 \"option A\" — substitute a cross-provider\nfa\n[…]\n service wiring\nland in the follow-up service PR.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(recommend): cross-provider backup SUBSTITUTION (0.2.20) [package…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-05T05:43:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "247a3a2c5e31e11dc6c49b42b36156ad06e8885d",
          "body": "…s #2) (#387)\n\n* fix(service): stop overriding Cursor Thinking=On back to N/A (unbreaks #2)\n\nroadmodel 0.2.17 (#2) made _structured_settings emit Cursor thinking as\n\"On\" on purpose — Cursor's frontier models reason; the dial it exposes is\nMax Mode. But the service's _normalize_no_thinking still list\n[…]\ndate stale #188 comment (Cursor moved to package)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(service): stop overriding Cursor Thinking=On back to N/A (unbreak…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-05T05:32:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c8f2f799795e0259846ea780fac587e903d9bed7",
          "body": "Ships the deterministic same-provider backup guard (#385) to prod on\nredeploy. roadmodel 0.2.19 is published to PyPI.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel>=0.2.19 (#386)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-05T02:03:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "735ad08564b0bff8869970446c0109412ef29fdf",
          "body": "…385)\n\n* feat(recommend): deterministic same-provider BACKUP guard (draft)\n\n#4 made the Step 7 cross-provider backup rule HARD in PROMPT prose only;\nGemini can still emit a same-maker backup (observed in prod: Fable 5 ->\nOpus 4.8, both Anthropic — zero resilience). Add a deterministic guard,\nmirrori\n[…]\nd. Follow-up\nbumps the service floor to >=0.2.19.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(recommend): deterministic same-provider BACKUP guard (0.2.19) (#…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-05T01:56:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1621f76654aaa63f5ad8bbd9e221accc8de24b00",
          "body": "… svc+web] (#383)\n\nWire the single-call Cost/Balanced/Quality ladder (roadmodel 0.2.18) through\nthe service and the web edge. Ships DARK behind RECOMMEND_LADDER_ENABLED with\nthe per-priority fan-out as instant rollback.\n\nService:\n- models.py: LadderResponse (tier-keyed picks + tier-distinctness guar\n[…]\nt 3x for the ladder (vs 3x/3x for the fan-out).\n- mock-recommend/ladder: E2E mock so the path runs end-to-end when the flag is on.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(recommend): ladder endpoint + flag-gated single-call edge [#1/#3…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T19:34:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e55462f25240e95eb7a7c41b4b41b89ba21a2080",
          "body": "…kg] (#382)\n\nAdd a selector \"ladder mode\" + package plumbing that emits the whole\nCost/Balanced/Quality ladder in ONE response, replacing three independent\nper-priority calls that could collapse onto the same model (Balanced =\nQuality = Opus 4.8). Quality is chosen first (no budget cap); Balanced an\n[…]\n.18 (additive, backward-compatible; within the service's\n>=0.2.17,<0.3 floor). Single-prompt + roadmap-annotation modes unchanged.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(selector): single-call tier-ladder recommender (0.2.18) [#1/#3 p…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T19:26:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4ea6d0173b2da1f57e6d65909dc7e19969309314",
          "body": "Bumps the service floor so the backup cross-provider hard rule (#375) and\nthe Cursor Thinking=On display reframe (#376) reach prod on redeploy.\nroadmodel 0.2.17 is published to PyPI.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel>=0.2.17 (#381)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T19:01:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a861e95df7c54fc2b889d8c74bfc09c0a062f501",
          "body": "…l (#378)\n\nThe \"Per 1k\" column was the model's blended API token rate stamped onto\nevery platform row. Because the funding-rank table is ONE model across\nplatforms, that number is identical on every row — which implies\nplatforms charge different token rates when they don't. It's also\noutright mislea\n[…]\n (per1kCost / sharedApiRate /\nhasPoolBilledRow) into lib/cost-format.ts with a unit spec, matching the\nrepo's lib/ + spec pattern.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): make 'cost by platform' honest — per-1k is model-leve…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T18:52:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fe21e2cea48246e23c4b6e57f209d740e96b4ce7",
          "body": "…splay) (#379)\n\nBundles the two selector-package changes that reach prod only via a\nPyPI release:\n- #375 BACKUP hard cross-provider requirement (Step 7).\n- #376 Cursor picks read Thinking=On + Max Mode (_structured_settings).\n\nBumps version in pyproject.toml + __init__.py, pins it in\ntests/test_packaging.py, and adds the CHANGELOG entry. A follow-up bumps\nthe service floor to roadmodel>=0.2.17.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: roadmodel 0.2.17 (backup cross-provider + Cursor thinking di…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T18:47:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d9e94e40826ee8f9019b26c74bb5f86d93654017",
          "body": "… (#376)\n\nCursor's frontier models always reason, but the IDE exposes no\nthinking-level dial, so the selector emits THINKING=N/A for Cursor.\nSurfaced raw, a Cursor pick read \"Thinking: N/A\" beside an em-dash\nEffort — implying it had no controllable settings at all.\n\nReframe it at the display layer i\n[…]\nn the selector vocabulary\nmeans the daily effort/thinking conformance cron (which pins Cursor's\nTHINKING=N/A) can never revert it.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): Cursor picks read Thinking=On + Max Mode, not N/A + —…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T18:03:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9d56d885a53f486ccefcdead3fbce3b27f13023e",
          "body": "… (#375)\n\nThe backup exists so a single provider's outage or access block can't\ntake out both picks — but Step 7 only said \"prefer a model from a\nDIFFERENT provider/family\", a soft preference that let same-family\nbackups through (e.g. Fable 5 primary -> Opus 4.8 backup, both\nAnthropic). Rewrite it a\n[…]\nkup_step_requires_different_provider) that guards\nthe hard language and rejects the old soft phrasing. Regenerated the\n.md mirror.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(selector): make BACKUP a hard cross-provider requirement (Step 7)…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T17:55:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8bc2e9df90d65e8b0aa363ae4d4282890dde409d",
          "body": "The DEFAULT badge was absolutely positioned (right-2.5 top-2.5) and\nreserved no space, so the uppercase column label ran under it on narrow\ncolumns (\"BALANCED\"/\"QUALITY\"). Put the label and badge in one in-flow\nrow with justify-between so the badge can never overlap the label at any\nviewport width or column position.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): stop DEFAULT badge overlapping the column label (#374)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T17:48:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "492955138fb78428b662293042ae79c2291f7684",
          "body": "…gh\" (#372)\n\nClaude Code has no separate orchestration dial — Ultracode is the top of its one\nEffort ladder (folded into the effort value by roadmodel >=0.2.16). Add\n\"orchestration\" to HIDDEN_SETTING_KEYS so the row never renders, including for any\nstale/cached record that still carries the key (imm\n[…]\nsplay the `xhigh` effort step as \"Extra high\" to match Claude\nCode's own /effort label (Low/Medium/High/Extra high/Max/Ultracode).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): hide any orchestration row + label XHigh as \"Extra hi…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T16:12:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "70ca238153f4e0aba11cb67ea087c3d1b8d8aeca",
          "body": "…rt) (#373)\n\nRedeploys roadmodel-api onto 0.2.16 so /recommend presents Claude Code's single\nEffort ladder (Ultracode as the top value) with no separate Orchestration row.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel>=0.2.16 (Ultracode folded into Effo…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T16:07:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "50b6f52cc6a6736e300c9fa9854e5f5a7a7032c9",
          "body": "…stration row (0.2.16) (#371)\n\nClaude Code exposes ONE effort dial (Low/Medium/High/XHigh/Max/Ultracode, where\nUltracode = xhigh + Dynamic Workflows) plus a separate Thinking toggle — it has\nno standalone \"orchestration\" control. The 0.2.15 change surfaced ORCHESTRATION\nas its own settings row, whic\n[…]\nd for Quality/demanding) so the Cost/Balanced/\nQuality effort tiers stay distinct after folding. Bumps roadmodel 0.2.15 -> 0.2.16.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): fold Ultracode into the Effort ladder, drop the Orche…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T15:50:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "365a46011ae0937c72ddd307c4d1975f5d7b4a61",
          "body": "…h mock) (#370)\n\nThe per-platform cost table lists the SAME recommended model across platforms,\nso its \"Model\" column just repeated one name three times and stole the width\nthe \"Your cost\" column needs — forcing it to wrap 2-3 lines and pushing the\ndetail panel below the fold. Show the Model column \n[…]\n\n\nCard bottom at 960px with a real 3-row personalized table: 922px -> 856px\n(mock ~828px), so the picks + detail fit one viewport.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): drop redundant Model column from the cost table (matc…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T04:34:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d9682ca3eb5774911c8ee9356daebad573ad2a7e",
          "body": "…ingful (#369)\n\n* fix(recommend): drop matrix rows where every pick's value is non-meaningful\n\nA settings dimension whose value is off/absent for ALL three picks (e.g.\n\"Max Mode: Off / — / —\" when no pick is on a Max-Mode surface) added a noise\nrow the mock omits and pushed the result below the fold\n[…]\nMode ON to keep exercising the humanization path.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): drop matrix rows where every pick's value is non-mean…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T04:25:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ca7ed71992fbc7a95f2e9934615907636a06907e",
          "body": "…k) (#368)\n\nThe result was taller than the mock and spilled below the fold at ~960px. Two\ncauses: (1) generous page-level spacing (py-8, text-2xl title, gap-6) and (2)\nthe benchmark chips lived in the always-visible left column, adding ~120px.\n\n- Tighten the vertical rhythm to the mock's compact sca\n[…]\nt 960px dropped 948px -> 863px (mock ~828px), so the picks\n+ detail fit one viewport with only the optional drawer below the fold.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): compact the result so it fits one viewport (match moc…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T04:09:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "12b296dad9a6fb373f9c0bf4afcc937727d861f3",
          "body": "Redeploys roadmodel-api onto 0.2.15 so /recommend surfaces the Claude Code\nORCHESTRATION dial as a settings dimension — the Orchestration row in the\ncomparison matrix. Merge only AFTER 0.2.15 is published to PyPI.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel>=0.2.15 (Orchestration setting) (#367)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T03:27:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "28741675930709646b94567b0c2de94a92add1a4",
          "body": "…nsion (0.2.15) (#366)\n\nThe comparison-matrix mock shows an Orchestration row (Standard / Ultracode),\nbut the recommender captured ORCHESTRATION only to drop it. Add it to\n_OPTIONAL_KEYS so a meaningful value (Ultracode / PerPrompt) is surfaced, and\nhave _structured_settings emit an `orchestration` \n[…]\n\nstill parses. The web matrix already renders any settings key, so no frontend\nchange is needed. Bumps roadmodel 0.2.14 -> 0.2.15.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(recommend): surface Claude Code ORCHESTRATION as a settings dime…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T03:12:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8c61957df5215fefb9a6d6052c06cde875d9bd5d",
          "body": "…ck) (#365)\n\nAt the ~960px split-screen widths the page is actually viewed at, the matrix\nand the selected-pick detail STACKED — the `lg` (1024px) breakpoint didn't\nfire, so it looked nothing like the mock's compact side-by-side layout. Match\nthe mock's own `.body-split`: side-by-side (1.42fr / 1fr)\n[…]\nable), the \"Balanced is the best value\" insight clause, and\nthe cost cell rendering the amount + a muted funding-source sub-label.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): keep matrix + detail side-by-side at ~960px (match mo…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-04T03:00:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "115f29853071d58677214a1af59e2d7f7fe7e856",
          "body": "…t (#364)\n\nBump the service floor to the 0.2.14 release (concise rationale + budget\nobjective that lowers the Cost pick's tier/effort even at $0-funded), and\nalign the per-user funding-context Cost posture with it: differentiate by\nCAPABILITY TIER and EFFORT when a whole family is $0-funded (price i\n[…]\nhan holding the frontier $0 model — the fix for Cost==Quality on\nclaude.ai Max. Balanced states it lands between Cost and Quality.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): roadmodel>=0.2.14 + Cost posture steers by tier+effor…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T23:35:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "edf4c71a318ded6c53545dbe420d0fc6d910ad57",
          "body": "…lumn (#363)\n\nThe selected Cost/Balanced/Quality column showed only a ring around its header\nplus lightly-tinted cells — not the mock's one clean, continuous box. Rebuild\nthe highlight to mirror mockups/recommend-redesign.html: an accent border on\nthe header top+sides (transparent bottom so it flows\n[…]\nthe rows into one ordered list so the last row can close\nthe box regardless of which optional rows (settings, Backup) are present.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): continuous rounded outline for the selected matrix co…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T23:31:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8fa2ab0281cd470316c6d8a388121a8f09e01b5d",
          "body": "… (0.2.14) (#362)\n\nBudget priority collapsed to the frontier model for all three tiers when a\nuser funds a whole family at $0 (claude.ai Max): list price is flat across\nevery candidate, so the old \"keep the $0 model\" rule held the top model for\nCost/Balanced/Quality alike. Steer the `cheap` posture \n[…]\nSK/PICK/RUN) at one crisp ~15-25 word sentence so the\n\"Why this model?\" panel renders compactly. Bumps roadmodel 0.2.13 -> 0.2.14.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): Cost picks lower tier+effort at $0, concise rationale…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T23:08:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "49dc1dccc046e33d1cab655448535550e6f43187",
          "body": "#358's full-width stacked matrix fixed the empty space but read sparse and\nspread-out, losing the mock's compact side-by-side feel. This restores compact\nside-by-side and removes the empty column by FILLING it instead of stacking:\n\n- LEFT column = comparison matrix + a reference block (S->D scale + \n[…]\nting key carries the scale + benchmarks.\n\nFull Playwright suite green (130 passed); verified with verbose rationale by screenshot.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): compact side-by-side layout + filled left column (#361)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T22:20:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "03ce850473ac3b949f968ea922abc3e06a544d31",
          "body": "Side-by-side \"matrix + rating key | detail\" left a large empty left column when\nthe rationale was long — the detail panel was much taller than the matrix. The\nmock only looked balanced because its sample rationale was short; real Gemini\nrationales are verbose, so the columns never matched and the le\n[…]\n so the two stay balanced at any length.\n\nFull Playwright suite green (130 passed); verified with verbose rationale by screenshot.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): stack the pick detail below a full-width matrix (#358)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T19:27:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "98f55f858fc36cf402f027a37848cefc3870d6c0",
          "body": "…cohesive detail (#357)\n\nThe shipped redesign dropped several things from the approved mockup, leaving the\nresults cramped and unbalanced (a big empty gap under the matrix, no insight):\n\n- Add the funded-$0 insight strip (shown when every pick is $0 to the user;\n  best-effort funding-source extracti\n[…]\nhy-box with\n  the cost floating outside it).\n\nFull Playwright suite green (130 passed); verified against the mockup by screenshot.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): restore mockup fidelity — insight strip, rating key, …",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T19:00:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a485bef73f9825da9a19c88a4b99b6326d4b01c6",
          "body": "Reconciled `<thinking-context>` with docs_facts and expanded the claude-code method's best-for to reflect Claude Code CHANGELOG entries 2.1.196–2.1.200. Notable additions in best-for: effort-level fallback rule (highest supported at or below requested); Option+T/Alt+T, alwaysThinkingEnabled, and MAX\n[…]\ns 4.8,. This tracker only FLAGS new models; do NOT add them to selector model lists here. Open an issue for the catalog refresh.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-03 (#356)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-03T18:23:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f620e74da1541621e12b0496311d8b7eb594ee0f",
          "body": "Bumps the service's roadmodel floor to 0.2.13 so the redeploy installs the\nstructured-rationale selector (#349, now on PyPI). Changing service/ triggers\nthe roadmodel-api Vercel deploy, which pip-installs 0.2.13; /healthz then\nreports roadmodel_version 0.2.13.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel >=0.2.13 (structured rationale) (#354)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T13:55:26Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2e796aef4602c71f0bd06695d45f9408898db3f4",
          "body": "Ships the structured-rationale selector change (#349): RATIONALE is emitted as\nthree labelled segments (TASK / PICK / RUN) and recommend_structured parses them\nbest-effort into a rationale_sections payload field. The single RATIONALE field\nstays required and its parse_response regex / _REQUIRED_KEYS\n[…]\ncommendResponse.\n\n- version 0.2.12 -> 0.2.13 (pyproject + __init__)\n- CHANGELOG 0.2.13 entry\n- pin test_packaging expected version\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): roadmodel 0.2.13 (#353)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T04:34:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cd0c9aab351ed585743785cc497ed969bdb3e71c",
          "body": "filterByJurisdiction read each cost row's `model`, but SessionCostEstimate rows\ncarry the model under `model_name` — so a jurisdiction-restricted model was\ncorrectly excluded as a PICK yet still surfaced as a cost-table alternative. The\nredesign made this visible (the cost table renders in the selec\n[…]\nTightens the onboarding restrict-path test to assert the excluded model appears\nNOWHERE (pick or cost table), regressing the leak.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): jurisdiction-filter cost-table rows by model_name (#352)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T04:26:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "95a10bbd65d1217cf9052baf8402e29bee8133ef",
          "body": "…rationale (#350)\n\n* feat(recommend): redesign output as a comparison matrix + sub-headed rationale\n\nReplaces the three stacked PriorityCards (which overflowed the viewport and read\nas duplicate containers) with a single comparison matrix — Cost / Balanced /\nQuality as COLUMNS, shared attributes (Yo\n[…]\nrison matrix +\ndetail sit higher in the viewport.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(recommend): redesign output as a comparison matrix + sub-headed …",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T04:20:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9a3494cd84681d5d3a950ba4f9e9964475e77dee",
          "body": "…end redesign (#349)\n\nThe selector now emits its RATIONALE as three labelled segments —\n\"TASK: … PICK: … RUN: …\" — so the web \"Why this model?\" panel can render\nsub-headings instead of splitting one prose string. The change is additive\nand best-effort so it can never turn a good recommendation into \n[…]\nhing prod still needs a roadmodel release + service redeploy (per the\nrecommender release pipeline); this PR is code + tests only.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(recommend): structured rationale (task/pick/run) for the /recomm…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-03T04:13:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a7fecf6a528bb84717569d877c3f8337f0fbd921",
          "body": "Reconciled <thinking-context> with docs_facts: added Sonnet 5 to the Claude Code full-range effort list (low/medium/high/xhigh/max), the max-above-xhigh model set, and the default-high enumeration alongside Opus 4.6, Opus 4.8, Fable 5, and Sonnet 4.6. Updated <method id=\"claude-code\"> best-for to me\n[…]\ns 4.8,. This tracker only FLAGS new models; do NOT add them to selector model lists here. Open an issue for the catalog refresh.\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Automated Claude Code refresh: 2026-07-02 (#346)",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-02T17:45:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b3c45acf07094fdcd858eaf3192106eb0b10457b",
          "body": "…ilability (#343)\n\nStep 3 (final) of the Phase 4.9 B5 cutover. Bumps the service floor to the\n0.2.12 release that adds recommend_structured's `availability_authoritative`\nparam, and drops the temporary `_RS_SUPPORTS_AUTHORITATIVE` feature-detect guard\n(+ its test) — the floor now guarantees the para\n[…]\nlability-context> fallback.\n\nBLOCKED until roadmodel 0.2.12 is published to PyPI (CI installs the pinned\nfloor). Draft until then.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel>=0.2.12; activate authoritative ava…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-02T04:42:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4a33a2d0eaf7615eec83664994e9524802f87f2b",
          "body": "Cutover release that activates the authoritative runtime availability override\n(Phase 4.9 B5, #339): recommend_structured/recommend/build_prompt accept\navailability_authoritative, and <availability-context> becomes a fail-closed\ncold-start fallback. Publishing this + bumping the service floor is wha\n[…]\nurther releases.\n\n- version 0.2.11 -> 0.2.12 (pyproject + __init__)\n- CHANGELOG 0.2.12 entry\n- pin test_packaging expected version\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): roadmodel 0.2.12 (#342)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-02T04:34:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e9fa5a10e5a57c576e882e08929c55557bc9b12b",
          "body": "…(#341)\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(availability): probe-detected availability change (2026-07-02) …",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-02T03:10:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d90659da0a98beb684f03be5894915ec4c1dd968",
          "body": "… (#340)\n\nThe [verify] adjudication line printed only the decision reason; a dry-run showed\nthe un-bench decision but not the sources behind it. Append up to 5 evidence_urls\nfrom the AI verdict so a run log shows the grounded basis for each bench/hold/\nun-bench (useful because an un-bench deletes the entry, so the sources aren't\npersisted in the JSON).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(availability): log cited evidence_urls in the probe verify sweep…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-02T02:06:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "65348798620b03576da956fddbf09cca4a21ff6e",
          "body": "… a release (Phase 4.9 B5) (#339)\n\nMake the runtime availability layer the source of truth so a RESTORED model is\nrecommended again with no package release, while the bundled <availability-context>\nbecomes a fail-closed cold-start fallback (used only when the availability service\nis unreachable).\n\n-\n[…]\neds one cutover release (roadmodel + service floor bump + web\ndeploy); after it, un-benching is fully autonomous and release-free.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(availability): authoritative runtime override — un-bench without…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-02T00:29:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "55800656521f3490e1533ba0b38c941fcf3b2706",
          "body": "…337)\n\nAdd an AI web-search verification step (update/verify_availability.py) that gates\nthe un-bench direction of the daily availability probe. The cheap US-keyed 1-token\nprobe is trusted to BENCH a model (fail-safe) but no longer trusted to UN-BENCH one\non its own: every currently-restricted entry\n[…]\n).\nStage 2 (separate) makes the runtime layer authoritative so a restored model is\nactually recommended without a package release.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(availability): AI-grounded autonomous un-bench (Phase 4.9 B5) (#…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-07-02T00:04:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5caa0b7a77429860aa21ad22845e23267240e882",
          "body": "…(#336)\n\nCo-authored-by: roadmodel-bot <roadmodel-bot@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(availability): probe-detected availability change (2026-07-01) …",
          "author_name": "roadmodel-cron-bot[bot]",
          "author_login": "roadmodel-cron-bot[bot]",
          "committed_at": "2026-07-01T21:39:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a719d303d8ec3216a8e6f1d231020b3a600ab777",
          "body": "Pin the service to roadmodel 0.2.11 so the redeploy picks up the Max\nreasoning-effort output level (#324). Completes the release pipeline: PyPI\npublish -> service floor bump -> redeploy. Verify via healthz roadmodel_version.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel>=0.2.11 (#325)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-06-29T04:30:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "aae819b9aace8c449136932b9b5ea13e72075cae",
          "body": "…(#324)\n\nThe selector's structured THINKING field was a stale 6-state enum\n(Off/Low/Medium/High/XHigh/N/A) that capped at XHigh — so the recommender could\nnot surface Claude Code's top `/effort` level (`max`), even though roadmodel's\nown effort tracker lists `max` for Opus 4.7/4.8/Fable 5. Result: o\n[…]\n (pyproject + __init__ + packaging pin + CHANGELOG).\nReaches prod via PyPI release + service floor bump (same pipeline as 0.2.10).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(recommend): add Max reasoning-effort output level (above XHigh) …",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-06-29T04:15:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cc07430ec43e0ced63f6e80b3faeae46609f39b1",
          "body": "Pin the service to the just-published roadmodel 0.2.10 so the redeploy picks up\nthe bundled selector-prompt changes (budget-priority steering #319 + funding-\naware Cost #321). Completes the recommender release pipeline: PyPI publish ->\nservice floor bump -> redeploy. Verify via healthz roadmodel_version.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(service): require roadmodel>=0.2.10 (#323)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-06-29T02:46:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "988e20ff384b2d6b6d99418a079af848fc8bd4e8",
          "body": "Cut 0.2.10 so the budget-priority selector-prompt changes reach prod (the\nrecommender package is bundled at build time and only ships via a PyPI release\n+ service floor bump, not on merge — #319/#321 have been running service-side\nonly). This release bundles the updated <objective>:\n\n- Budget-priori\n[…]\ntisfied). Tag v0.2.10 + the gated workflow_dispatch\npublish follow on merge; then the service floor bumps to >=0.2.10 + redeploys.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): roadmodel 0.2.10 (#322)",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-06-29T02:09:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "eb7bd1bb39be9a116bd9130e802568315a0d12c4",
          "body": "…rt (#321)\n\nFor a user who already funds a capable model at $0 (e.g. Opus via Claude Max),\n\"Cost\" was switching to a cheaper-TIER model (GPT-5.4) by generic list price —\nwhich RAISES their real cost, since the cheaper-tier model is unfunded\n(pay-per-token) while their best model is free. List-price \n[…]\nestion: why Cost picked GPT-5.4 over Opus-at-lower-effort.\nBuilds on #319 (budget steers selection) and #320 (three-card surface).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(recommend): make Cost funding-aware — hold a $0 model, lower effo…",
          "author_name": "Nathan Ramos, CFA",
          "author_login": "nathanramoscfa",
          "committed_at": "2026-06-28T21:31:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 36,
      "commits_last_year": 391,
      "latest_release_at": "2026-07-22T17:37:36Z",
      "latest_release_tag": "v0.2.29",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 11,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 1.9
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 100,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "roadmodel",
          "exists": true,
          "license": null,
          "keywords": [
            "ai",
            "anthropic",
            "cli",
            "gemini",
            "llm",
            "model-selection",
            "openai",
            "Development Status :: 3 - Alpha",
            "Environment :: Console",
            "Intended Audience :: Developers",
            "License :: OSI Approved :: Apache Software License",
            "Operating System :: OS Independent",
            "Programming Language :: Python :: 3",
            "Programming Language :: Python :: 3 :: Only",
            "Programming Language :: Python :: 3.11",
            "Programming Language :: Python :: 3.12",
            "Programming Language :: Python :: 3.13",
            "Topic :: Software Development",
            "Topic :: Utilities"
          ],
          "ecosystem": "pypi",
          "matches_repo": true,
          "registry_url": "https://pypi.org/project/roadmodel/",
          "is_deprecated": false,
          "latest_version": "0.2.29",
          "repository_url": "https://github.com/nathanramoscfa/roadmodel",
          "versions_count": 34,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2026-05-15T03:48:45.267990Z",
          "latest_published_at": "2026-07-22T17:37:24.996900Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 1,
      "watchers": 0,
      "fork_history": {
        "days": [
          {
            "date": "2026-05-18",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 51
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": true,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "web/tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 51420,
      "source_files_sampled": 237,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "pyproject.toml",
        "service/pyproject.toml",
        "tests/requirements.txt",
        "update/requirements.txt",
        "web/package.json"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm",
        "pypi"
      ],
      "dependencies": [
        {
          "name": "click",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=8.3.3"
        },
        {
          "name": "roadmodel",
          "manifest": "service/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.2.29,<0.3"
        },
        {
          "name": "fastapi",
          "manifest": "service/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.110"
        },
        {
          "name": "uvicorn",
          "manifest": "service/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.27"
        },
        {
          "name": "pydantic",
          "manifest": "service/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=2.6"
        },
        {
          "name": "@google/genai",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.6.0"
        },
        {
          "name": "@supabase/ssr",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.10.3"
        },
        {
          "name": "@supabase/supabase-js",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.106.0"
        },
        {
          "name": "@upstash/ratelimit",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.0.8"
        },
        {
          "name": "@upstash/redis",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.38.0"
        },
        {
          "name": "lucide-react",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.511.0"
        },
        {
          "name": "next",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^15.3.2"
        },
        {
          "name": "react",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.1.0"
        },
        {
          "name": "react-dom",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.1.0"
        },
        {
          "name": "zod",
          "manifest": "web/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.25.28"
        }
      ],
      "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": 27,
        "merged_prs": 354,
        "open_issues": 24,
        "closed_ratio": 0.747,
        "closed_issues": 71,
        "closed_unmerged_prs": 11
      },
      "bus_factor": 1,
      "bot_contributors": 2,
      "top_contributors": [
        {
          "type": "User",
          "login": "nathanramoscfa",
          "commits": 374,
          "avatar_url": "https://avatars.githubusercontent.com/u/86393277?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "auto-remediate.yml",
        "claude.yml",
        "phase-verify.yml",
        "probe-availability.yml",
        "recommend-soak.yml",
        "release.yml",
        "sync-availability.yml",
        "tests.yml",
        "update-claude-code.yml",
        "update-codex.yml",
        "update-deepseek.yml",
        "update-gemini.yml",
        "update-models.yml",
        "verify-pypi.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        ".eslintrc.json"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": null,
            "reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow 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": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 8,
            "reason": "5 out of the last 5 releases have a total of 5 signed artifacts.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 1,
            "reason": "9 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "abfe10fed33b3b85daaf7f8193e193f0ad16e99a",
        "ran_at": "2026-07-22T19:07:59Z",
        "aggregate_score": 4.1,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-22T18:33:17Z",
      "oldest_open_prs": [
        {
          "number": 318,
          "created_at": "2026-06-27T19:40:17Z",
          "last_comment_at": "2026-06-27T19:40:21Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 326,
          "created_at": "2026-06-29T17:13:15Z",
          "last_comment_at": "2026-06-29T17:13:19Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 327,
          "created_at": "2026-06-29T18:47:09Z",
          "last_comment_at": "2026-06-29T18:47:13Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 328,
          "created_at": "2026-06-29T19:44:22Z",
          "last_comment_at": "2026-06-29T19:44:26Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 329,
          "created_at": "2026-06-30T16:55:01Z",
          "last_comment_at": "2026-06-30T16:55:05Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 332,
          "created_at": "2026-07-01T16:58:44Z",
          "last_comment_at": "2026-07-01T16:58:48Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 335,
          "created_at": "2026-07-01T19:43:37Z",
          "last_comment_at": "2026-07-01T19:43:41Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 344,
          "created_at": "2026-07-02T16:47:05Z",
          "last_comment_at": "2026-07-02T16:47:09Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 348,
          "created_at": "2026-07-02T19:40:27Z",
          "last_comment_at": "2026-07-02T19:40:30Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 360,
          "created_at": "2026-07-03T20:23:30Z",
          "last_comment_at": "2026-07-03T20:23:33Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 380,
          "created_at": "2026-07-04T18:08:32Z",
          "last_comment_at": "2026-07-04T18:08:36Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 392,
          "created_at": "2026-07-05T17:16:29Z",
          "last_comment_at": "2026-07-05T17:16:33Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 397,
          "created_at": "2026-07-07T18:08:28Z",
          "last_comment_at": "2026-07-07T18:08:30Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 402,
          "created_at": "2026-07-08T17:37:32Z",
          "last_comment_at": "2026-07-08T17:37:36Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 410,
          "created_at": "2026-07-10T18:30:33Z",
          "last_comment_at": "2026-07-10T18:30:37Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 413,
          "created_at": "2026-07-11T18:02:03Z",
          "last_comment_at": "2026-07-11T18:02:09Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 415,
          "created_at": "2026-07-11T20:13:59Z",
          "last_comment_at": "2026-07-11T20:14:03Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 418,
          "created_at": "2026-07-14T18:11:10Z",
          "last_comment_at": "2026-07-14T18:11:14Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 449,
          "created_at": "2026-07-17T17:20:20Z",
          "last_comment_at": "2026-07-17T17:20:24Z",
          "last_comment_author": "vercel"
        },
        {
          "number": 454,
          "created_at": "2026-07-18T17:05:34Z",
          "last_comment_at": "2026-07-18T17:05:37Z",
          "last_comment_author": "vercel"
        }
      ],
      "last_merged_pr_at": "2026-07-22T17:59:19Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 63,
          "created_at": "2026-05-19T03:06:20Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 65,
          "created_at": "2026-05-19T03:06:47Z",
          "last_comment_at": "2026-06-12T04:13:20Z",
          "last_comment_author": "nathanramoscfa"
        },
        {
          "number": 69,
          "created_at": "2026-05-19T03:29:12Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 81,
          "created_at": "2026-05-19T17:33:43Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 99,
          "created_at": "2026-05-20T18:16:51Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 148,
          "created_at": "2026-06-01T03:19:31Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 185,
          "created_at": "2026-06-05T14:39:38Z",
          "last_comment_at": "2026-06-06T04:35:10Z",
          "last_comment_author": "nathanramoscfa"
        },
        {
          "number": 188,
          "created_at": "2026-06-05T14:39:42Z",
          "last_comment_at": "2026-06-06T04:35:11Z",
          "last_comment_author": "nathanramoscfa"
        },
        {
          "number": 189,
          "created_at": "2026-06-05T14:39:44Z",
          "last_comment_at": "2026-06-06T04:35:12Z",
          "last_comment_author": "nathanramoscfa"
        },
        {
          "number": 201,
          "created_at": "2026-06-06T23:35:50Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 210,
          "created_at": "2026-06-07T15:37:11Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 211,
          "created_at": "2026-06-07T15:37:21Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 254,
          "created_at": "2026-06-12T20:18:29Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 260,
          "created_at": "2026-06-13T17:06:33Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 330,
          "created_at": "2026-06-30T19:38:59Z",
          "last_comment_at": "2026-07-15T19:23:21Z",
          "last_comment_author": "nathanramoscfa"
        },
        {
          "number": 331,
          "created_at": "2026-07-01T16:58:41Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 422,
          "created_at": "2026-07-15T18:07:51Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 438,
          "created_at": "2026-07-16T18:59:55Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 439,
          "created_at": "2026-07-16T18:59:56Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 440,
          "created_at": "2026-07-16T18:59:57Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/nathanramoscfa/roadmodel",
    "host": "github.com",
    "name": "roadmodel",
    "owner": "nathanramoscfa"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 61,
      "inputs": {
        "security": 41,
        "vitality": 76,
        "community": 43,
        "governance": 54,
        "engineering": 86
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 76,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 62,
            "inputs": {
              "commits_last_year": 391,
              "human_commit_share": 0.83,
              "days_since_last_push": 0,
              "active_weeks_last_year": 11
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "11/52 weeks with commits",
                "points": 7.6,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 11
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "391 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 391
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 98,
            "inputs": {
              "releases_count": 36,
              "latest_release_tag": "v0.2.29",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 1.9
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "36 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 36
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~1.9 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 1.9
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "5 out of the last 5 releases have a total of 5 signed artifacts.",
                "points": 8,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 43,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 1,
              "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": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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": "excellent",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 92,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": true,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (Apache-2.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "Apache-2.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 13.5,
                "status": "met",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 54,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 72,
            "inputs": {
              "merged_prs": 354,
              "open_issues": 24,
              "closed_issues": 71,
              "issue_closed_ratio": 0.747,
              "closed_unmerged_prs": 11
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "75% of issues closed",
                "points": 34.9,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 75
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "354/365 decided PRs merged",
                "points": 37.1,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 354,
                      "decided": 365
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 50,
            "inputs": {
              "followers": 25,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "nathanramoscfa",
              "public_repos": 21,
              "account_age_days": 1854
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "25 followers of nathanramoscfa",
                "points": 10.2,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 25,
                      "login": "nathanramoscfa"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "21 public repos, account ~5 yr old",
                "points": 19.9,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 21
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 5
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "roadmodel"
              ],
              "ecosystems": "pypi",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on pypi",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "pypi"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 0 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "34 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 34
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "excellent",
        "name": "Engineering Quality",
        "value": 86,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "14 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 14
                    }
                  }
                ],
                "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": ".eslintrc.json",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".eslintrc.json"
                    }
                  }
                ],
                "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": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": "https://roadmodel-web.vercel.app",
              "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://roadmodel-web.vercel.app",
                "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": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 41,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Branch-Protection. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "branch_protection"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 41,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 4.1
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 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 detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "5 out of the last 5 releases have a total of 5 signed artifacts.",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "9 existing vulnerabilities detected",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 53,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "83 of 83 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 83,
                      "sampled": 83
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "package-lock.json"
              ],
              "has_dockerfile": true,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "web/tsconfig.json"
              ],
              "agent_commit_share": 0.84,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": ".eslintrc.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".eslintrc.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "web/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "web/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "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": "84 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 84,
                      "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": "good",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "primary_language": "Python",
              "largest_source_bytes": 51420,
              "source_files_sampled": 237,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Python with type-check config (web/tsconfig.json)",
                "points": 27,
                "status": "partial",
                "details": [
                  {
                    "code": "typecheck_config_language",
                    "params": {
                      "files": "web/tsconfig.json",
                      "language": "Python"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/237 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 237,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "critical",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "example_dirs": [],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "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 pypi package 'roadmodel-service' from its registry",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
    "deps.dev does not index pypi:roadmodel@0.2.29; advisories assessed against the repository dependency graph instead"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-22T19:08:19.337969Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/n/nathanramoscfa/roadmodel.svg",
  "full_name": "nathanramoscfa/roadmodel",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

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

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

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