公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-27 16:49 UTC

yishanhe / one-finance-data

one finance data client to rule them all

PythonMIT★ 0 星标⑂ 0 复刻始于 2026年5月在 GitHub 上查看 ↗

yishanhe/one-finance-data 的健康指数为 100 分中的 53 分,处于「中等」区间。 其得分最高的类别是Engineering Quality(85/100),最低的是Community & Adoption(24/100)。 最近一次更新在 3 天前。 近期的大部分工作由 1 位贡献者完成。

53
总分 / 100
中等

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。

53
优秀85-100堪称典范;基本满足所有检验标准
良好70-84健康;仅有轻微不足
中等50-69可接受,但存在明显不足;建议进行审查
存在风险30-49存在重大薄弱环节;采用时应保持审慎
危急1-29问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。

所有权

Syi个人账户
60 关注者27 个公开仓库始于 2011年6月@facebook

该仓库由个人账户拥有。相较于组织支持的项目,单一所有者项目的延续性风险更高。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
PyPIonefinance0.1.21-193 天前

按类别列示的指标

活力

项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?

72良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 3 天前
7.6/36提交节奏 — 52 周中有 11 周有提交
18/18提交量 — 最近一年 101 次提交
0/10OpenSSF Scorecard:Maintained — project was created within the last 90 days. Please review its contents carefully
所用输入
commits_last_year101
human_commit_share1
days_since_last_push3
active_weeks_last_year11

发布纪律

88优秀
评分方式
16.2/27有发布版本 — 17 个版本标签(无 GitHub 发布版本)
36/36发布时效 — 最近一次发布版本于 3 天前
27/27发布节奏 — 约每 4.2 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count17
latest_release_tagv0.1.21
releases_from_tags
days_since_latest_release3
mean_days_between_releases4.2
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?

24危急 · 占总体的 18%
评分方式
0/60星标 — 0 个星标
0/25复刻 — 0 个复刻
0/15关注者 — 0 位关注者
所用输入
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

50中等
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(MIT)
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template

可持续性与治理

项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?

38存在风险 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
3/10OpenSSF Scorecard:Contributors — project has 1 contributing companies or organizations -- score normalized to 3
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
0/46.8议题解决 — 没有议题或无数据
0/38.3PR 接受 — 没有已裁定的拉取请求或无数据
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
已排除计分(无数据或不适用):议题解决, PR 接受。 其余权重已重新归一化。
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
12.8/25所有者影响力 — yishanhe 有 60 位关注者
22.5/25既往记录 — 27 个公开仓库,账户约 15 年
所用输入
followers60
owner_typeUser
is_verified
owner_loginyishanhe
public_repos27
account_age_days5,527
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — pypi 上有 1 个软件包
35/35发布时效 — 最近一次发布于 3 天前
20/20版本历史 — 19 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesonefinance
ecosystemspypi
any_deprecated
min_days_since_publish3

工程质量

基础的工程与文档实践是否到位?

85优秀 · 占总体的 20%

工程实践

92优秀
评分方式
24/24CI 工作流 — 2 个工作流
24/24存在测试
16/16Linter 配置
9.6/9.6Pre-commit 钩子
0/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 无数据
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config
已排除计分(无数据或不适用):OpenSSF Scorecard:CI-Tests。 其余权重已重新归一化。

文档

75良好
评分方式
30/30README
25/25文档目录
0/15文档 / 主页站点
10/10仓库描述
0/10主题标签
10/10Wiki
所用输入
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?

44存在风险 · 占总体的 16%

安全态势

33存在风险
评分方式
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 — 无数据
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.5许可证 — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — 无数据
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 — 无数据
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated15
scorecard_versionv5.5.0
checks_inconclusive3
scorecard_aggregate3.3
已排除计分(无数据或不适用):ci_tests, packaging, signed_releases。 其余权重已重新归一化。
评分方式
26.6/35直接依赖不含已知公告 — 1 个受影响:diskcache 5.6.3 (moderate)
25/25间接依赖不含已知公告 — 没有间接依赖携带已知公告
37.2/40没有长期未处理的公告 — 1 个携带公告的软件包超过 90 天未处理;最早一条发布于 165 天前
所用输入
sourceosv
advisories2
affected_packages1
assessed_packages39
unassessed_packages0
affected_by_severitymoderate 1
direct_affected_packages1
比对的是 pypi:onefinance@0.1.21 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 39 个软件包。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。

68中等 · 占总体的 0%
评分方式
45/45代理指令 — AGENTS.md, CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 98 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.98
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes24,231
评分方式
0/18一条命令的引导启动
22/22自动化测试
11/11Lint / 格式化配置
0/11静态类型检查
10/10可复现环境 — lockfile
10/10已体现的代理实践 — 最近 100 次提交中有 70 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
8/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 8
所用输入
has_nix
has_tests
lockfilesuv.lock
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0.7
toolchain_manifests
dependency_bot_commit_share0
评分方式
0/45可类型检查的代码 — Python,未配置类型检查
54.4/55可控的文件大小 — 采样的 98 个源文件中有 1 个超过 60KB
所用输入
primary_languagePython
largest_source_bytes69,667
source_files_sampled98
oversized_source_files1

关键数据

0GitHub 星标
1贡献者
101最近 12 个月提交数
3距最近推送天数
17发布版本数
1巴士系数(bus factor)
0开放议题
PyPI软件包生态系统数

数据采集警告

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

更多细节

OpenSSF Scorecard 3.3 / 10
3.3综合

来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。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
不适用CI-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
不适用Packagingpackaging workflow not detected
8Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 8
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
7Vulnerabilities3 existing vulnerabilities detected
直接依赖 7
注册表软件包版本约束清单文件
PyPIdiskcache>=5.6pyproject.toml
PyPIpydantic>=2.0pyproject.toml
PyPIpyyamlpyproject.toml
PyPIhttpxpyproject.toml
PyPIyfinancepyproject.toml
PyPItyper>=0.26pyproject.toml
PyPIrichpyproject.toml
全部依赖 未采集

本报告未能采集到解析后的依赖集合:GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

依赖安全公告 1

安装 pypi:onefinance@0.1.21 会引入 39 个包(直接与传递):其中 1 个存在已知公告,1 个为直接依赖。

软件包版本关系严重程度公告数修复版本
diskcache5.6.3直接2

公告表示依赖图中记录的版本落入某条公告的受影响范围。可达性未经分析,且依赖图包含开发与测试的版本固定——某项发现可能只涉及工具链而非交付的软件。

原始 JSON 报告 机器可读
{
  "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"
}

评分是信号,而非担保。 评分反映的是 GitHub 上公开可见的实践——不是代码审计,也不是安全保证。

缺失数据将被剔除并重新归一化权重,绝不按零分计。方法论已版本化并公开:指标 v1.13.0、模式 v0.27.0—— 完整方法论 · 指标知识库.

单项结果在整体记录中的位置: 汇总统计PyPI.