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

yishanhe / one-finance-data

one finance data client to rule them all

PythonMIT★ 0 estrellas⑂ 0 forksdesde may 2026Ver en GitHub ↗

yishanhe/one-finance-data tiene un índice de salud de 53 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Engineering Quality (85/100) y la más baja, Community & Adoption (24/100). Se actualizó por última vez hace 3 días. Una sola persona concentra la mayor parte del trabajo reciente.

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

53
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

SyiCuenta personal
60 seguidores27 repositorios públicosdesde jun 2011@facebook

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

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
PyPIonefinance0.1.21-19hace 3 días

Métricas por categoría

Vitalidad

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

72Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 3 días
7.6/36Cadencia de commits — 11/52 semanas con commits
18/18Volumen de commits — 101 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_year101
human_commit_share1
days_since_last_push3
active_weeks_last_year11
Cómo se puntúa
16.2/27Publica versiones — 17 etiquetas de versión (sin releases de GitHub)
36/36Recencia de las versiones — última versión hace 3 días
27/27Cadencia de publicación — una versión cada ~4,2 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count17
latest_release_tagv0.1.21
releases_from_tags
days_since_latest_release3
mean_days_between_releases4,2
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: Signed-Releases. Los pesos restantes se han renormalizado.

Comunidad y Adopción

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

24Crítico · 18% del índice global
Cómo se puntúa
0/60Estrellas — 0 estrellas
0/25Forks — 0 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sostenibilidad y Gobernanza

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

38En riesgo · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
0/22.5Distribución de commits — el principal contribuyente firma el 100% de los commits
1.4/13.5Amplitud de contribuyentes — 1 contribuyentes
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Datos de entrada utilizados
bus_factor1
contributors_sampled1
top_contributor_share1
Cómo se puntúa
0/46.8Resolución de issues — sin issues o sin datos
0/38.3Aceptación de PR — sin PR decididos o sin datos
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
Excluidos de la puntuación (sin datos o no aplicable): Resolución de issues, Aceptación de PR. Los pesos restantes se han renormalizado.
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
12.8/25Alcance del propietario — 60 seguidores de yishanhe
22.5/25Trayectoria — 27 repos públicos, cuenta de ~15 años
Datos de entrada utilizados
followers60
owner_typeUser
is_verified
owner_loginyishanhe
public_repos27
account_age_days5527
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 3 días
20/20Historial de versiones — 19 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packagesonefinance
ecosystemspypi
any_deprecatedno
min_days_since_publish3

Calidad de Ingeniería

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

85Excelente · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 2 flujo(s) de trabajo
24/24Pruebas presentes
16/16Configuración de linter
9.6/9.6Hooks de pre-commit
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — sin datos
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_config
has_precommit_config
Excluidos de la puntuación (sin datos o no aplicable): OpenSSF Scorecard: CI-Tests. Los pesos restantes se han renormalizado.
Cómo se puntúa
30/30README
25/25Directorio de documentación
0/15Sitio de documentación / página del proyecto
10/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepage
has_readme
has_docs_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?

44En riesgo · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — sin datos
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
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
0/5Packaging — sin datos
4/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 8
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — sin datos
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated15
scorecard_versionv5.5.0
checks_inconclusive3
scorecard_aggregate3,3
Excluidos de la puntuación (sin datos o no aplicable): ci_tests, packaging, signed_releases. Los pesos restantes se han renormalizado.
Cómo se puntúa
26.6/35Dependencias directas libres de avisos conocidos — 1 afectados: diskcache 5.6.3 (moderate)
25/25Dependencias indirectas libres de avisos conocidos — ninguna dependencia indirecta tiene un aviso conocido
37.2/40Sin avisos pendientes — 1 paquete(s) con avisos sin atender más allá de 90 días; el más antiguo publicado hace 165 días
Datos de entrada utilizados
sourceosv
advisories2
affected_packages1
assessed_packages39
unassessed_packages0
affected_by_severitymoderate 1
direct_affected_packages1
Se cotejó el cierre de dependencias en tiempo de ejecución de pypi:onefinance@0.1.21 —lo que arrastra la instalación del paquete publicado—: 39 paquetes. No se analiza la alcanzabilidad.

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.

68Moderado · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — AGENTS.md, CLAUDE.md
0/15Documentación legible por máquinas (llms.txt)
40/40Historial de commits legible — 98 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txtno
legible_history_share0,98
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes24.231
Cómo se puntúa
0/18Arranque con un solo comando
22/22Pruebas automatizadas
11/11Configuración de lint / formato
0/11Verificación estática de tipos
10/10Entorno reproducible — lockfile
10/10Práctica demostrada con agentes — 70 de los últimos 100 commits con autoría o crédito de agente
0/8Mantenimiento automatizado — no se observan actualizaciones automáticas de dependencias
8/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 8
Datos de entrada utilizados
has_nixno
has_tests
lockfilesuv.lock
has_dockerfileno
typed_languageno
bootstrap_files
has_devcontainerno
has_linter_config
typecheck_configs
agent_commit_share0,7
toolchain_manifests
dependency_bot_commit_share0
Cómo se puntúa
0/45Código verificable por tipos — Python sin configuración de verificación de tipos
54.4/55Tamaños de archivo manejables — 1/98 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languagePython
largest_source_bytes69.667
source_files_sampled98
oversized_source_files1

Datos clave

0estrellas de GitHub
1contribuidores
101commits en los últimos 12 meses
3días desde el último push
17versiones publicadas
1factor bus
0issues abiertas
PyPIecosistemas de paquetes

Advertencias de recopilación de datos

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

Más detalle

OpenSSF Scorecard 3.3 / 10
3.3agregado

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
n/dCI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
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
n/dPackagingpackaging workflow not detected
8Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 8
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
n/dSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
7Vulnerabilities3 existing vulnerabilities detected
Dependencias directas 7
RegistroPaqueteRestricción de versiónManifiesto
PyPIdiskcache>=5.6pyproject.toml
PyPIpydantic>=2.0pyproject.toml
PyPIpyyamlpyproject.toml
PyPIhttpxpyproject.toml
PyPIyfinancepyproject.toml
PyPItyper>=0.26pyproject.toml
PyPIrichpyproject.toml
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

Avisos de dependencias 1

Instalar pypi:onefinance@0.1.21 arrastra 39 paquetes, directos y transitivos: 1 tienen avisos conocidos, de los cuales 1 son dependencias directas.

PaqueteVersiónRelaciónGravedadAvisosCorregido en
diskcache5.6.3directamoderada2

Un aviso significa que la versión registrada en el grafo de dependencias cae dentro del rango afectado de un aviso. No se analiza la alcanzabilidad, y el grafo incluye fijaciones de desarrollo y prueba: un hallazgo puede referirse al utillaje y no al software distribuido.

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 951,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Python": 1201514
      },
      "pushed_at": "2026-07-24T08:47:21Z",
      "created_at": "2026-05-14T05:52:30Z",
      "owner_type": "User",
      "updated_at": "2026-07-24T08:46:03Z",
      "description": "one finance data client to rule them all ",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Python",
      "significant_languages": [
        "Python"
      ]
    },
    "owner": {
      "blog": "https://yishanhe.net",
      "name": "Syi",
      "type": "User",
      "login": "yishanhe",
      "company": "@facebook",
      "location": "San Jose, CA",
      "followers": 60,
      "avatar_url": "https://avatars.githubusercontent.com/u/838961?v=4",
      "created_at": "2011-06-09T01:52:55Z",
      "is_verified": null,
      "public_repos": 27,
      "account_age_days": 5527
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.1.21",
          "kind": "patch",
          "published_at": "2026-07-24T08:45:22Z"
        },
        {
          "tag": "v0.1.20",
          "kind": "patch",
          "published_at": "2026-07-24T08:19:42Z"
        },
        {
          "tag": "v0.1.19",
          "kind": "patch",
          "published_at": "2026-07-19T02:34:49Z"
        },
        {
          "tag": "v0.1.18",
          "kind": "patch",
          "published_at": "2026-07-09T06:28:37Z"
        },
        {
          "tag": "v0.1.17",
          "kind": "patch",
          "published_at": "2026-07-03T17:21:14Z"
        },
        {
          "tag": "v0.1.16",
          "kind": "patch",
          "published_at": "2026-06-29T05:50:57Z"
        },
        {
          "tag": "v0.1.15",
          "kind": "patch",
          "published_at": "2026-06-28T23:27:13Z"
        },
        {
          "tag": "v0.1.14",
          "kind": "patch",
          "published_at": "2026-06-27T07:04:20Z"
        },
        {
          "tag": "v0.1.13",
          "kind": "patch",
          "published_at": "2026-06-20T02:48:57Z"
        },
        {
          "tag": "v0.1.12",
          "kind": "patch",
          "published_at": "2026-06-16T10:07:10Z"
        },
        {
          "tag": "v0.1.11",
          "kind": "patch",
          "published_at": "2026-06-16T01:49:22Z"
        },
        {
          "tag": "v0.1.10",
          "kind": "patch",
          "published_at": "2026-06-12T06:42:21Z"
        },
        {
          "tag": "v0.1.9",
          "kind": "patch",
          "published_at": "2026-06-10T07:54:57Z"
        },
        {
          "tag": "v0.1.8",
          "kind": "patch",
          "published_at": "2026-06-03T19:19:41Z"
        },
        {
          "tag": "v0.1.7",
          "kind": "patch",
          "published_at": "2026-06-01T22:16:33Z"
        },
        {
          "tag": "v0.1.6",
          "kind": "patch",
          "published_at": "2026-05-30T06:40:00Z"
        },
        {
          "tag": "v0.1.4",
          "kind": "patch",
          "published_at": "2026-05-17T07:19:33Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "51ee22afa2d52fd88dff94f350e14749c56ae2f6",
          "body": "Replace direct click dependencies with Typer's core type hierarchy (Command, TyperGroup, Parameter)\nand duck-typed choices inspection in _capabilities.py. Also update test_cli_app.py to import Result from typer.testing.",
          "is_bot": false,
          "headline": "refactor(cli): migrate capabilities introspection to Typer 0.26+ types",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-24T08:45:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e22e140313a5809c0246cb908a723d70772d7233",
          "body": "Typer 0.16+ dropped click as a dependency and changed internal types\n(TyperCommand no longer inherits from click.Command). The CLI manifest\ngenerator (_capabilities.py) introspects click.Group/Command/Choice/\nParameter types, which breaks with typer>=0.16.\n\nThis fixes the smoke test failure:\n  ModuleNotFoundError: No module named 'click'\n  Command '['ofclient', '--help']' returned non-zero exit status 1",
          "is_bot": false,
          "headline": "fix(deps): pin typer<0.16 to keep click dependency",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-24T08:34:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a2e30818c194e158aac8ad553aa614d41526a4f9",
          "body": null,
          "is_bot": false,
          "headline": "refactor: modularize client internals and remove Tradier",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-24T08:19:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "28b3b0be05bcb7672d522a89f6bcca21343ca016",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: log open issue — yfinance near-zero open interest on active chains",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-19T02:34:49Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "50afe8219fd85a362c0c1aed1dc2c586b4360485",
          "body": "…iendly CLI\n\nRouter:\n- BaseProvider.KNOWN_MISSING_FIELDS lets a provider declare fields its\n  API can never populate (Finnhub /quote has no volume). The router then\n  starts the augment filler concurrently with the primary call instead\n  of serially after it, hiding ~400ms of per-quote latency. Pref\n[…]\nnd environment variables.\n\nDocs: CLAUDE.md capability matrix gains the Cboe column; augment\nsection documents prefetch and the new stats fields.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: concurrent augment prefetch, audit enrichment metrics, agent-fr…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-19T02:34:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6671bd66c774788adbc5cc86bd5f8a6fe49bacdc",
          "body": "Concurrent requests for the same cache key now share a single provider\ncall via a bounded-lifetime keyed lock pool: the first caller fetches\nand stores, waiters re-check the cache after acquiring the lock and\nserve the fresh entry. no_cache requests bypass coalescing.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(client): coalesce concurrent cache-miss fetches per cache key",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-19T02:34:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "715c9164896674b08befd889248683c486b4c800",
          "body": "…ontract\n\nAudit-log review findings, all live-verified:\n- C1: endpoint_ok marker (7d TTL) vetoes global 402/403 bench when the\n  (provider, endpoint) succeeded recently; success heals an existing bench.\n  One plan-gated symbol no longer disables a whole endpoint for 24h.\n- C2: augment filler calls r\n[…]\ng.\n\nAlso includes the keyless Cboe volatility-index quote provider (B4).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01NU2QVpSVFWo4JvWtXnUUiW",
          "is_bot": false,
          "headline": "feat: audit-driven reliability fixes (C1-C7) + indicators freshness c…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-09T06:28:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a3324c140839a7a1c3f134ad12fd866d6c93780f",
          "body": "…id/endpoint/symbol params\n\nBundles request_id, endpoint, symbol, and cache_key into one AuditContext\nobject threaded through the router and client, cutting repetitive\nparameter plumbing across every record_* call site. Also adds\nRouterCache/AuditSink protocols in place of bare Any typing, and splits\n_cached_fetch/_cached_batch_fetch into smaller focused helpers.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_016NrJn3o2FWcvMacdNxSbdc",
          "is_bot": false,
          "headline": "refactor(audit): introduce AuditContext to replace scattered request_…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-05T15:41:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8da4eef87f64b199b66251f521383a00bf6c491e",
          "body": "Drop the 15 done/already-resolved entries from the 2026-07-03 triage and\nprior sessions; keep only what's still actionable.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CbEDvLxsJKGRuZkopjvwdM",
          "is_bot": false,
          "headline": "docs: trim FEEDBACK.md to open/deferred items only",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-03T17:21:14Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3865ce652f43c098297069a94ab82440e0c66493",
          "body": "Triaged a 22-item skill-library feedback doc (A1-D6) against current code\nand fixed the six items that were real, in-repo-fixable, and testable\nwithout live API keys:\n\n- quote: reject comma/space-containing symbol input up front with a clear\n  error pointing at `quotes`, instead of it silently misbe\n[…]\nlume validation, treasury rates, 13F holdings, batch\ncompany profiles).\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CbEDvLxsJKGRuZkopjvwdM",
          "is_bot": false,
          "headline": "fix: address top-priority items from external ofclient feedback audit",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-03T15:28:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0d70730262e446c705ba0574577cbf69b49fc2fe",
          "body": "Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CbEDvLxsJKGRuZkopjvwdM",
          "is_bot": false,
          "headline": "docs: mark P5 complete in improvement-plan",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-02T21:13:55Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "96740af6943bb62da0a340170a1ba4ab2d99a7c8",
          "body": "Finishes P5 from docs/improvement-plan.md:\n\n- AuditLog.record no longer opens/closes the file per call — keeps a\n  line-buffered handle open across the process lifetime (flushed per\n  line, so durability is unchanged) and only closes it in close()/clear().\n  This was a syscall pair on the hot path f\n[…]\ncan only narrow the staleness window a caller observes, never widen it.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CbEDvLxsJKGRuZkopjvwdM",
          "is_bot": false,
          "headline": "perf: reuse audit-log file handle + add in-process cache memo layer (P5)",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-02T21:13:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "24ac71f5244cc434812e4afa248a9de6118fb1a2",
          "body": "Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CbEDvLxsJKGRuZkopjvwdM",
          "is_bot": false,
          "headline": "docs: mark improvement-plan phases 1-3 complete",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-02T20:26:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "946f51356e846983e512e37f55d38d0e0dcb20c6",
          "body": "Implements F2 of docs/improvement-plan.md — the options-analytics tier\nnamed as the downstream goal of the Tradier greeks provider work:\n\n- onefinance/options/core.py: compute_gex (per-strike dealer gamma\n  exposure, aggregated across expirations, with an approximate gamma-flip\n  strike) and compute\n[…]\nas available), rather than\n  returning a meaningless all-zero snapshot.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CbEDvLxsJKGRuZkopjvwdM",
          "is_bot": false,
          "headline": "feat: add GEX (gamma exposure) and max-pain options analytics",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-02T20:26:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3445b5822feb807775e589a4053f3ef430af6fb0",
          "body": "…h/single fixes\n\nImplements Phase 1+2 of docs/improvement-plan.md:\n- Trading-day-aware range coverage + delta-fetch for daily price history\n  (skip weekend/holiday refetches, fetch only the new tail on partial overlap)\n- Cache quote-augment fillers (volume) per symbol instead of re-fetching on\n  eve\n[…]\nsult\n- New `ofclient warm` command to prefetch a watchlist concurrently\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CbEDvLxsJKGRuZkopjvwdM",
          "is_bot": false,
          "headline": "perf: cache-hit-rate improvements (P1-P6) + cache warm command + batc…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-02T20:21:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "27f01179ae69bea2a14f2230d8de0e88dd1c7846",
          "body": "…tion",
          "is_bot": false,
          "headline": "fix(audit): Remove redundant variable in hit-rate denominator calcula…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-02T04:31:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a39588730da2f3a8fe00cd4350b45e7d9c474cc6",
          "body": "Every httpx-based provider repeated a byte-identical block translating a\nnon-200 response into ProviderError(code=\"NETWORK_ERROR\", retry_safe on\n5xx, http_status set). Hoist it into HttpProviderMixin._raise_for_status\nand call it from all 8 sites (fmp, finnhub, twelve_data, alpha_vantage x2,\nmassive\n[…]\ne other providers.\n\nNet -33 lines. 985 tests pass; ruff and mypy clean.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AB62e7pkGr5BTZ4qdwLZiA",
          "is_bot": false,
          "headline": "refactor(providers): centralize generic non-2xx HTTP error mapping",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-01T18:41:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "61260251507ad347f4a8675f723fa0ec29bfd1b3",
          "body": "Three mechanical cleanups to the ~21 near-identical endpoint methods,\nstandardizing their shape without changing behavior:\n\n- Push default-TTL resolution into _cached_fetch. It already receives\n  endpoint and fresh, so it now resolves self._default_ttl(endpoint,\n  fresh=fresh) when ttl is None. Remo\n[…]\nt_quote/get_dcf/get_analyst_data.\n\n985 tests pass; ruff and mypy clean.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AB62e7pkGr5BTZ4qdwLZiA",
          "is_bot": false,
          "headline": "refactor(client): reduce endpoint-method boilerplate",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-01T11:05:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "39b9418f3392ac040ab3348d81b9d95ae1b51798",
          "body": "…t rate\n\nThe cache_hit_rate denominator used total_calls (provider attempts), so a\nsingle miss that fell back or augmented registered as multiple misses,\nunderstating the rate. Every quote — finnhub primary + yfinance\nvolume-augment sharing one request_id — counted as two misses.\n\nSwitch the denomin\n[…]\nchange. Adds a regression test proving augment no longer\ndouble-counts.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01AB62e7pkGr5BTZ4qdwLZiA",
          "is_bot": false,
          "headline": "fix(audit): count provider-served requests, not attempts, in cache hi…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-07-01T11:05:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5aa11e25483f87d6ef3dbd5c8df0f1738dc8097b",
          "body": "- null_key for insider-trade subsumption only computed when since_d is set\n- _slice_insider_trades: drop redundant None guard (isinstance handles it)\n- _cached_batch_fetch: hoist len(batch_result) to n_got, used in both\n  the warning and the truncation slice\n- get_news: skip list allocation when art\n[…]\nlimit\n- manager.py: trim redundant calendar subsumption prose comment\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CHTi12LiEZrvk6RKVnRbSp",
          "is_bot": false,
          "headline": "refactor: micro-cleanups from second simplify pass",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-29T10:16:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ade0f95e9af1a3972f9ba2b39100ef9c8588e154",
          "body": "- Extract _find_covering_range + _record_range_index private helpers;\n  price and calendar subsumption methods delegate to them, eliminating\n  ~30 lines of structural duplication\n- _slice_price_bars → _slice_range_items(items, start, end, attr=\"date\")\n  with operator.attrgetter; shared by price (att\n[…]\nn\n- record_calendar_range: drop ttl param, use class constant instead\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CHTi12LiEZrvk6RKVnRbSp",
          "is_bot": false,
          "headline": "refactor: deduplicate range-index subsumption in CacheManager",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-29T09:44:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "83bfdd40fc182c0f8ca9b786fb96e2751440818f",
          "body": "- Drop `fresh` from get_ratios/get_earnings cache keys (fresh=True and\n  fresh=False fetched identical data under separate keys)\n- get_news: remove `limit` from cache key; always fetch _NEWS_FETCH_MAX=50,\n  slice to caller's limit — eliminates limit=10/limit=20 key splits\n- get_forward_estimates: ad\n[…]\nms than requested\n- CLI: add -h as alias for --help on all Typer apps\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CHTi12LiEZrvk6RKVnRbSp",
          "is_bot": false,
          "headline": "fix: cache hit rate improvements + -h flag for --help",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-29T05:50:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "aaafe3378971744db17955851efdf51db99fee9f",
          "body": "This reverts commit 399196ecc72fdfec0be122333132410474442d40.",
          "is_bot": false,
          "headline": "Revert \"feat: add version field to audit log + version-based truncation\"",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-29T00:18:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "399196ecc72fdfec0be122333132410474442d40",
          "body": "Every audit entry now carries a `version` field (the running package\nversion, resolved once via importlib.metadata).  `AuditLog.truncate_before_version(v)`\nrewrites the log keeping only entries >= v; entries with no version field\n(written before this release) are treated as pre-versioning and removed.\nCLI: `ofclient audit truncate --before-version X.Y.Z --confirm`.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01EKrwQvrwhyq1BTbpGVyPek",
          "is_bot": false,
          "headline": "feat: add version field to audit log + version-based truncation",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-28T23:43:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "79d2c9c8fa42bbf39ebfeb144600c9f2af83ee6a",
          "body": "…ns 302/404\n\nThe FMP /stable/analyst-ratings endpoint is deprecated and redirects to an\ninvalid double-prefixed URL (302 -> 404). Previously this crashed the whole\nget_analyst_data call even when price-target-consensus succeeded.\n\nWrap the sub-call in try/except so price-target data is still returned when\nratings data is unavailable.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01EKrwQvrwhyq1BTbpGVyPek",
          "is_bot": false,
          "headline": "fix: FMP analyst_data — degrade gracefully when analyst-ratings retur…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-28T23:27:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fb8b10c8113cf9ed4d8036a61fe38fb33088b8bc",
          "body": "New endpoints implemented across 5 providers:\n\nAlpha Vantage (3):\n- get_insider_trades via INSIDER_TRANSACTIONS\n- get_corporate_actions via DIVIDENDS + SPLITS (two calls, merged)\n- get_earnings_calendar via EARNINGS_CALENDAR (CSV response)\n\nTwelve Data (3):\n- get_info via /profile\n- get_news via /ne\n[…]\ne tier lists.\n41 new unit tests added (984 total), ruff + mypy clean.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01EKrwQvrwhyq1BTbpGVyPek",
          "is_bot": false,
          "headline": "feat: add 9 provider endpoints + EconomicEvent macro calendar",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-28T23:14:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "46074f682a1e19980c83f7f60f73921b77e7337d",
          "body": "Cache / TTL:\n- ttl_for_quote(): 30s open / 2min closed / 30min weekend (was flat 30s)\n  eliminates redundant quote fetches in batch scan workflows\n- yfinance get_option_chain: raise ProviderError(EMPTY_RESPONSE) when both\n  calls+puts empty — prevents caching empty weekend chains for 4h; lets\n  rout\n[…]\nsee individual diffs)\n- CLI: peers command + related app.py additions\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01EKrwQvrwhyq1BTbpGVyPek",
          "is_bot": false,
          "headline": "fix: cache hit rate improvements + peers endpoint + provider fixes",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-27T07:04:20Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a0c6e14fb94b3f8bf04b0afef636bedde9c422bd",
          "body": "Tradier provider (options + ORATS greeks):\n- New TradierProvider for get_options_expirations and get_option_chain\n- Parses ORATS greeks (delta/gamma/theta/vega/rho/smv_vol) onto OptionContract\n- Handles single-item scalar quirk from Tradier JSON\n- Sandbox default (TRADIER_SANDBOX=0 for prod); TRADIE\n[…]\n) to\n  human-readable labels (current_Q, next_Q, current_FY, next_FY)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01GnFdqwry1CvAXVS71ZLpoh",
          "is_bot": false,
          "headline": "feat: add Tradier provider + fix FMP URL bug + CLI improvements",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-25T04:04:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "81999820456bac645d33f2c4c20a1a2682c88d5a",
          "body": "Polygon.io rebranded to Massive in October 2025. Rename the provider id\npolygon -> massive across config tiers, factory registration, doctor, CLI\nsample config, tests, and docs. Default base URL is now api.massive.com\n(legacy api.polygon.io still works in parallel). The provider reads\nMASSIVE_API_KE\n[…]\nys and audit history are keyed by the provider id, so they reset/split.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01GUBEBwN5o7Ln6UuCAU3nAx",
          "is_bot": false,
          "headline": "refactor: rename Polygon provider to Massive (rebrand)",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-22T05:57:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a3fb260a307ba20f8a8e8b6822bb5c6e5075f2cc",
          "body": "Integrate the SEC's free XBRL data API as a 5th source for financials —\nthe authoritative primary filings, not a reseller. No API key required\n(SEC asks for a descriptive User-Agent via EDGAR_USER_AGENT).\n\nget_financials reconstructs income/balance/cashflow from the raw\ncompanyfacts XBRL:\n- Periods \n[…]\ndated.\n\n904 unit tests pass; live integration green; ruff + mypy clean.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01XWZEiHTph5ALqqXSMVjv3R",
          "is_bot": false,
          "headline": "feat: add SEC EDGAR provider (financials) — keyless, authoritative",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-21T09:45:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0486f2840b741831fbee7c78b04230ac281cf45a",
          "body": "The mean latency hides tail behavior — a provider that's 80ms typical but\n4s at p99 looks identical to a steady-200ms one. Add nearest-rank p50/p95/p99\nper provider, computed from the same per-attempt latency pool as the mean\n(every real attempt, success or failure — \"how slow when it responds\").\n\n-\n[…]\ncted, not gated.\n\nCLAUDE.md updated. 891 tests pass; ruff + mypy clean.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01XWZEiHTph5ALqqXSMVjv3R",
          "is_bot": false,
          "headline": "feat: report per-provider latency percentiles in audit stats",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-21T06:32:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "45d333c597f2adf8cc8972c6c3de33d02c0a69d2",
          "body": "Options endpoints had a single provider (yfinance) and thus no fallback.\nAdd get_options_expirations and get_option_chain to Polygon and extend\ntheir tier lists to [\"yfinance\", \"polygon\"], so an options request now\nhas a second source.\n\n- Expirations from /v3/reference/options/contracts; chain from\n\n[…]\nLAUDE.md\nmatrix + footnote updated.\n\n889 tests pass; ruff + mypy clean.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01XWZEiHTph5ALqqXSMVjv3R",
          "is_bot": false,
          "headline": "feat: add Polygon options support for provider redundancy",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-21T05:08:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7f805ec53d3c8da565c210d2b98151f0c5fc6ca1",
          "body": "Extend the stale-on-error observability with two operator-facing signals:\n\n- stale_serve_rate — stale_serves / (calls + cache_hits + stale_serves).\n  Stale serves now share the single request denominator with\n  cache_hit_rate; since stale_serves is 0 in any pre-feature period,\n  existing cache_hit_r\n[…]\nread\nback None). CLAUDE.md updated.\n\n880 tests pass; ruff + mypy clean.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01XWZEiHTph5ALqqXSMVjv3R",
          "is_bot": false,
          "headline": "feat: track stale-serve rate and freshness age in audit stats",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-21T04:24:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8a0ca710f8f2c7d35366313cc8c45319bfdbc819",
          "body": "Add an availability layer: when every provider fails\n(AllProvidersFailedError), serve a long-lived last-known-good (LKG)\ncopy instead of raising. On each successful fetch the client\ndual-writes the result under an `lkg:{cache_key}` key with an\nendpoint-volatility-aware TTL; the error path consults i\n[…]\nritten; no_cache only skips reads).\n\n879 tests pass; ruff + mypy clean.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01XWZEiHTph5ALqqXSMVjv3R",
          "is_bot": false,
          "headline": "feat: stale-on-error cache fallback with last-known-good copies",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-21T04:18:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "df0c48c0f06bb20cec833ee2659c6d7bdabcb484",
          "body": "…nhub\n\nAlpha Vantage OVERVIEW function already returns TTM ratio data (P/E, P/B,\nP/S, margins, ROE, ROA, dividend yield, book value/share, revenue/share);\nexpose it as get_ratios and add alpha_vantage to the ratios tier.\n\nFinnhub /stock/dividend + /stock/split provide 5-year corporate action\nhistory on the free tier; expose as get_corporate_actions and move finnhub\nto the front of the corporate_actions tier behind fmp.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add get_ratios to AlphaVantage and get_corporate_actions to Fin…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-20T02:48:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8ef8d5babe574d565f8f074eb614d43bcb5160f1",
          "body": null,
          "is_bot": false,
          "headline": "docs: update TTLs, cache key design, negative caching, provider matrix",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-19T23:08:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aa36d6df1a414abc27e03280219970a02708e417",
          "body": "Endpoints whose data changes on a daily cadence now include\ndate.today() in their cache key:\n\n  ratios      — P/E, margins etc. move with price every trading day.\n                7-day cache with yesterday's price is misleading.\n  financials  — New quarter released any day; stale Q should not\n      \n[…]\ngs (were 7d) — keeping\n7d with a daily key would just waste cache storage on stale entries\nthat can never be reused after the key rolls over.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: add date to cache keys for time-sensitive endpoints",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-19T22:14:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4ea218c6631e0831c0af456af65ff2c8bf78edce",
          "body": "Trim returned bars to [start_d, end_d] inclusive regardless of provider\nor cache source. Prevents out-of-range bars (provider returns extra head/\ntail data) from causing date misalignment when comparing multiple symbols.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: enforce [start, end] date boundary on price_history results",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-19T22:07:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7aa43633ae2b78020980b5d74315c15239a8fa69",
          "body": "Negative caching: router writes a 24h not_supported marker per\n(provider, endpoint, symbol) on NotSupportedError; subsequent requests\nskip that provider without an HTTP call.\n\nSmart TTLs:\n- price_history: 30d (fully historical), 30min (multi-day market open),\n  1min (today-only market open), 6h (mar\n[…]\nontent' key format (≥0.2.54) with\nflat fallback for older releases.\n\nhttpx: follow_redirects=True for FMP (avoids 302→404 on some endpoints).\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf: reduce API calls and improve cache hit rate",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-19T18:36:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "99d144e5ee095122aba00b26e51fc9f93d59aa02",
          "body": "- Update tagline to include Alpha Vantage and Polygon.io\n- Rename \"Environment variables\" to \"Setup\" with subsections\n- Add export snippets with signup URLs so users know where to get keys\n- Add free-tier limits column to provider key table\n- Move CLI env overrides into the Setup section (removed duplicate)\n- CLAUDE.md env vars already current (no changes needed)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: expand README setup section and update provider list in tagline",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-17T04:42:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "24f15667972486b1f5e915e6ba0f255d9b65a1df",
          "body": "Implements PolygonProvider covering get_price_history, get_quote, get_info,\nget_news, and get_corporate_actions (dividends + splits via Reference API).\n\nKey details:\n- Aggregates endpoint with adjusted=true for price history\n- Snapshot endpoint for quotes (15-min delayed on free tier)\n- Reference ti\n[…]\nistory, after finnhub in quote, and before alpha_vantage/\nyfinance for info/news/corporate_actions.\n\n100% line coverage across 55 unit tests.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add Polygon.io as a data provider",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-17T04:33:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "335261cec5480732c98c3eb4ee2cce420143372a",
          "body": "Add 18 tests covering previously uncovered branches:\n- _parse_av_datetime ISO fallback\n- _rate_limit_signals with non-200/non-429 status, JSON parse errors, non-dict body\n- is_rate_limited / cooldown_for with Exception and non-httpx inputs\n- _get with non-200 status and benign Note key (no rate-limi\n[…]\nrdcoding \"annual\")\n- get_earnings skipping records with missing fiscal date\n- get_news with unparseable timestamp, missing title, missing URL\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: achieve 100% coverage for AlphaVantageProvider",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-17T04:14:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6b0c5c5e6a2606c8990a13a7119a653bf1757ec9",
          "body": "Implements AlphaVantageProvider covering get_price_history, get_quote,\nget_info, get_financials (income/balance/cashflow), get_earnings, and\nget_news. Rate limits are detected from JSON body (Note = per-minute,\nInformation = daily) in addition to HTTP 429.\n\nWired into factory registry, default config, and tier lists. AV placed\nlast for quote (15-min delay + 25/day free quota) and before yfinance\nfor fundamentals (more structured data).\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add Alpha Vantage as a data provider",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-17T03:59:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6b1b16709b5fc6a402fd2675d94930d945f18ea7",
          "body": "Populate market_cap in get_quote for FMP (marketCap from /quote endpoint)\nand YFinance (marketCap from ticker.info); None for Finnhub/TwelveData.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add market_cap field to Quote model",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-16T10:07:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0ee6ebe01c6dca4bffa26b6ebb381d8dafd1a0c8",
          "body": "…dpoints\n\ndocs/ held completed implementation plans and a stale v1 design draft, all\nsuperseded by CLAUDE.md and TODO.md. README/TODO were missing DCF, options\nanalytics, short interest, and market sentiment endpoints added since M10.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: remove outdated planning docs, sync README/TODO with current en…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-16T04:41:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3b0903853ae9c0b71dd80cfceea63263d49cb378",
          "body": "Cache stats:\n- Add lifetime hit/miss ratio to CacheManager.stats() via diskcache statistics=1\n- CLI cache stats command shows hit rate and merges audit provider usage\n\nAudit stats:\n- Add per-endpoint call/error breakdown (calls_by_endpoint, errors_by_endpoint)\n- Add fallback detection via request_id\n[…]\nonce per TTL\n- Augment status logged in audit; excluded from fallback grouping\n- Fixes Finnhub free tier returning volume=0 on quote endpoint\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: observability improvements and null-fill provider merge",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-16T01:49:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "172ab837404eef75477aa8bd168d4c11f1d8cad0",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: add yfinance live integration test for get_options_analytics",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:26:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bf9aeea10b2115e9e21ec70fc1256622e12a63d2",
          "body": null,
          "is_bot": false,
          "headline": "fix: update FMP supported endpoint count to 17",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:24:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1528b8c9e4660153c3be487d7c31169aa2df693d",
          "body": "…ckage",
          "is_bot": false,
          "headline": "feat: export OptionsAnalytics, ShortInterest, MarketSentiment from pa…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:23:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0a1261b748e1c1ce3e2d0f0c5c56ed716a2f247",
          "body": null,
          "is_bot": false,
          "headline": "feat: add options-analytics, short-interest, sentiment CLI commands",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:23:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7e662a279caa32c530f4c3bda3a9ada479a682d5",
          "body": "…ment to client",
          "is_bot": false,
          "headline": "feat: add get_options_analytics, get_short_interest, get_market_senti…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:22:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a8fb189b145d3d5b47ecc3862ae3067aa182864",
          "body": null,
          "is_bot": false,
          "headline": "feat: implement FMPProvider.get_short_interest and get_market_sentiment",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:19:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "162ccd8d010265adc931eecd9e075a5e38e93ae9",
          "body": null,
          "is_bot": false,
          "headline": "feat: implement YFinanceProvider.get_short_interest",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:17:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9de33688fb1c582038feaf990ad5bfc2f5c5512a",
          "body": null,
          "is_bot": false,
          "headline": "feat: add short_interest and market_sentiment stubs and TTLs",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:16:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0f86a733f677365e1e53a775e3385710602c4cb1",
          "body": null,
          "is_bot": false,
          "headline": "feat: add OptionsAnalytics, ShortInterest, MarketSentiment models",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:15:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5837fa1ae39f2ccebc093fd4b728c7b2c4be8cca",
          "body": null,
          "is_bot": false,
          "headline": "feat: add Bollinger Bands to compute_indicators",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:15:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff779aecc8000ad40ddb93956c98b1623301e80c",
          "body": "12 tasks covering BB, OptionsAnalytics, ShortInterest,\nMarketSentiment — models, providers, client, CLI, tests.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add indicators expansion implementation plan",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T09:10:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "45413c6026176bf97abe96d5298fdf66547df1b2",
          "body": "Covers Bollinger Bands, symbol-level PCR, short interest,\nand market-wide PCR endpoints.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add indicators expansion design spec",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T08:52:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "948325593538b84d015979e48bf10212686139cb",
          "body": null,
          "is_bot": false,
          "headline": "docs: Update CLAUDE.md and README.md to reflect current feature set",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T07:32:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2ba5dd060a92615375a4a632d3c3e3a68752fe1c",
          "body": null,
          "is_bot": false,
          "headline": "fix: Handle list[date] in cache serialisation (options expirations)",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-12T06:42:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "30a235260fc9c3d95ae12d7185b310d611d8ca97",
          "body": null,
          "is_bot": false,
          "headline": "feat: Add hybrid batch quotes support and ofclient quotes command",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-10T07:54:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bff8d487e01c19479fa8d0a5c3ec7a52b3b958f9",
          "body": "…ider_trades\n\nyfinance now covers all FMP/Finnhub endpoints it can serve as fallback\nfor. get_ratios returns a single TTM snapshot (period arg ignored).\nget_earnings maps earnings_history DataFrame; revenue fields are None.\nget_insider_trades infers trade type from Text field; shares_owned_after\nis unavailable and left None.",
          "is_bot": false,
          "headline": "feat(yfinance): add get_financials, get_ratios, get_earnings, get_ins…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-03T19:19:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "861016b0eedf6c038dd1d32888bd881089d24945",
          "body": "…rtedError\n\n- New EarningsCalendarEntry model with report_date, year, quarter,\n  eps/revenue estimate/actual, time_of_day (bmo/amc/dmh)\n- get_earnings_calendar(start, end, symbol=) on client + all providers;\n  Finnhub supports full date-range, FMP returns current week (free tier)\n- ofclient calendar\n[…]\nading\n- 4-hour TTL; cache key is date-range only, symbol filter applied post-fetch\n- 21 new unit tests across fmp, finnhub, and client layers\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "v0.1.7: add earnings calendar API (Finnhub + FMP), FMP 402 → NotSuppo…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-06-01T22:16:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ded24eaa9c113f802c6dbfcd5e6832509793c516",
          "body": null,
          "is_bot": false,
          "headline": "docs: clarify release process and _version.py warning in CLAUDE.md",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-05-30T06:45:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f11551ab81b00e991b8fa54b94a2d5d36f25a080",
          "body": "…follow CLI",
          "is_bot": false,
          "headline": "v0.1.6: fix audit logging (symbol + http_status), add audit truncate/…",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-05-30T06:40:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "020d8673b0ac2a1bc04ed740a30eea3058a7bbdd",
          "body": "- test_yfinance_provider: guard `top_companies` None-check before `in`\n- test_finnhub_provider: annotate bare `dict` as `dict[str, object]`\n- .pre-commit-config.yaml: add local mypy hook (uv run mypy onefinance tests)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci: add mypy to pre-commit; fix two type errors in tests",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-05-26T05:01:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d3db27a6eae59208d30a91226a0d24ef00cf2c56",
          "body": "Adds targeted unit tests across all providers, client, and CLI modules.\nCovers new endpoints (news, corporate actions, holders, analyst data,\noptions, DCF, screener, sector overview, forward estimates), edge cases,\nand error paths previously untested.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: raise coverage from 75% to 90%",
          "author_name": "Shanhe Yi",
          "author_login": "yishanhe",
          "committed_at": "2026-05-26T03:05:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "545dc575f9161d2f7e85af10bf8f7b9eb9317f20",
          "body": null,
          "is_bot": false,
          "headline": "chore: exclude generated _version.py from ruff",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-18T05:12:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3b9fb029e1c26299816aa392a543110bb0d2970f",
          "body": null,
          "is_bot": false,
          "headline": "feat: add new core modules, providers, and related tests",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-18T05:08:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9ae9a2c7e8bef2077aebba099f5a6bcbdc572ec0",
          "body": "- Add `pre-commit` to dev dependencies in `pyproject.toml`.\n- Create `.pre-commit-config.yaml` with `ruff` and `ruff-format` hooks.\n- Apply `ruff check --fix` and `ruff format` across the tracked codebase.",
          "is_bot": false,
          "headline": "chore: add pre-commit and apply ruff formatting",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-18T05:07:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6cd6326a5dde60a4af6d5bba16b479e2deea447b",
          "body": "`@v8` is not a published floating tag; the action only ships exact-version\ntags. Pin to the v8.1.0 commit SHA, matching the form recommended by the\nuv docs and the GitHub Actions hardening guide.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci: pin astral-sh/setup-uv to v8.1.0 SHA",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-17T07:19:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a73a37bc6c6cd11ec9e735d92c4c1be5c99d6f31",
          "body": "Brings the test suite up to mypy strict mode so `uv run mypy onefinance\ntests` (the documented CLAUDE.md command, now also the CI step in\npython-package.yml) passes end to end.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "tests: add return-type annotations across the test suite",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-17T07:11:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "329b2558fc4e1defb14a4f154166baa49ea176b3",
          "body": "- New publish.yml: tag-triggered (v*) workflow that runs uv build, smoke-tests\n  the wheel and sdist in isolated envs, and publishes to PyPI via trusted\n  publishing (OIDC). A verify step fails before upload if the tag and the\n  built artifact version don't match.\n- Migrate python-package.yml to uv:\n[…]\ntall.\n- CLAUDE.md: new \"Releasing to PyPI\" section documenting the tag-and-push\n  release flow plus the one-time PyPI/GitHub environment setup.\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci: automate PyPI release via uv + hatch-vcs",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-17T07:11:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6041b73f9ec2f3fa32f60857fdc2a0929f0e0ae4",
          "body": "Bring the codebase to 0 ruff and 0 mypy errors.\n\nMechanical:\n- ruff --fix + ruff format: Optional[X] → X | None, timezone.utc → UTC,\n  unused imports, line wrapping (224 auto-fixes across the tree)\n- Add -> None to all 24 Typer command functions\n- dict → dict[str, Any] where bare dict was used\n- Add\n[…]\n check: 0 errors\n- mypy: 0 errors\n- pytest -m \"not integration\": 360 / 360 pass\n- ofclient providers check --ping: still returns valid envelope\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: lint cleanup — ruff + mypy clean",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-17T06:39:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "39d7edbbd420f0bf6a4bbc5a3f1bf538fe467605",
          "body": "This workflow installs Python dependencies, runs tests, and lints code using multiple Python versions.",
          "is_bot": false,
          "headline": "Add GitHub Actions workflow for Python package",
          "author_name": "Syi",
          "author_login": "yishanhe",
          "committed_at": "2026-05-17T06:27:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b88f460443ed7f16d0c4ea7b32e7c29f445715cf",
          "body": "- ofclient indicators SYMBOL: technical snapshot (MA, MACD, RSI, ATR,\n  bias, trend_status, volume, support/resistance) from cached bars\n- ofclient providers check [--ping]: validate provider config (API\n  keys, instantiation, tier membership, tier-ref integrity) and\n  optionally call get_quote() to\n[…]\nness\n- OneFinanceClient.get_indicators() and check_providers() library APIs\n- Capabilities manifest enumerates every indicator field for agents\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add indicators and providers check commands, bump to 0.1.3",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-17T06:13:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0d819662384a3942fbced8538a5a43b765901bb1",
          "body": "diskcache hit/miss counting is opt-in; without `statistics=1` at init\nthe counters never start. Additionally, calling `stats(enable=False)` on\nread was shutting off tracking on every invocation. Both bugs combined to\nkeep hits and misses permanently at zero in `ofclient cache stats`.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: enable diskcache statistics so cache stats hits/misses are tracked",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T20:05:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1a468ad484d8ada001230b8db4f3de89e2eb239a",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add pipx as install option for externally-managed Python",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:46:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4ba759662a28a285ccf7de29fa522c4555152650",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add pip3 --break-system-packages as alternative install",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:46:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a8a1e9673f4fadb62254dfdb307c42bbac0e93d5",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add uv tool install instructions for Homebrew Python",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:42:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4a7da1a72413658bfa277f05e9c4a7c5ab1d0115",
          "body": "ofclient CLI now works out of the box with pip install onefinance.\nDrops the [cli] optional extra.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: promote typer+rich to core deps, bump to 0.1.1",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:37:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "da5af7adfe32f37806990e4b9d153e4b4fe27827",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: add PyPI metadata (author email, URL, classifiers)",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:16:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4af9f6841a450380900558a750675879959fc920",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: update author email to ysh@yishanhe.net",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:15:21Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f4ed6f290a57e99eb3e14a946677c9d2f3de056e",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add PyPI publish implementation plan",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:14:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d9e4c48826b8a94f80baa3f435cd376dc93c18e2",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add PyPI publish design spec",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:13:55Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "df31a26ec1a42bc87f30015999cc8fd40f8634e0",
          "body": "- Exclude .claude/, CLAUDE.md, TODO.md, scripts/, docs/ from sdist\n- Remove dev from project.optional-dependencies (kept in dependency-groups)\n- dist/ was already in .gitignore\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: clean sdist excludes and drop duplicate dev extra",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:03:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ebc2fc74191c10ea70eede297de4b2760a2f4b5d",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add github-installable implementation plan",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:02:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "99fd1051086f623c8b280753bede3c1dab23ecd4",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add github-installable packaging design spec",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T08:01:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e40aec98c6ed31dc636f588fafca661095e69fe4",
          "body": "…tion\n\nExtract shared _safe_float/_safe_int helpers into providers/_utils.py,\nreplacing three identical per-file copies. Fix a runtime bug in\nFinnhubProvider.get_forward_estimates where a frozen Pydantic model was\nmutated via attribute assignment; now collects raw data per period before\nconstructing\n[…]\n derived\nshares_outstanding (mktCap/price division, susceptible to TypeError/\nZeroDivisionError) with the direct sharesOutstanding API field.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: consolidate _safe_float/_safe_int and fix frozen model muta…",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T07:53:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7b264771bec97ddcc24e386bdf6543dff41943e1",
          "body": "- Add beta and shares_outstanding to CompanyInfo\n- Add nav to Quote (ETF support)\n- Implement ForwardEstimates model and get_forward_estimates endpoint\n- Update FMP, Finnhub, and YFinance providers to support new fields/endpoints\n- Add 'estimates' command to CLI\n- Update cache and routing configurations",
          "is_bot": false,
          "headline": "feat: complete finance-skills parity gaps",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T06:37:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "acb998cd1f40a9fe70c4295348dbc5d83218fb07",
          "body": null,
          "is_bot": false,
          "headline": "docs: add twelvedata sdk and api doc links to CLAUDE.md",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T06:21:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2b701705de79d356db6c5a85e7bce7485f607a14",
          "body": null,
          "is_bot": false,
          "headline": "docs: add fmp api doc link to CLAUDE.md",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T06:19:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ceb15ac4c035d8b8fed8110b8b7f1a72145ede1b",
          "body": null,
          "is_bot": false,
          "headline": "docs: add finnhub sdk and api doc links to CLAUDE.md",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T06:19:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "52c00fc76a8a40758011cdf35cf768c84819d15e",
          "body": "- Add intraday interval mapping for all providers\n- Implement get_news and get_analyst_data for Finnhub\n- Add OptionContract and OptionChain models\n- Add get_options_expirations and get_option_chain (yfinance)\n- Add ScreenerResult and SectorInfo models\n- Implement screen_stocks (FMP) and get_sector_overview (yfinance)\n- Add CLI commands for options, screen, and sector\n- Reorganize scratch files to scripts/\n- Update CLAUDE.md documentation",
          "is_bot": false,
          "headline": "feat: complete provider capability parity (M11)",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-15T05:49:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b78de3a8ad999017f9547a4416344fda1c73b177",
          "body": "… CLAUDE.md\n\n- Add live integration tests for FinnhubProvider and TwelveDataProvider\n- Write README with install instructions, Python/CLI usage, provider coverage table\n- Update CLAUDE.md milestone table (M4-M10 complete) and env vars table\n- Mark M6/M7/M9/M10 complete in TODO.md\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs+tests: integration tests for Finnhub/TwelveData, README, updated…",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-14T18:49:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9f16e8fe51e13eaf20d45aff2d1e6fcce4367efb",
          "body": "OneFinanceClient now builds provider instances from the config registry\ninstead of defaulting to YFinanceProvider only. Providers whose API key\nenv var is unset are silently skipped; YFinanceProvider is always\nincluded as a no-credential fallback.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: auto-instantiate providers from config when none passed explicitly",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-14T18:47:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "802432225b43a5e1e080fc45c4b471f6f4932b24",
          "body": "…it codes\n\nImplements M9 (price, quote, financials, info, insiders, ratios, earnings)\nand M10 (capabilities, version, config init/show, cache stats, providers\nstatus, --dry-run on all data commands). 266 unit tests, all passing.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(m9+m10): CLI — all 7 data commands, introspection, --dry-run, ex…",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-14T18:30:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "265a10136ffd7889b1f03577c0a1f3f013aabc85",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(m9): cli format.py — envelope helpers and output functions",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-14T18:26:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "19308e2ecd44ff698e667b328ffea9eb08f7d46e",
          "body": "…a API\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(m7): TwelveDataProvider — price history and quote via Twelve Dat…",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-14T18:24:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ac5da5ba88a55de2b263ec00cd70f62150cda47e",
          "body": "28 unit tests passing. Implements price_history, quote, info,\nfinancials (XBRL normalization), ratios, earnings, insider_trades.\nRate-limit detection uses Retry-After header; cooldown default 60s.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(m6): FinnhubProvider — all 7 endpoints complete",
          "author_name": "Shanhe Yi",
          "author_login": null,
          "committed_at": "2026-05-14T18:21:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 17,
      "commits_last_year": 101,
      "latest_release_at": "2026-07-24T08:45:22Z",
      "latest_release_tag": "v0.1.21",
      "releases_from_tags": true,
      "days_since_last_push": 3,
      "active_weeks_last_year": 11,
      "days_since_latest_release": 3,
      "mean_days_between_releases": 4.2
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "onefinance",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "Development Status :: 3 - Alpha",
            "Intended Audience :: Developers",
            "Intended Audience :: Financial and Insurance Industry",
            "License :: OSI Approved :: MIT License",
            "Programming Language :: Python :: 3",
            "Programming Language :: Python :: 3.11",
            "Programming Language :: Python :: 3.12",
            "Programming Language :: Python :: 3.13",
            "Topic :: Office/Business :: Financial",
            "Topic :: Software Development :: Libraries :: Python Modules"
          ],
          "ecosystem": "pypi",
          "matches_repo": true,
          "registry_url": "https://pypi.org/project/onefinance/",
          "is_deprecated": false,
          "latest_version": "0.1.21",
          "repository_url": "https://github.com/yishanhe/one-finance-data",
          "versions_count": 19,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2026-05-15T08:21:32.021369Z",
          "latest_published_at": "2026-07-24T08:52:37.637149Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 3
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 69667,
      "source_files_sampled": 98,
      "oversized_source_files": 1,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 24231
    },
    "dependencies": {
      "manifests": [
        "pyproject.toml"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [
          {
            "name": "diskcache",
            "direct": true,
            "version": "5.6.3",
            "severity": "moderate",
            "ecosystem": "pypi",
            "cvss_score": null,
            "advisory_ids": [
              "GHSA-w8v5-vhqr-4h9v",
              "PYSEC-2026-2447"
            ],
            "fixed_version": null,
            "advisory_count": 2,
            "oldest_advisory_days": 165
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "moderate": 1
        },
        "advisory_count": 2,
        "affected_count": 1,
        "assessed_count": 39,
        "malicious_count": 0,
        "assessed_package": "pypi:onefinance@0.1.21",
        "unassessed_count": 0,
        "direct_affected_count": 1
      },
      "ecosystems": [
        "pypi"
      ],
      "dependencies": [
        {
          "name": "diskcache",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=5.6"
        },
        {
          "name": "pydantic",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=2.0"
        },
        {
          "name": "pyyaml",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "httpx",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "yfinance",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        },
        {
          "name": "typer",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.26"
        },
        {
          "name": "rich",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": null
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 0,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "yishanhe",
          "commits": 69,
          "avatar_url": "https://avatars.githubusercontent.com/u/838961?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "publish.yml",
        "python-package.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": true
    },
    "security_signals": {
      "lockfiles": [
        "uv.lock"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 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": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 8,
            "reason": "dependency not pinned by hash detected -- score normalized to 8",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "51ee22afa2d52fd88dff94f350e14749c56ae2f6",
        "ran_at": "2026-07-27T16:49:03Z",
        "aggregate_score": 3.3,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-24T08:52:41Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": null,
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/yishanhe/one-finance-data",
    "host": "github.com",
    "name": "one-finance-data",
    "owner": "yishanhe"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 53,
      "inputs": {
        "security": 44,
        "vitality": 72,
        "community": 24,
        "governance": 38,
        "engineering": 85
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 72,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 62,
            "inputs": {
              "commits_last_year": 101,
              "human_commit_share": 1,
              "days_since_last_push": 3,
              "active_weeks_last_year": 11
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 3 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "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": "101 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 101
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 88,
            "inputs": {
              "releases_count": 17,
              "latest_release_tag": "v0.1.21",
              "releases_from_tags": true,
              "days_since_latest_release": 3,
              "mean_days_between_releases": 4.2
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "17 version tags (no GitHub releases)",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "version_tags_no_releases",
                    "params": {
                      "count": 17
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 3 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~4.2 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 4.2
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 24,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "at_risk",
        "name": "Sustainability & Governance",
        "value": 38,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 13,
            "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 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution",
                    "pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "merged_prs": 0,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "no decided pull requests or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_decided_prs_or_data",
                    "params": {}
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 57,
            "inputs": {
              "followers": 60,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "yishanhe",
              "public_repos": 27,
              "account_age_days": 5527
            },
            "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": "60 followers of yishanhe",
                "points": 12.8,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 60,
                      "login": "yishanhe"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "27 public repos, account ~15 yr old",
                "points": 22.5,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 27
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 15
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "onefinance"
              ],
              "ecosystems": "pypi",
              "any_deprecated": false,
              "min_days_since_publish": 3
            },
            "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 3 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "19 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 19
                    }
                  }
                ],
                "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": 85,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "excellent",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 92,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": true
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 16,
                "status": "met",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 9.6,
                "status": "met",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 44,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 33,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 15,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 3,
              "scorecard_aggregate": 3.3
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "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 not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 8",
                "points": 4,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "3 existing vulnerabilities detected",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Matched the pypi:onefinance@0.1.21 runtime dependency closure — what installing the published package pulls in — 39 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "pypi:onefinance@0.1.21",
                  "assessed": 39
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 89,
            "inputs": {
              "source": "osv",
              "advisories": 2,
              "affected_packages": 1,
              "assessed_packages": 39,
              "unassessed_packages": 0,
              "affected_by_severity": "moderate 1",
              "direct_affected_packages": 1
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "1 affected: diskcache 5.6.3 (moderate)",
                "points": 26.6,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "diskcache 5.6.3 (moderate)"
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "no indirect dependency carries a known advisory",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "no_indirect_advisories",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "1 advisory-carrying package(s) unaddressed past 90 days; oldest published 165 days ago",
                "points": 37.2,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_stale",
                    "params": {
                      "days": 90,
                      "count": 1,
                      "oldest": 165
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 39,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 68,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.98,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 24231
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "98 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 98,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 61,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "uv.lock"
              ],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0.7,
              "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": null,
                "points": 11,
                "status": "met",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "70 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 70,
                      "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 8",
                "points": 8,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "moderate",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 54,
            "inputs": {
              "primary_language": "Python",
              "largest_source_bytes": 69667,
              "source_files_sampled": 98,
              "oversized_source_files": 1
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Python without a type-check config",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_typecheck_config_language",
                    "params": {
                      "language": "Python"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "1/98 source files over 60KB",
                "points": 54.4,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 98,
                      "oversized": 1
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-27T16:49:07.916189Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/y/yishanhe/one-finance-data.svg",
  "full_name": "yishanhe/one-finance-data",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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