公开记录
软件健康报告模式 0.27.0 · 指标 2.3.2 · 2026-07-31 03:10 UTC

amun-ai / hypha

A distributed application framework for large-scale data management and AI model serving

Python · JavaScript · HTMLMIT★ 24 星标⑂ 14 复刻始于 2021年10月在 GitHub 上查看 ↗
类型如何判定

amun-ai/hypha 的健康指数为 100 分中的 80 分,处于「优秀」区间。 其得分最高的类别是Engineering Quality(91/100),最低的是Community & Adoption(45/100)。 最近一次更新在今天。 近期的大部分工作由 1 位贡献者完成。

80
总分 / 100
优秀

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均,再依据公开记录的分布进行校准,使各等级具有百分位含义;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 34(存在风险)的上限。

80
卓越93-100公开记录中的最高层级(约前 5%);基本满足所有检验标准
优秀80-92各方面均表现强劲;仅有少量不足
良好65-79健康;不足之处有限且可控
中等50-64可接受,但存在明显不足;建议进行审查
薄弱35-49多个领域存在实质性薄弱环节
存在风险20-34存在重大薄弱环节;采用时应保持审慎
危急1-19问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

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

加权总体分 68 经校准后在公布的指数量表上为 80(记录校准 2026-08-02)。

所有权

Amun AI组织
4 关注者8 个公开仓库始于 2020年12月

该仓库由组织支持——共同承担、可问责的托管责任,可延续于任何单一维护者之后。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
PyPIhypha0.21.1275,4424010 天前

按类别列示的指标

活力

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

90优秀 · 占总体的 21%
评分方式
36/36推送新近度 — 最近一次推送于 0 天前
20.8/36提交节奏 — 52 周中有 30 周有提交
18/18提交量 — 最近一年 284 次提交
0/10OpenSSF Scorecard:Maintained — 无数据
所用输入
commits_last_year284
human_commit_share1
days_since_last_push0
active_weeks_last_year30

发布纪律

100卓越
评分方式
27/27有发布版本 — 已发布 100 个发布版本
36/36发布时效 — 最近一次发布版本于 0 天前
27/27发布节奏 — 约每 0.8 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count100
latest_release_tagv0.21.127
releases_from_tags
days_since_latest_release0
mean_days_between_releases0.8

社区与采用

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

45薄弱 · 占总体的 17%

流行度与采用

31存在风险
评分方式
22.1/60星标 — 24 个星标
9.3/25复刻 — 14 个复刻
0/15关注者 — 2 位关注者
所用输入
forks14
stars24
watchers2
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
readme_badges
has_contributing
has_issue_template
has_code_of_conduct
readme_badge_services
has_pull_request_template
评分方式
49.8/80月度下载量 — pypi 合计每月 5,442 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packageshypha
dependents
ecosystemspypi
total_downloads
monthly_downloads5,442
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

62中等 · 占总体的 23%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
1/22.5提交分布 — 头号贡献者编写了 96% 的提交
13.5/13.5贡献者广度 — 12 位贡献者
0/10OpenSSF Scorecard:Contributors — 无数据
所用输入
bus_factor1
contributors_sampled12
top_contributor_share0.957
评分方式
42/42议题解决 — 100% 的议题已关闭
19.3/30PR 接受 — 已裁定的 PR 中 637/988 已合并
0/13Newcomer PR acceptance — 30 天内没有首次贡献者的 PR 得到裁决
0/15OpenSSF Scorecard:Code-Review — 无数据
所用输入
merged_prs637
open_issues0
closed_issues30
prs_merged_7d
prs_decided_7d
prs_merged_30d
prs_decided_30d
issue_closed_ratio1
closed_unmerged_prs351
first_time_authors_30d
first_time_prs_merged_30d
first_time_prs_decided_30d
已排除计分(无数据或不适用):newcomer_pr_acceptance。 其余权重已重新归一化。
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
5/25所有者影响力 — amun-ai 有 4 位关注者
18.2/25既往记录 — 8 个公开仓库,账户约 5 年
所用输入
followers4
owner_typeOrganization
is_verified
owner_loginamun-ai
public_repos8
account_age_days2,047
评分方式
25/25已发布且可解析 — pypi 上有 1 个软件包
35/35发布时效 — 最近一次发布于 0 天前
20/20版本历史 — 401 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packageshypha
ecosystemspypi
any_deprecated
min_days_since_publish0

工程质量

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

91优秀 · 占总体的 19%

工程实践

92优秀
评分方式
24/24CI 工作流 — 7 个工作流
24/24存在测试
16/16Linter 配置 — tox.ini
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

文档

90优秀
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://docs.amun.ai
10/10仓库描述
0/10主题标签
10/10Wiki
所用输入
topics
has_wiki
homepagehttps://docs.amun.ai
has_readme
has_docs_dir
has_description

安全

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

46薄弱 · 占总体的 16%

安全态势

33存在风险
评分方式
0/30安全策略(SECURITY.md)
25/25Dependabot 配置
0/25依赖锁定文件 — 已发布的类库——锁定文件属于应用层关注点,不作要求
0/20CodeQL 工作流
所用输入
sourcefile_signals
lockfiles
manifestsrequirements.txt, requirements_dev.txt, requirements_lint.txt, requirements_pypi.txt, requirements_test.txt, setup.cfg, setup.py
has_codeql_workflow
has_security_policy
has_dependabot_config
已排除计分(无数据或不适用):依赖锁定文件。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
0/25间接依赖不含已知公告 — 在此范围内,传递依赖集合无法与开发和测试依赖区分
0/40没有长期未处理的公告 — 没有公告带有发布日期
所用输入
sourceosv
advisories39
affected_packages10
assessed_packages63
unassessed_packages54
affected_by_severitycritical 2, high 6, moderate 2
direct_affected_packages0
已排除计分(无数据或不适用):间接依赖不含已知公告, 没有长期未处理的公告。 其余权重已重新归一化。 已将 63 个已解析依赖与 OSV 比对。 有 54 项无法评估——没有已解析的版本、生态系统不受支持,或超出所报告的软件包清单。 该仓库未发布任何索引可解析的软件包,因此改为评估仓库依赖图。该图将开发与测试版本固定同交付的依赖混在一起,因此仅对声明的运行时依赖计分;传递性发现仅作为背景信息列出,不计入评分。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?权重刻意设小(4%):代理工具链是一项真实的维护信号,但完全不具备的仓库仍可达到 100/100。

72良好 · 占总体的 4%
评分方式
45/45代理指令 — CLAUDE.md
15/15机器可读文档(llms.txt) — 存在 llms.txt
40/40可读的提交历史 — 100 次人类提交中有 100 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share1
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes55,402
评分方式
0/18一条命令的引导启动
22/22自动化测试
11/11Lint / 格式化配置 — tox.ini
0/11静态类型检查
10/10可复现环境 — Dockerfile
10/10已体现的代理实践 — 最近 100 次提交中有 96 次由代理编写或署名代理
5/8自动化维护 — 已配置依赖自动化,但在抽样提交中未观察到
0/10OpenSSF Scorecard:Pinned-Dependencies — 无数据
所用输入
has_nix
has_tests
lockfiles
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0.96
toolchain_manifests
dependency_bot_commit_share0
评分方式
0/45可类型检查的代码 — Python,未配置类型检查
48.2/55可控的文件大小 — 采样的 201 个源文件中有 25 个超过 60KB
所用输入
primary_languagePython
largest_source_bytes512,705
source_files_sampled201
oversized_source_files25
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
20/20MCP 服务器
40/40可运行示例 — notebooks
所用输入
example_dirsnotebooks
has_mcp_signal
api_schema_files

关键数据

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

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • deps.dev does not index pypi:hypha@0.21.127; advisories assessed against the repository dependency graph instead
  • OpenSSF Scorecard did not return a usable result (exit code -9); skipping Scorecard checks

更多细节

Star 与 Fork 历史 0 ★ / 14 ⇿
0Star
14Fork
61发布

每颗 star 和每个 fork 的添加时间,来自 GitHub 并按天汇总。累计增长位于其构成来源——每日新增——的正上方,二者可相互对照:稳定的自然增长与短暂的突增形态截然不同。当这一差别可被衡量时,它会作为增长真实性予以报告。

0246810121212022-072024-052026-03
主版本 0次版本 0修订 61

每个点涵盖 4 天。

全部依赖 117

来自 GitHub 依赖图的完整解析依赖集合:0 个直接依赖与 117 个间接(传递)软件包。仓库提交锁文件时,传递闭包才是完整的。

注册表软件包版本关系
PyPIa2a-sdk间接
PyPIa2a-sdk0.3.0间接
PyPIaioboto313.2.0间接
PyPIaiobotocore间接
PyPIaiocache0.12.2间接
PyPIaiofiles23.2.1间接
PyPIaiortc间接
PyPIaiosqlite0.20.0间接
PyPIalembic1.14.0间接
PyPIapscheduler间接
PyPIasyncpg间接
PyPIazure-identity间接
PyPIazure-keyvault-secrets间接
PyPIazure-storage-blob间接
PyPIbackoff间接
PyPIbase58间接
PyPIbase582.1.1间接
PyPIblack24.10.0间接
PyPIboto31.36.0间接
PyPIclick间接
PyPIconda-pack间接
PyPIcryptography间接
PyPIdiskcache间接
PyPIdulwich间接
PyPIfakeredis2.24.1间接
PyPIfastapi间接
PyPIfastapi0.115.2间接
PyPIfastapi-sso间接
PyPIfastembed间接
PyPIfastembed0.4.2间接
PyPIfastuuid间接
PyPIfastuuid0.14.0间接
PyPIflake87.1.1间接
PyPIflake8-docstrings1.7.0间接
PyPIfriendlywords1.1.3间接
PyPIgoogle-cloud-iam间接
PyPIgoogle-cloud-kms间接
PyPIgoogle-genai间接
PyPIgreenlet3.1.1间接
PyPIgunicorn间接
PyPIhrid0.3.0间接
PyPIhttpx0.28.1间接
PyPIhypha-rpc0.21.46间接
PyPIipykernel间接
PyPIjinja23.1.4间接
PyPIjsonschema4.24.0间接
PyPIjupyter-client间接
PyPIkubernetes间接
PyPIlitellm-enterprise0.1.20间接
PyPIlitellm-proxy-extras0.2.19间接
PyPIlxml4.9.3间接
PyPImcp间接
PyPImcp1.11.0间接
PyPImlflow间接
PyPImsgpack1.0.8间接
PyPInumcodecs间接
PyPInumcodecs0.16.2间接
PyPInumpy间接
PyPIollama0.5.1间接
PyPIopenai间接
PyPIorjson间接
PyPIplaywright间接
PyPIplaywright1.51.0间接
PyPIpolars间接
PyPIprisma0.11.0间接
PyPIprometheus-client0.21.1间接
PyPIprompt-toolkit3.0.50间接
PyPIpsutil间接
PyPIpsycopg2-binary间接
PyPIpsycopg2-binary2.9.10间接
PyPIptpython3.0.29间接
PyPIptyprocess0.7.0间接
PyPIpydantic2.11.3间接
PyPIpyjwt间接
PyPIpylint3.2.6间接
PyPIpymultihash间接
PyPIpymultihash0.8.2间接
PyPIpynacl间接
PyPIpyotritonclient0.2.6间接
PyPIpytest7.4.0间接
PyPIpytest-asyncio0.21.1间接
PyPIpytest-cov4.1.0间接
PyPIpytest-timeout2.3.1间接
PyPIpython-dotenv间接
PyPIpython-jose3.3.0间接
PyPIpython-multipart间接
PyPIpyyaml间接
PyPIredis5.2.0间接
PyPIredis6.2.0间接
PyPIrequests间接
PyPIrequests2.31.0间接
PyPIresend间接
PyPIrich13.7.1间接
PyPIrq间接
PyPIscikit-learn1.7.1间接
PyPIsemantic-router间接
PyPIsetuptools69.0.3间接
PyPIshortuuid1.0.13间接
PyPIsimpervisor1.0.0间接
PyPIsqlalchemy2.0.35间接
PyPIsqlmodel0.0.34间接
PyPIstarlette-compress间接
PyPIstream-zip0.0.83间接
PyPItiktoken间接
PyPItokenizers间接
PyPItox间接
PyPItwine4.0.2间接
PyPIuuid-utils0.9.0间接
PyPIuvicorn间接
PyPIuvicorn0.23.2间接
PyPIuvloop间接
PyPIwebsocket-client1.6.1间接
PyPIwebsockets间接
PyPIwebsockets15.0.1间接
PyPIwheel0.41.1间接
PyPIzarr间接
PyPIzarr3.1.2间接
依赖安全公告 10

该仓库未发布可被索引解析的包,因此评估的是其自身的依赖图——共 63 个包,其中也包含从不交付的开发与测试版本固定:10 个存在已知公告,0 个为直接依赖。 有 54 个无法评估——没有已解析的版本、生态系统不受支持,或不在所列包清单之内。

软件包版本关系严重程度公告数修复版本
black24.10.0间接严重326.3.1
python-jose3.3.0间接严重53.4.0
jinja23.1.4间接63.1.6
lxml4.9.3间接26.1.0
mcp1.11.0间接61.28.1
msgpack1.0.8间接11.2.1
setuptools69.0.3间接683.0.0
wheel0.41.1间接20.46.2
pytest7.4.0间接29.0.3
requests2.31.0间接62.33.0

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 57054,
      "has_wiki": true,
      "homepage": "https://docs.amun.ai",
      "languages": {
        "HTML": 770154,
        "Mako": 651,
        "Shell": 8473,
        "Python": 5363763,
        "Dockerfile": 2868,
        "JavaScript": 985523,
        "Go Template": 3529
      },
      "pushed_at": "2026-07-31T03:07:24Z",
      "created_at": "2021-10-16T18:36:37Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-31T02:24:04Z",
      "description": "A distributed application framework for large-scale data management and AI model serving",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "Python",
      "significant_languages": [
        "Python",
        "JavaScript",
        "HTML"
      ]
    },
    "owner": {
      "blog": "https://amun.ai",
      "name": "Amun AI",
      "type": "Organization",
      "login": "amun-ai",
      "company": null,
      "location": null,
      "followers": 4,
      "avatar_url": "https://avatars.githubusercontent.com/u/76439739?v=4",
      "created_at": "2020-12-21T14:21:15Z",
      "is_verified": null,
      "public_repos": 8,
      "account_age_days": 2047
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": null,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.21.127",
          "kind": "patch",
          "published_at": "2026-07-31T03:07:38Z"
        },
        {
          "tag": "v0.21.126",
          "kind": "patch",
          "published_at": "2026-07-29T19:09:51Z"
        },
        {
          "tag": "v0.21.124",
          "kind": "patch",
          "published_at": "2026-07-25T21:58:36Z"
        },
        {
          "tag": "v0.21.123",
          "kind": "patch",
          "published_at": "2026-07-25T21:04:12Z"
        },
        {
          "tag": "v0.21.122",
          "kind": "patch",
          "published_at": "2026-07-25T19:59:33Z"
        },
        {
          "tag": "v0.21.121",
          "kind": "patch",
          "published_at": "2026-07-25T17:59:27Z"
        },
        {
          "tag": "v0.21.120",
          "kind": "patch",
          "published_at": "2026-07-25T17:07:11Z"
        },
        {
          "tag": "v0.21.119",
          "kind": "patch",
          "published_at": "2026-07-25T02:54:25Z"
        },
        {
          "tag": "v0.21.118",
          "kind": "patch",
          "published_at": "2026-07-23T17:58:56Z"
        },
        {
          "tag": "v0.21.117",
          "kind": "patch",
          "published_at": "2026-07-23T13:27:07Z"
        },
        {
          "tag": "v0.21.116",
          "kind": "patch",
          "published_at": "2026-07-22T19:00:53Z"
        },
        {
          "tag": "v0.21.115",
          "kind": "patch",
          "published_at": "2026-07-22T18:17:34Z"
        },
        {
          "tag": "v0.21.113",
          "kind": "patch",
          "published_at": "2026-07-22T15:46:08Z"
        },
        {
          "tag": "v0.21.112",
          "kind": "patch",
          "published_at": "2026-07-22T14:17:49Z"
        },
        {
          "tag": "v0.21.111",
          "kind": "patch",
          "published_at": "2026-07-14T02:52:24Z"
        },
        {
          "tag": "v0.21.110",
          "kind": "patch",
          "published_at": "2026-07-11T00:26:27Z"
        },
        {
          "tag": "v0.21.109",
          "kind": "patch",
          "published_at": "2026-07-10T11:59:48Z"
        },
        {
          "tag": "v0.21.108",
          "kind": "patch",
          "published_at": "2026-07-08T06:40:37Z"
        },
        {
          "tag": "v0.21.107",
          "kind": "patch",
          "published_at": "2026-07-08T05:04:23Z"
        },
        {
          "tag": "v0.21.106",
          "kind": "patch",
          "published_at": "2026-07-07T02:52:08Z"
        },
        {
          "tag": "v0.21.105",
          "kind": "patch",
          "published_at": "2026-07-02T17:55:58Z"
        },
        {
          "tag": "v0.21.104",
          "kind": "patch",
          "published_at": "2026-06-26T01:29:01Z"
        },
        {
          "tag": "v0.21.103",
          "kind": "patch",
          "published_at": "2026-06-25T09:23:01Z"
        },
        {
          "tag": "v0.21.102",
          "kind": "patch",
          "published_at": "2026-06-23T14:44:28Z"
        },
        {
          "tag": "v0.21.101",
          "kind": "patch",
          "published_at": "2026-06-23T07:31:46Z"
        },
        {
          "tag": "v0.21.100",
          "kind": "patch",
          "published_at": "2026-06-22T22:54:09Z"
        },
        {
          "tag": "v0.21.99",
          "kind": "patch",
          "published_at": "2026-06-22T18:28:54Z"
        },
        {
          "tag": "v0.21.98",
          "kind": "patch",
          "published_at": "2026-06-22T16:24:00Z"
        },
        {
          "tag": "v0.21.97",
          "kind": "patch",
          "published_at": "2026-06-22T12:04:00Z"
        },
        {
          "tag": "v0.21.90",
          "kind": "patch",
          "published_at": "2026-06-17T11:10:19Z"
        },
        {
          "tag": "v0.21.89",
          "kind": "patch",
          "published_at": "2026-06-17T07:31:48Z"
        },
        {
          "tag": "v0.21.88",
          "kind": "patch",
          "published_at": "2026-06-17T03:41:21Z"
        },
        {
          "tag": "v0.21.87",
          "kind": "patch",
          "published_at": "2026-06-16T19:58:09Z"
        },
        {
          "tag": "v0.21.86",
          "kind": "patch",
          "published_at": "2026-06-13T19:36:19Z"
        },
        {
          "tag": "v0.21.85",
          "kind": "patch",
          "published_at": "2026-05-02T13:05:30Z"
        },
        {
          "tag": "v0.21.84",
          "kind": "patch",
          "published_at": "2026-05-02T09:04:27Z"
        },
        {
          "tag": "v0.21.83",
          "kind": "patch",
          "published_at": "2026-04-26T22:37:10Z"
        },
        {
          "tag": "v0.21.82",
          "kind": "patch",
          "published_at": "2026-03-19T07:31:47Z"
        },
        {
          "tag": "v0.21.81",
          "kind": "patch",
          "published_at": "2026-03-19T06:36:59Z"
        },
        {
          "tag": "v0.21.80",
          "kind": "patch",
          "published_at": "2026-03-11T07:26:53Z"
        },
        {
          "tag": "v0.21.79",
          "kind": "patch",
          "published_at": "2026-03-08T10:49:21Z"
        },
        {
          "tag": "v0.21.78",
          "kind": "patch",
          "published_at": "2026-03-07T12:08:06Z"
        },
        {
          "tag": "v0.21.77",
          "kind": "patch",
          "published_at": "2026-03-07T07:43:13Z"
        },
        {
          "tag": "v0.21.76",
          "kind": "patch",
          "published_at": "2026-03-07T07:31:44Z"
        },
        {
          "tag": "v0.21.75",
          "kind": "patch",
          "published_at": "2026-03-07T04:42:59Z"
        },
        {
          "tag": "v0.21.74",
          "kind": "patch",
          "published_at": "2026-03-07T02:54:14Z"
        },
        {
          "tag": "v0.21.73",
          "kind": "patch",
          "published_at": "2026-03-06T18:51:28Z"
        },
        {
          "tag": "v0.21.72",
          "kind": "patch",
          "published_at": "2026-03-06T05:31:42Z"
        },
        {
          "tag": "v0.21.70",
          "kind": "patch",
          "published_at": "2026-03-01T20:25:49Z"
        },
        {
          "tag": "v0.21.69",
          "kind": "patch",
          "published_at": "2026-03-01T16:47:03Z"
        },
        {
          "tag": "v0.21.67",
          "kind": "patch",
          "published_at": "2026-03-01T07:57:25Z"
        },
        {
          "tag": "v0.21.64",
          "kind": "patch",
          "published_at": "2026-02-27T22:47:00Z"
        },
        {
          "tag": "v0.21.63",
          "kind": "patch",
          "published_at": "2026-02-27T08:09:04Z"
        },
        {
          "tag": "v0.21.61",
          "kind": "patch",
          "published_at": "2026-02-27T02:04:15Z"
        },
        {
          "tag": "v0.21.59",
          "kind": "patch",
          "published_at": "2026-02-26T18:59:33Z"
        },
        {
          "tag": "v0.21.58",
          "kind": "patch",
          "published_at": "2026-02-26T14:36:49Z"
        },
        {
          "tag": "v0.21.57",
          "kind": "patch",
          "published_at": "2026-02-26T13:51:46Z"
        },
        {
          "tag": "v0.21.56",
          "kind": "patch",
          "published_at": "2026-02-26T13:29:14Z"
        },
        {
          "tag": "v0.21.55",
          "kind": "patch",
          "published_at": "2026-02-25T23:21:46Z"
        },
        {
          "tag": "v0.21.54",
          "kind": "patch",
          "published_at": "2026-02-25T17:19:57Z"
        },
        {
          "tag": "v0.21.53",
          "kind": "patch",
          "published_at": "2026-02-24T22:36:10Z"
        },
        {
          "tag": "v0.21.52",
          "kind": "patch",
          "published_at": "2026-02-24T20:50:48Z"
        },
        {
          "tag": "v0.21.51",
          "kind": "patch",
          "published_at": "2026-02-24T15:38:19Z"
        },
        {
          "tag": "v0.21.50",
          "kind": "patch",
          "published_at": "2026-02-23T08:36:57Z"
        },
        {
          "tag": "v0.21.49",
          "kind": "patch",
          "published_at": "2026-02-23T07:12:34Z"
        },
        {
          "tag": "v0.21.48",
          "kind": "patch",
          "published_at": "2026-02-23T06:29:40Z"
        },
        {
          "tag": "v0.21.47",
          "kind": "patch",
          "published_at": "2026-02-13T13:30:46Z"
        },
        {
          "tag": "v0.21.44",
          "kind": "patch",
          "published_at": "2026-02-11T14:57:18Z"
        },
        {
          "tag": "v0.21.43",
          "kind": "patch",
          "published_at": "2026-02-11T14:28:59Z"
        },
        {
          "tag": "v0.21.42",
          "kind": "patch",
          "published_at": "2026-02-10T19:05:27Z"
        },
        {
          "tag": "v0.21.40",
          "kind": "patch",
          "published_at": "2026-02-07T15:42:30Z"
        },
        {
          "tag": "v0.21.39",
          "kind": "patch",
          "published_at": "2026-01-30T05:47:12Z"
        },
        {
          "tag": "v0.21.37",
          "kind": "patch",
          "published_at": "2026-01-24T07:14:50Z"
        },
        {
          "tag": "v0.21.35",
          "kind": "patch",
          "published_at": "2026-01-22T15:24:53Z"
        },
        {
          "tag": "v0.21.34",
          "kind": "patch",
          "published_at": "2026-01-17T01:29:14Z"
        },
        {
          "tag": "v0.21.33",
          "kind": "patch",
          "published_at": "2026-01-17T01:09:51Z"
        },
        {
          "tag": "v0.21.32",
          "kind": "patch",
          "published_at": "2026-01-16T10:02:20Z"
        },
        {
          "tag": "v0.21.31",
          "kind": "patch",
          "published_at": "2026-01-15T23:49:58Z"
        },
        {
          "tag": "v0.21.30",
          "kind": "patch",
          "published_at": "2026-01-14T17:35:47Z"
        },
        {
          "tag": "v0.21.29",
          "kind": "patch",
          "published_at": "2025-12-23T17:19:31Z"
        },
        {
          "tag": "v0.21.28",
          "kind": "patch",
          "published_at": "2025-12-15T22:43:37Z"
        },
        {
          "tag": "v0.21.27",
          "kind": "patch",
          "published_at": "2025-12-04T07:22:59Z"
        },
        {
          "tag": "v0.21.26",
          "kind": "patch",
          "published_at": "2025-10-28T12:34:20Z"
        },
        {
          "tag": "v0.21.25",
          "kind": "patch",
          "published_at": "2025-10-07T14:57:42Z"
        },
        {
          "tag": "v0.21.24",
          "kind": "patch",
          "published_at": "2025-10-07T12:39:29Z"
        },
        {
          "tag": "v0.21.23",
          "kind": "patch",
          "published_at": "2025-09-16T12:19:07Z"
        },
        {
          "tag": "v0.21.22",
          "kind": "patch",
          "published_at": "2025-09-10T00:20:21Z"
        },
        {
          "tag": "v0.21.21",
          "kind": "patch",
          "published_at": "2025-09-08T23:26:29Z"
        },
        {
          "tag": "v0.21.20",
          "kind": "patch",
          "published_at": "2025-09-08T20:54:23Z"
        },
        {
          "tag": "v0.21.19",
          "kind": "patch",
          "published_at": "2025-09-07T18:00:31Z"
        },
        {
          "tag": "v0.21.18",
          "kind": "patch",
          "published_at": "2025-09-06T15:50:39Z"
        },
        {
          "tag": "v0.21.17",
          "kind": "patch",
          "published_at": "2025-09-06T14:29:37Z"
        },
        {
          "tag": "v0.21.16",
          "kind": "patch",
          "published_at": "2025-09-06T00:35:03Z"
        },
        {
          "tag": "v0.21.15",
          "kind": "patch",
          "published_at": "2025-08-22T05:04:06Z"
        },
        {
          "tag": "v0.21.14",
          "kind": "patch",
          "published_at": "2025-08-22T03:19:57Z"
        },
        {
          "tag": "v0.21.13",
          "kind": "patch",
          "published_at": "2025-08-21T19:11:17Z"
        },
        {
          "tag": "v0.21.12",
          "kind": "patch",
          "published_at": "2025-08-20T22:01:58Z"
        },
        {
          "tag": "v0.21.11",
          "kind": "patch",
          "published_at": "2025-08-20T03:35:10Z"
        },
        {
          "tag": "v0.21.10",
          "kind": "patch",
          "published_at": "2025-08-20T02:08:51Z"
        },
        {
          "tag": "v0.21.8",
          "kind": "patch",
          "published_at": "2025-08-18T22:11:55Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "c7e40ee3bdb6779ac25158f772f7ac9cb79e182b",
          "body": "…(#0017) (#1039)\n\nfix(http): missing ASGI/apps service -> clean 404, not 500+traceback (#0017) — 0.21.127\n\nA GET to /{workspace}/apps/{service_id}/... for a service that does not exist\n(in an existing, accessible workspace) raised a bare KeyError inside\nget_service_info on the workspace-manager side\n[…]\nce under the always-present public workspace; #0014 co-test + the present-\nservice 200 path both still pass (shared-middleware non-regression).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(http): missing ASGI/apps service -> clean 404, not 500+traceback …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-31T02:24:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "964f07ad56536048c6a762f54d4bd6779b1680d3",
          "body": "…iness path (#0015) — 0.21.126 (#1038)\n\n* fix(startup): defer + parallelize orphan-service reaping off the readiness path (#0015) — 0.21.126\n\nRoot-cause fix for the 2026-07-29 hypha-server startup CrashLoop.\n\ninit() awaited _cleanup_orphaned_client_services INLINE in the readiness path,\nand that rea\n[…]\nus-loop\nbehavior stays covered in isolation by tests/test_orphan_reaper.py.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(startup): defer + parallelize orphan-service reaping off the read…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-29T18:25:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8594f61a3d731e9eda10003da3e62115e86bc633",
          "body": "…r MCP/SSE churn — 0.21.125 (#1037)\n\nNightly prod review found the top log line by volume was\nWARNING:asyncio:socket.send() raised exception. (~340/24h, bursts, no\ntraceback), clustered around MCP /rpc churn.\n\nRoot cause: asyncio emits this ONLY from its transport's `if self._conn_lost:`\nbranch, onc\n[…]\n_utils.py (drops the two exact messages, passes all\nothers incl. substring look-alikes, fail-open, idempotent install, end-to-end\nsuppression).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(log): silence benign asyncio socket.send() conn-lost warning unde…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-26T02:06:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d5b2654d930817badeb36fb7b403934aabbf4fa9",
          "body": "… 4 & 5) — 0.21.124 (#1036)\n\ndocs(auth): document token revocation + indexed auth-store lookup (#0006 items 4 & 5) — 0.21.124\n\nItem 4 — docs/auth.md now covers the two server-side revocation mechanisms\na custom auth provider should rely on instead of hand-rolling an\n\"is-this-user-still-enabled?\" cac\n[…]\nt the docs recommend (existing\nsearch tests only exercised wildcard $like matches).\n\nNo server behavior change — both mechanisms already exist.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(auth): token revocation + indexed auth-store lookup (#0006 items…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-25T21:12:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "96e907102e15f47254f56f6930d963234f971731",
          "body": "…urn (#0007) — 0.21.123 (#1035)\n\nOn last-client-disconnect the workspace manager unloads an empty\nnon-persistent workspace immediately (delete_client(unload=True) ->\nunload_if_empty). An app that intentionally closes+reconnects on a\ncadence (e.g. a feedback sink reconnecting every ~31s) therefore ch\n[…]\nault behavior)\n - reconnect-within-grace keeps the workspace (guards both the connect\n   cancel hook and the delayed task's emptiness re-check)\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(workspace): optional unload grace period to collapse reconnect ch…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-25T20:18:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9d3c6e9b17f7d1ce9b84b7061dad94332f405444",
          "body": "…(V16) — 0.21.122 (#1034)\n\nThe public `search()`/`list()`/`list_children` @schema_methods built their\nWHERE clause by f-string-interpolating user-supplied input directly into\nSQLAlchemy `text()`: `filters` manifest keys/values, `keywords`, the\n`config.permissions` filter, and the `order_by` JSON-fie\n[…]\nord/config.permissions/order_by injection plus a positive config\npermissions match, across both SQLite and PostgreSQL. CLAUDE.md documents V16.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(security): SQL injection in artifact-manager search/list filters …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-25T19:16:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3d6a172670fc39fa13fc8a0e86ab750ce9948fc4",
          "body": "…otchas (#0006 items 3,6,7) (#1033)\n\nFills the concrete gaps in the \"Custom Authentication Providers\" guide that\nfirst-time integrators hit (from true-toad's production phone+SMS provider):\n\n- Login lifecycle diagram (login → start → index page → report → check →\n  connect → parse_token); the client\n[…]\natches the new\n  contract table (timeout=0 → None instead of raising; report_url/check_url;\n  invalid-key raises).\n\nDocs-only; no version bump.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(auth): custom-auth-provider guide — lifecycle, hook contracts, g…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-25T18:04:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "74c550dfc5cbaff6e865adc87032c9b91d004d09",
          "body": "…0598(c)) (#1031)\n\nCompound-engineering follow-up to PR #1030 (0.21.120): document why the HTTP\nrate limiter runs before auth, why elevation must be by cryptographically\nverified identity (never header presence), and why the authenticated tier is a\nhigh FINITE limit keyed on client_id/sub/workspace rather than a /rpc path\nexemption.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(claude): record pre-auth rate-limiter identity-tiering lesson (#…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-25T17:24:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8be879c9e630b4c0d68a576573e046de0a586ca8",
          "body": "… (#0006 item 2) — 0.21.121 (#1032)\n\nfix(auth): custom-auth extra_handlers receive the authenticated caller as scope[\"user\"] (#0006 item 2) — 0.21.121\n\nHandlers registered via register_auth_service(..., <name>=handler) become HTTP\nfunctions-service handlers on the public hypha-login service; each is\n[…]\ndler_receives_authenticated_user\n(+ whoami handler in tests/custom_auth_startup_test.py). Verified it fails\nwithout the fix and passes with it.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(auth): custom-auth extra_handlers get authenticated scope[\"user\"]…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-25T17:16:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "521652dac3e5982c4fff4391d66b701b7b5f066e",
          "body": "…d rate-limit tier (#0598(c)) — 0.21.120 (#1030)\n\nHTTPRateLimitMiddleware is mounted outermost (before routing AND before auth),\nso it could only ever key on raw client IP. Behind a shared NAT/egress or a\nsingle busy daemon, legitimate first-party /rpc traffic collided with the\nanonymous per-IP buck\n[…]\nnonymous-limited-but-authenticated-not,\nforged/expired token does-not-bypass, client-id keying isolates one daemon,\nmissing-client-id fallback.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(http): authenticated first-party callers get a high identity-keye…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-25T16:18:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f91775937080cfe93cafba12f8cbd35939cd027e",
          "body": "…+traceback (#0014) — 0.21.119 (#1029)\n\nfix(http): unknown/inaccessible workspace on apps path -> 404, not 500+traceback (#0014) — 0.21.119\n\nA GET to /{workspace}/apps/{service}/... for a workspace that does not exist\n(and cannot be auto-created for the caller) raised a bare KeyError inside\nget_work\n[…]\ny the kth-k8s nightly platform review.\n\nhypha/core/store.py::WorkspaceNotFoundError + hypha/http.py;\ntest tests/test_asgi_unknown_workspace.py.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(http): unknown/inaccessible workspace on apps path → 404, not 500…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-25T02:10:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "02f0def0a09b45d7bf21df963987988dfa5d3a33",
          "body": "…0.21.118 (#1028)\n\nfix(http-rpc): self-heal wedged HTTP-streaming connections (#0012) (0.21.118)\n\nProd incident (loop-law): a client's retry-flood (frontend retrying not-found\nsessions in a tight no-backoff loop) filled a svamp-machine's /rpc DOWNSTREAM\nqueue; send_to_queue then dropped messages IND\n[…]\ned by true-toad (ndtai). Companion client-side retry-bound (easy-mule) +\noptional server fail-fast routing for SUSTAINED floods are follow-ups.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(http-rpc): self-heal wedged HTTP-streaming connections (#0012) — …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-23T17:15:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7972cf8d5aadb6218e469030c656340a479a020c",
          "body": "…#0011) — 0.21.117 (#1027)\n\n* fix(http-rpc): liveness reaper for half-open HTTP-streaming clients (#0011) (0.21.117)\n\nA client on the HTTP-streaming transport (/rpc) that died HALF-OPEN (container\nhard-removed / docker compose down yanks the veth → NO FIN) was never reaped:\nthe stream loop only dete\n[…]\neep teardown, #0011), so the\nhelper must set them too (mirroring __init__).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(http-rpc): liveness reaper for half-open HTTP-streaming clients (…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-23T12:44:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "100c15a6724cbc8f8fe6f77e26ce190cff72a137",
          "body": "…#0006 item 1) — 0.21.116 (#1026)\n\nfix(server): --from-env must not silently clobber explicit CLI args (#0006 item 1) (0.21.116)\n\ncreate_application's --from-env path did setattr(args, key, value) for EVERY\nenvironment-derived arg, unconditionally overwriting explicitly-provided CLI\nflags. So a --st\n[…]\nthenticated context, check() contract\ndocs, token-revocation hook, indexed auth-store lookup, custom-provider guide)\nare tracked as follow-ups.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): --from-env must not silently clobber explicit CLI args (…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-22T18:16:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b05a2626338a0f219505a1ca5ef4289a5813fea2",
          "body": "…-spam (#0005) — 0.21.115 (#1025)\n\nfix(apps): daemon apps for an unavailable worker type WARN, not ERROR-spam (#0005) (0.21.115)\n\nProd logged ERROR:apps:Failed to start daemon app ... 'No server app worker\nfound for type: compute-app' ~11x on every restart, for demo apps\n(cap-test/canary-demo/ab-dem\n[…]\n worker type is rejected with the clear worker-not-found\n  message and the server stays healthy\n- version bump 0.21.114 -> 0.21.115 + CHANGELOG\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(apps): daemon apps for an unavailable worker type WARN, not ERROR…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-22T17:34:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0c982649b124aabfa151e86e15d400aac29dba7e",
          "body": "…hildren (#0010) — 0.21.114 (#1024)\n\n* feat(artifact): recipient_can_delete — recipient self-delete of own children (#0010)\n\nCompanion to #0009. A private-children collection configured with\n{\"recipient_can_delete\": true, \"recipient_field\": \"<field>\"} lets a recipient\ndelete (ack/prune) ONLY the chi\n[…]\np 0.21.113 -> 0.21.114 (recipient_can_delete #0010) + CHANGELOG + CLAUDE.md\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(artifact): recipient_can_delete — recipient self-delete of own c…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-22T15:55:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0a3b74f9d080f52b1ad3d869bd092b94d33015ed",
          "body": "…0009 mode-b validation) (#1023)\n\ntest(artifact): lock cross-workspace public private_children collection (#0009 mode-b)\n\nValidates hosting the #0009 recipient-scoped drop-box in the PUBLIC workspace\nas a global, universally-addressable cross-user inbox (backs svamp-user-events\n/ svamp-shared-sessio\n[…]\ngular\nuser is a public-workspace admin, so nobody accidentally bypasses (unlike a\nws-user-<x> home where the owning user is a workspace admin).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(artifact): cross-workspace public private_children collection (#…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-22T15:09:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "04fadc7cc4d5b7f422f59cad27b19b8632efb984",
          "body": "… — 0.21.113 (#1022)\n\n* fix(ws): route expired/invalid token through AuthenticationError — WARNING not ERROR traceback (#0008) (0.21.113)\n\nA client presenting an expired or invalid token on connect is an EXPECTED\nclient condition (the client should refetch), not a server fault — but it\nwas logging a\n[…]\nserts \"Authentication\") and updates the new\n#0008 regression test to match.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ws): JWT-expiry log hygiene — WARNING not ERROR traceback (#0008)…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-22T15:03:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2ea0bd703e0a1fc7e9fc1e4a0ebadd0491c0d04f",
          "body": "… — 0.21.112 (#1021)\n\nfeat(artifact): recipient-scoped private-children collections (#0009) (0.21.112)\n\nA collection configured with\n  {\"private_children\": true, \"recipient_field\": \"<manifest field>\"}\nbecomes a cross-user inbox / drop-box: any writer may create a child\naddressed to any recipient, bu\n[…]\nilters; discovery boundary\n- CLAUDE.md — two artifact permission-model constraints learned here\n- version bump 0.21.111 -> 0.21.112 + CHANGELOG\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(artifact): recipient-scoped private-children collections (#0009)…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-22T13:34:20Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7b533499b1c6e3f8dfa0b5ac90b1ee896f15d98d",
          "body": "…race (0.21.111) (#1020)\n\n* fix(ws): guard register_client() against event_bus=None on reconnect race (0.21.111)\n\nProd teardown race (nightly review, ~2/24h, caught/non-fatal): on a reconnect via\nreconnection_token immediately followed by a 1001 disconnect, the background\nregister_client() task that\n[…]\natures (per ops request — conscious feature call,\nnot a silent ride-along).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ws): guard register_client() against event_bus=None on reconnect …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-14T02:12:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ebc5b2c68ecf24821a37ff0e9023f04827ea4177",
          "body": "… (0.21.110) (#1019)\n\nchore: re-pin bundled hypha-rpc to 0.21.46 — ship inline login client (0.21.110)\n\nCompletes the embedded (no-popup) login feature (server half in 0.21.109). Bumps\nhypha_rpc_version to 0.21.46 (hypha/__init__.py, setup.py, requirements.txt) and\nrefreshes static_files/hypha-rpc-w\n[…]\n 0.21.46 = 0.21.45's inline-login feature + a release-CI fix (npm publish\nnow runs on node 22 / npm@11 after npm@latest raised its node floor).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: re-pin hypha-rpc 0.21.46 — ship inline (no-popup) login client…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-10T23:44:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "26939d7039729e181d7a27461212a1a33c704e85",
          "body": "…pup (0.21.109) (#1018)\n\nfeat(local-auth): embedded (iframe) login support — no popup required (0.21.109)\n\nMany host apps block popup windows, silently breaking login. The local-auth\nlogin page now detects when it's rendered inside an iframe (window.parent !==\nwindow) and, on success, postMessages a\n[…]\nlogin page, asserts the embedded markers AND that window.close()\nis preserved). Full local-auth suite green (10). Version 0.21.108 -> 0.21.109.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: embedded (iframe) login support for local + custom auth — no po…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-10T11:17:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "550ce4e2fabd23e9f74c39b3cd0514ae0c2cdd95",
          "body": "…0.21.108 (#1017)\n\n* feat(local-auth): email verification via Resend + full code workflow (0.21.108)\n\nMake local auth feature-complete: signup → email a short numeric code → verify →\ncreate account. Previously email_verified was hardcoded True.\n\n- Verification code: 6-digit, secrets.randbelow (CSPRN\n[…]\n returns when RESEND_API_KEY is unset (as in CI). Both tests\ngreen locally.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: feature-complete local auth with email verification (Resend) — …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-08T05:59:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c3aa9792881f9b644a95d365922e905f6508badd",
          "body": "…(0.21.107) [HOLD for post-sweep] (#1016)\n\n* fix(websocket): log hygiene — benign lifecycle events no longer log at ERROR (0.21.107)\n\nFlagged during the 0.21.106 prod rollout. Benign WS-lifecycle events were logged\nat ERROR and masked genuine errors during triage.\n\nCENTERPIECE — supersede-cancel no \n[…]\ne and still closes, disconnect() logs INFO not ERROR. 24/24 WS\nsuite green.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: WS log hygiene — benign lifecycle events no longer log at ERROR …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-08T04:21:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e4d59335205ffe0e472512b1463aebf8b1a0639f",
          "body": "…(#1015)\n\nfix(websocket): harden two caught-but-noisy WS-lifecycle bugs (0.21.106)\n\nFlagged by the nightly prod review on 0.21.105. Both were already caught (no\ncrash, no leak) but burned CPU + log volume and masked genuine errors.\n\n[1] Teardown race: filtered_handler hit a niled _subscriptions (~64\n[…]\ngrades the\ntwo benign messages. Both bugs reproduced (TypeError / RuntimeError) before the\nfix, green after. Version bump 0.21.105 -> 0.21.106.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: harden two caught-but-noisy WebSocket-lifecycle bugs (0.21.106) …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-07T02:10:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "920d4c674c0126908bb9987b75ff8947483a951e",
          "body": "…d /rpc memory leak (0.21.105) (#1014)\n\n* fix(http-rpc): close interface connection when __aenter__ fails (prod /rpc leak) — 0.21.105\n\nRoot cause: store.get_workspace_interface() creates the RedisRPCConnection + RPC\npeer synchronously in the factory, before __aenter__ runs. __aenter__ then calls\nget\n[…]\nP /rpc get_workspace_interface __aenter__ leak fix from the same 0.21.105.)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(http-rpc): close interface connection when __aenter__ fails — pro…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-07-02T17:15:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c8efb2ee25a38929aef67f0446778db3fd9cde36",
          "body": "…FS verify https (#991) — 0.21.104 (#993)\n\n* fix(#989): attribute artifact ownership to the effective (human) id\n\nAn artifact created via a generated (agent) token recorded the token's ephemeral\nclient-credentials sub as created_by + the owner permission, so the human (the\ntoken's parent) couldn't s\n[…]\ncess (not a permissions[\"*\"] grant). Security/permission subset: 31 passed.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: effective-id ownership (#989) + non-git error clarity (#990) + L…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-26T00:47:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fde65631995335a3af5c1d3e9936de8c19839539",
          "body": "…history (0.21.103) (#992)\n\nfix(git): shallow clone empty-boundary case (--depth on single-commit / depth>=history)\n\n0.21.102's shallow-clone fix (#986) only emitted the shallow-update section when\nthe boundary was NON-empty. For a repo with no boundary — a single-commit repo\n(--depth=1, HEAD has no\n[…]\ntory) and a\nsingle-commit repo --depth=1. Full tests/test_git.py = 42 passed (full clone,\npush, LFS, all shallow cases). Full clone unaffected.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(git): shallow clone empty-boundary case — single-commit / depth>=…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-25T08:42:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "08c35c6009a3a77b4354ff3453c9b21034ff9821",
          "body": "…(0.21.102) (#988)\n\nfix(git+artifact): support shallow clone (--depth) + validate alias length\n\nTwo validation-batch fixes (0.21.102), both TDD (reproducing test first).\n\n#986 shallow clone: the smart-HTTP upload-pack parsed `deepen` but ignored it,\nreplying NAK where the client expected the shallow\n[…]\nied to FAIL without the fix. Full tests/test_git.py = 43 passed (full clone,\npush, LFS push/pull, anon LFS, shallow all green) — no regression.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(git+artifact): shallow clone (--depth) + alias length validation …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-23T14:03:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8d949efc064e18d49d13a0da03f08880fb6ef893",
          "body": "…0.21.101) (#985)\n\n* fix(git-lfs): resolve public repos anonymously on the LFS batch API (0.21.101)\n\ngit clone of a public git-storage artifact fetched the pack but the LFS smudge\nfailed (\"batch response: Repository or object not found\"); a direct anonymous\nPOST to .../<alias>.git/info/lfs/objects/b\n[…]\nFS push/pull\n  tests otherwise hang to timeout locally). No-op on CI/Linux.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(git-lfs): resolve public repos anonymously on the LFS batch API (…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-23T06:50:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7fc871dc2ea824e4ce6dd74f91bf200316e27737",
          "body": "…OM (0.21.100) (#984)\n\n* fix(mcp): cache adapter per service on POST path (real per-request OOM)\n\n0.21.98 entered StreamableHTTPSessionManager.run() once per adapter and held\nit open in a background task — correct ONLY for a cached/reused adapter (as its\ndocstring assumed). But _handle_mcp_request b\n[…]\nv object-count PASS bar on both\nhappy (valid type:mcp) and bare-echo paths.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(mcp): cache adapter per service on POST path — real per-request O…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-22T22:13:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e190b7f8103838a568c8499280b1786164e7f2be",
          "body": "* release: 0.21.99 — durable Postgres-backed admin blocklist\n\nblock_user/block_ip lived only in Redis, so prod (HYPHA_RESET_REDIS=true) wiped\nthe blocklist on every restart — blocks didn't survive restarts/OOMs/deploys.\n\nNow Postgres is the source of truth (blocklist table / BlockEntry); Redis is a\n\n[…]\ngs/artifacts convention. SQLite is lenient so it only surfaced on Postgres.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: 0.21.99 — durable Postgres-backed admin blocklist (#983)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-22T17:46:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bed60288c53e713e5e2001764c29c641789f949d",
          "body": "… OOM) (#982)\n\n* fix(mcp): enter StreamableHTTPSessionManager.run() once, not per-request (OOM)\n\nThe MCP adapter is cached and shared across all requests for a service, and\nStreamableHTTPSessionManager.run() owns an internal anyio task group designed to\nbe entered exactly once per instance (the app \n[…]\nx (same incident).\n\nTests: tests/test_resource_limits.py::TestCheckBlocked.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(mcp): enter session_manager.run() once, not per-request (residual…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-22T15:42:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e807bd10e8c44b9cd8069d7adf85c240c6e664b9",
          "body": "…980)\n\nrelease: 0.21.97 — fix dedicated browser-worker visibility routing (#978 cutover unblock)\n\nbrowser.py __main__ set the --visibility/HYPHA_VISIBILITY override at the top\nlevel of the service config instead of inside config, where register_service\nreads it. The override was silently dropped, so\n[…]\ndicated-worker\ncutover that keeps headless-Chromium memory off the API pod. Now matches the\nk8s/conda/terminal workers. Adds a regression test.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: 0.21.97 — fix dedicated browser-worker visibility routing (#…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-22T11:22:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7bae9b5441ca1d65911ed8ff5bcb67fbf3f35f5c",
          "body": "…of pack size) (#979)\n\n* feat(git): range-read S3 pack (O(1) clone/fetch memory)\n\n* test(git): single-blob memory guard 3.0x→5.5x (range-read doesn't improve single giant blobs)\n\nCI caught it: test_git_clone_memory_peak uses a single 200MB blob, which is the\ninherent worst case range-read does NOT i\n[…]\ndelta is well under repo size and the < 2.0x guard is both\nmeaningful (catches a whole-pack-reload regression) and non-flaky. The O(1)\nproof across pack sizes remains test_git_clone_memory_flat_curve.",
          "is_bot": false,
          "headline": "feat(git): range-read S3 pack — O(1) clone/fetch memory (independent …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-22T01:04:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "47a14e921d11599d6df43d4999f108b82932c28f",
          "body": "…wser-free (#978)\n\nThe in-process browser worker (registered under --enable-server-apps) spawns\nheadless Chromium as children of the API server process — the dominant OOM\nrisk on a memory-limited pod, and a reconnection storm that respawns browser\napps can crash-loop the server (observed in prod: 38\n[…]\ng Chromium memory\noff the API pod. Required for a clean dedicated-worker cutover since worker\nselection could otherwise route to either worker.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(apps): HYPHA_DISABLE_INPROCESS_BROWSER_WORKER to run API pod bro…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-21T22:56:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e1f3f277e0f5023be602e3aaf16e38aad48fa978",
          "body": "…memory fix) (#977)\n\n* feat(git): streaming clone + disk-spill push + concurrency cap (root memory fix)\n\n* test(git): gate RSS-peak assertion to Linux (malloc_trim is a no-op off glibc)\n\nThe streaming/disk-spill correctness is covered by the fsck clone/thin-pack\nroundtrip tests on all platforms; onl\n[…]\noth in-memory and rolled-to-disk spools, still streams, Content-Length set.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(git): streaming clone + disk-spill push + concurrency cap (root …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-18T20:23:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "751d6b3f7b521456cf585907e36e8a2a43c4d6fb",
          "body": "…976)\n\nFollow-up to the per-request git trim (PR #975). Live prod diagnostic on\n0.21.93 showed RSS plateauing ~2.1GB of which malloc_trim(0) reclaimed ~1.3GB\n(gc freed 0, normal object graph) — i.e. glibc-arena-retained FREE memory, NOT\na leak. The per-request trim only fires on git ops, so memory f\n[…]\ngit trim stays for immediate relief of multi-GB git spikes.\n\nTests: tests/test_malloc_trim.py (task lifecycle + coroutine safety, docker-free).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(memory): periodic malloc_trim to bound glibc-arena RSS plateau (#…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-18T18:08:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "47054e36c426dfa2db2c7bb4983017732cf6280f",
          "body": "… tuning) (#975)\n\nfix(git): release pack memory after each request (malloc_trim + close) + arena tuning\n\nProduction OOM root cause (diagnosed live: gc.collect freed 0, malloc_trim(0)\nreclaimed ~1-1.6GB): git clone/push buffer whole packs (request body, the\ngenerated pack BytesIO, the joined response\n[…]\nt concurrency cap (follow-up; to be sized from a Linux measurement).\nglibc behavior can only be validated on Linux (not the macOS dev harness).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(git): release pack memory after each request (malloc_trim + arena…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-18T17:09:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "aa542eee0bc1b0329836dc0f4959010cdd1e5fd4",
          "body": "…#974)\n\nTwo git smart-HTTP permission fixes (also shipped as the 0.21.92 hotfix\nbuilt from stable 0.21.86 for an N=1 prod deploy):\n\n1) Under-grant (the 'Josh' bug): artifact _permissions are keyed on the\n   stable human user id, but a token minted via generate_token() (the\n   realistic git credentia\n[…]\nact\nsuites (137 passed locally). The ws-level over-grant is intentionally NOT\nchanged here (deferred as a separate, wider-blast-radius change).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(git): honor effective/parent id in artifact perms + 403 not 404 (…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-18T15:15:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7500f195f073f14cb8fc902e0f47a7bc8be729ab",
          "body": "list_apps now derives app id from the authoritative artifact alias instead of trusting the manifest blob, fixing the safe-colab Applications page crash (TypeError: Cannot read properties of null reading 'startsWith'). Bumps 0.21.89 -> 0.21.90.",
          "is_bot": false,
          "headline": "fix(apps): list_apps non-null id + release 0.21.90 (#971)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-17T10:32:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8dc781dfff28ed0c848187b2a3e0f462f0106222",
          "body": "The fastapi_server fixture generated ROOT_TOKEN = secrets.token_urlsafe(32)\n(~43 chars). The server's root-token complexity check rejects tokens <64 chars\nthat contain a simple substring (abc/123/root/test/...), so a random short\ntoken intermittently tripped it (\"Root token appears to be too simple\"\n[…]\n Use\ntoken_urlsafe(64) (~86 chars), which is over the 64-char exemption and always\npasses. Distinct from the fastembed and reject-storm issues.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: use >=64-char root token in fixture to fix flaky server startup",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-06-17T06:54:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "250d6a256b584654b55e27cc54367ce895d6b50f",
          "body": "…ures\n\nThe fastembed model fetch (BAAI/bge-small-en-v1.5) is intermittently slow or\ntemporarily unavailable (\"Could not load model ... from any source\"), which\nrepeatedly failed the release build via test_artifact_vector_collection and is\nalso a real server-startup hazard. New hypha.utils.load_faste\n[…]\nrs.\n\nTests: tests/test_fastembed_retry.py (monkeypatched fastembed) — retries then\nsucceeds; re-raises after exhausting; passes kwargs through.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(vectors): retry fastembed model download on transient HF/CDN fail…",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-06-17T06:48:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a7d8a8e36882385ef04ee6e36deec3276228c429",
          "body": "…facet)\n\nShips #970: the dead-peer check now fast-fails only primary calls awaiting a\nresponse (carry a \"session\"); fire-and-forget results/rejects/callbacks to a\ngone peer are dropped silently — eliminating the reject-storm that churned\nclients into reconnect loops at N>=2 when they disconnect mid-RPC. With the\nmigration fix in 0.21.88 (#969), hypha-server is safe at N>=2.\n\nBumps all version pins. Last commit so the auto-release fires.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): 0.21.89 — fix multi-replica reject-storm (F6, second …",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-06-17T06:24:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5fae9cb68eedcb46d31dd1dff689b4e14a2ae50f",
          "body": "…>=2) (#970)\n\n* fix(f6): drop fire-and-forget messages to gone peers (reject-storm, N>=2)\n\nSECOND N>=2 incident (2026-06-17, distinct from the migration fix #969): when\na client with in-flight RPCs disconnects, the server cleans up its pending\npromises by routing reject/result callbacks back to the \n[…]\ntest_dead_peer_reject_storm.py),\nwhich fail without their respective fixes.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(f6): drop fire-and-forget messages to gone peers (reject-storm, N…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-17T06:23:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1ff3821de8c8d94aab948734a521bbf739594da3",
          "body": "…t (F6)\n\nShips the cross-pod dead-peer fix (#969): on (re)connect a pod broadcasts\nclient-reconnected so every pod clears the migrated client from its per-pod\n_recently_disconnected cache — fixing the N>=2 false-reject (\"Target peer is\nnot connected\") that forced the first multi-replica rollout back\n[…]\ne.\n\nBumps all version pins per the release checklist. This is the LAST commit so\nthe auto-tag/auto-publish Release job detects the new version.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): 0.21.88 — fix multi-replica cross-pod RPC false-rejec…",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-06-17T03:03:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a002c7d229d144edd8ee717b2de60c487f57648a",
          "body": "…correctness) (#969)\n\n* fix(f6): clear cross-pod recently-disconnected cache on re-pin (N>=2 correctness)\n\nPROD INCIDENT (2026-06-17): with hypha-server at N>=2, the dead-peer check in\nRedisRPCConnection.emit_message (\"Target peer <id> is not connected\") false-\nrejected RPCs to a peer that had re-pi\n[…]\nt migration; test client re-pin across pods, not just stable\ncross-pod RPC.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(f6): clear cross-pod recently-disconnected cache on re-pin (N>=2 …",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-17T03:02:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "070a6424bf772c12c5579feb349456724386ec1f",
          "body": "… download\n\n60s was still occasionally too tight: the text-embedding add_vectors triggers\na one-time ~130MB fastembed ONNX model download (BAAI/bge-small-en-v1.5) on\neach fresh CI runner, which under CI network/CPU load can exceed 60s — the test\nflaked again on the release commit. Use 180s (≈3x margin over a worst-case cold\ndownload) to make it deterministic.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(artifact): raise vector-collection timeout to 180s for fastembed…",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-06-16T19:16:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a2cf2d4e4f12eafdfb3a29deb13f076a05fe2079",
          "body": "…ening\n\nRelease 0.21.87. Ships F6 Phase 1 (#964–#968): leader election + leader-gated\nautoscaling, per-resource locks for workspace-cleanup and app inactivity-stop,\nand a reset-redis guard so a restarting replica can't wipe a live cluster —\nmaking hypha-server safe to run with N>=2 replicas sharing \n[…]\n+ one real Redis).\nAlso includes CI fixes (Release-job pip provisioning; flaky vector test).\n\nBumps all version pins per the release checklist.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): 0.21.87 — F6 Phase 1 multi-replica control-plane hard…",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-06-16T19:06:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7afb4f75de1fd59d6ffeb8ff9860674caf78c85b",
          "body": "test_artifact_vector_collection intermittently failed main CI with\n\"TimeoutError: ...add_vectors\": embedding generation (sentence-transformer,\nincl. cold start) can exceed the default ~10s RPC method timeout under CI CPU\nload. The same tree passed in the PR build, confirming flakiness, not a\nregression. Give that connection a 60s method_timeout so the embedding-heavy\nadd_vectors calls have headroom. Unrelated to F6.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(artifact): raise method timeout for vector add to fix flaky CI",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-06-16T18:29:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a028983683b8f65c8d9834f7f3c120e37d2c1620",
          "body": "In a multi-replica deployment several replicas may each register an\ninactivity tracker for the same app session, so the inactivity callback can\nfire on each of them and race on _stop. _stop_after_inactive now takes a short\nper-session lock (app-stop-lock:{id}, 30s TTL) via the new\nServerAppControlle\n[…]\nfakeredis): only one replica acquires the lock; different\nsessions don't block each other; the lock expires to allow a later stop.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(f6): per-session lock for app inactivity-stop (Phase 1, P4) (#968)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-16T15:46:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "32dd494c856ae63074ce53425d14514fb241da13",
          "body": "The Release job (push to main) failed at \"Upgrade pip\" with\n\"No module named pip\": the conda env created by setup-miniconda can resolve\nwithout pip, so `python -m pip install pip` fails. Same root cause as the\nbuild-job fix (78855189) and the PyPI publish fix (#962); the Release job's\npip step was the last one still unpatched. Provision pip via conda first.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci(release): provision pip in conda env for the Release job",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-06-16T15:05:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9518ed637c1c4b806eba67d0be738f692a2fb87f",
          "body": "…1) (#967)\n\nfeat(f6): guard reset-redis + real multi-replica integration tests (P1)\n\nP1/P0 — protect a live cluster from a flush:\nRedisStore._maybe_reset_redis() flushes shared Redis only when reset is\nrequested AND no other hypha server is already registered (peers detected\nvia their public built-i\n[…]\ns\nwhen a peer is registered, no-op when not requested.\n\nCompletes F6 Phase 1 (P0/P1 + P2 #965 + P3 #966 on the leader-lease #964).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(f6): reset-redis guard + real multi-replica integration tests (P…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-14T09:00:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2f9d4a87a0343d56bad7167db36e4d195df997ab",
          "body": "Prevents several replicas' activity trackers from concurrently cleaning up\nthe same inactive workspace, without leaking workspaces.\n\n_cleanup_inactive_workspace() now takes a short per-workspace NX lock\n(ws-cleanup-lock:{id}, 30s TTL) before deleting; if another replica holds it,\nthis replica no-ops\n[…]\ntimer and\nkeeps the workspace when clients are still present. Updates\ndocs/multi-replica-design.md §3.1/P3 to record the decision.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(f6): per-workspace lock for activity cleanup (Phase 1, P3) (#966)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-14T08:53:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "00f80f65074853be27de99bda25c17e0cf79118e",
          "body": "…se 1a) (#965)\n\nBuilds on the Phase-0 leader-lease primitive (#964). Wires it into the store\nand uses it to gate the autoscaling control-plane singleton so it does not\nrun on every replica.\n\n- RedisStore.init() starts a LeaderLease (identity = server_id); teardown()\n  stops it. New RedisStore.is_lea\n[…]\np loop (P3, needs care to avoid a cleanup-leak regression) and\nidempotent built-in startup (P1). See docs/multi-replica-design.md.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(f6): wire leader lease into store + leader-gate autoscaling (Pha…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-14T03:15:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d12ac126e561655fe9ce1a33384870a84d5dd30d",
          "body": "feat(f6): add Redis leader-lease primitive (Phase 0)\n\nAdds hypha/core/leader.py — a best-effort single-leader election over a\nshared Redis key, the \"exactly-one-runner\" primitive for the control-plane\nsingletons that must not run on every replica in a multi-replica deployment\n(autoscaling monitor, w\n[…]\na peer's lease, failover after expiry, end-to-end loop promotion, ttl/\nrenew-interval guard, key isolation. 10 tests, all passing.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(f6): Redis leader-lease primitive (Phase 0) (#964)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-14T01:57:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9388233d1c8548ae6e40e8716cce29cf492706a3",
          "body": "Adds docs/multi-replica-design.md scoping F6 (multi-replica hypha-server):\ndata-plane already horizontally scalable; the work is control-plane\nhardening (leader-lease over autoscaling/activity-cleanup, idempotent\nstartup) + a config fix (HYPHA_RESET_REDIS) + sticky affinity for Phase 1.\n\nReconciles \n[…]\nHPA). Phased plan; Phase 1 targets zero-blip rollouts and\nfinally validates the shipped F4/F5 reconnection work on a warm replica.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(f6): scope multi-replica hypha-server design (#963)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-14T01:51:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "03110657f6dd7a575b1a427f0a6e9c0c80885169",
          "body": "The PyPI publish job sets up a conda env via setup-miniconda, but that env\ncan resolve without pip, so the next step's `python -m pip install pip`\nfailed with \"No module named pip\" — blocking the 0.21.86 release publish.\n\nProvision pip via `conda install` first (mirrors the test-env fix in\n78855189), then upgrade it.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci(publish): provision pip in conda env before PyPI publish (#962)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-13T20:32:14Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9eea27d44752e0e06b57221c97e102c09696c8a9",
          "body": "Release 0.21.86. Ships F4 (graceful WS + HTTP-stream connection draining on\nserver shutdown, merged in #960) and bumps the bundled hypha-rpc dependency\n0.21.38 -> 0.21.42.\n\nhypha-rpc 0.21.42 brings:\n- getService/wm proxy retarget to the new manager_id after reconnection\n  (avoids a spurious 400 on g\n[…]\n in requirements.txt/setup.py/__init__.py) and refreshed the bundled\nhypha-rpc JS static assets via scripts/upgrade_rpc_assets.py.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(release): 0.21.86 + bump hypha-rpc to 0.21.42 (#961)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-13T19:35:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "21c039ded78f3bac437a22e3b9f15d6cfe2596da",
          "body": "…n (#960)\n\nOn rollout/redeploy the old pod cut long-lived connections abruptly, so\nclients only detected the dead pod via their heartbeat/read timeout and\nall reconnected in the same window — a thundering-herd reconnection storm\non the new pod.\n\nRoot cause: RedisStore.teardown() closed only WebSocke\n[…]\nocks).\n\nTracked as F4 (svamp reliability audit). The companion k8s preStop drain\nlives in the deployment manifests, not this repo.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(shutdown): gracefully drain WS and HTTP-stream clients on teardow…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-13T16:21:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7e31b88a76f754dadcb74fae34acea6f8a9068ed",
          "body": "…t (#958) (#959)\n\n* fix(auth): wildcard scope must not shadow stronger per-workspace grant (#958)\n\nA workspace owner who is not a global admin could not start a server-app in\ntheir own workspace: apps.start mints a per-app client token via\ngenerate_token, which requires admin on the target workspace\n[…]\nstall pip to make env provisioning\ndeterministic.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(auth): wildcard scope must not shadow stronger per-workspace gran…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-06-13T15:42:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a06f5cd23dd86b59c3e1edf4d9c4205ae354b04c",
          "body": "…957)\n\nExternal report: 5 sequential GETs to /zip-files/data.zarr.zip/~/0/.zarray\non a 236 GB / 3.6M-entry ZIP64 archive each took 28–55 s and timed out\nVizarr's HTTP client. A 4.68 GB / 71k-entry archive on the same path took\n~0.7–1.3 s. The functional ZIP64 fix from 0.21.84 worked, but exposed a\np\n[…]\nget_zip_file_content_endpoint{,_large_scale,_very_large}`.\nZIP64 functional tests from #956 still pass.\n\nBumps version to 0.21.85.\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(zip-files): memoize parsed central directory to fix perf cliff (#…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-05-02T12:26:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b307dfce71362c43a06a47598cb3feacfd124931",
          "body": "…ies) (#956)\n\nReported by an external agent against artifact reef-imaging/poc-hpa-plate1-zip:\nGET .../zip-files/data.zarr.zip/~/.zattrs returned 500 with \"Corrupt zip64\nend of central directory locator\" on a 4.68 GB / 71308-entry ZIP64 archive\nthat python's zipfile validates correctly when given the\n[…]\numps version to 0.21.84 and syncs helm-charts / docker-compose tags\n(previously stuck at 0.21.78) per CLAUDE.md release checklist.\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(zip-files): correctly handle ZIP64 archives (>4 GB or >65535 entr…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-05-02T08:26:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4e5342661fe76c17508767ee7605d8c94cba29c0",
          "body": "…rom #938) (#955)\n\nfeat: add connection admission control to prevent reconnection storms\n\nWhen a server restarts, all connected clients reconnect simultaneously,\ntriggering heavy Redis SCAN/DELETE operations that saturate the event\nloop and cause cascading liveness probe failures. This adds a semaph\n[…]\nnection setup and random jitter\n(0-1s) for reconnecting clients to spread the load.\n\nConfigurable via HYPHA_MAX_CONCURRENT_CONNECTIONS env var.\n\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: connection admission control for reconnection storms (rebased f…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-05-02T07:38:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a6c8bd9d971847c1efaf2a25d53e411a9eb9820a",
          "body": "Adds docs/login.md — a focused, agent-friendly guide for client-side\nauthentication: Python and JavaScript login() flows, login_callback\npatterns, programmatic generate_token, expiration handling, logout, and\ntroubleshooting. Sourced from the actual hypha-rpc client signatures.\n\nAudits the agent-ski\n[…]\n the skills\n  zip so offline agents see them.\n\nNo new behavior — purely documentation surfacing. All 56 test_skills.py\ntests pass.\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(agent-skills): add login guide and audit guide cross-links (#954)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-04-28T14:39:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dd38f63216f2cca74fea7f86ac746bdffa1a0c87",
          "body": "…) (#953)\n\nA signed-in browser sending its access_token cookie to a public service\nURL in an arbitrary workspace was rejected with a workspace-level 403\nbefore the per-service visibility check ran, even though the same URL\nworked anonymously.\n\nNow the HTTP route only requires workspace read permissi\n[…]\nder and\naccess_token cookie auth paths, and verifying that protected services\nin unowned workspaces remain forbidden.\n\nCloses #952\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(http): defer workspace permission check for public services (#952…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-04-28T14:38:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "af7c20fc4df0e7a583c49bb24f361a4af64c0891",
          "body": "…ts (#951)\n\nSome S3-compatible providers — notably Google Cloud Storage with scoped\nHMAC keys — return AccessDenied on CreateBucket even when the bucket\nalready exists and the key can read/write objects in it. This prevents\nhypha from starting after an image upgrade whenever the provisioning\nHMAC ke\n[…]\nObserved in production: a 0.21.82 rollout crash-looped for 14 days with\n>3900 restarts because CreateBucket returned AccessDenied instead of\nthe BucketNameUnavailable code the earlier fix anticipated.",
          "is_bot": false,
          "headline": "fix(s3): handle AccessDenied on CreateBucket when bucket already exis…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-04-26T22:03:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ddad7f37df61b21682ab90c10070dbc5cb81edd0",
          "body": "Adds an optional ``email`` field to ``TokenConfig``. When set, ``generate_token``\nwrites it onto the newly-minted JWT's email claim. Restricted to callers\ncarrying the ``admin`` role so a workspace admin cannot forge emails for\nanother user.\n\nMotivation: downstream services that validate email on in\n[…]\nine tokens because admin ``generate_token``\ncalls produce tokens with ``email: null``. This lets operators mint\nuser-attributed tokens so those gateways can authenticate and attribute\nusage correctly.",
          "is_bot": false,
          "headline": "feat: allow admins to override email claim in generate_token (#950)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-04-26T22:00:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "56b63eb06ec918c4f6a93d42dc302f8c1f7e822b",
          "body": "feat: support wildcard artifact-scoped tokens for get_file and put_file\n\nAdd wildcard `*` path support for artifact-scoped tokens, allowing a single\ntoken to grant access to all files within a specific artifact without\ngranting access to the entire workspace.\n\nTokens can now use `get_file:<artifact_\n[…]\norted.\n\nAlso adds `token` query parameter to the PUT upload endpoint for\nscoped token authentication on file uploads.\n\nCloses #948\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: support wildcard artifact-scoped tokens (#949)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-04-26T21:58:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b7f60031765a35c4e14e6c2bc33c8754ff41b5fd",
          "body": "* fix: connection counter leak causing user lockout and memory drift\n\nThe resource limits manager's connection counters (per-user and\nper-workspace) were not properly decremented in several code paths,\ncausing counters to inflate over time. After 7 days in production,\ntracked connections reached 258\n[…]\n@anthropic.com>\n\n* chore: bump version to 0.21.82\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: connection counter leak causing user lockout (#947)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-19T06:54:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d9cd27acbfe7083e5f9f5c965265b762044abb8c",
          "body": "* chore: upgrade hypha-rpc to 0.21.36 and bump hypha to 0.21.81\n\nIncorporates oeway/hypha-rpc#159 which fixes JS kwargs unpacking in\n_handle_method — Python→JS calls with keyword arguments now map correctly\nto named parameters instead of passing the kwargs dict as a positional arg.\n\nCo-Authored-By: \n[…]\n\n* fix(test): update numpy echo assertion for kwargs unpacking\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: upgrade hypha-rpc to 0.21.36 and bump hypha to 0.21.81 (#946)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-19T05:57:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8ed434869ac9c46112561ff2ecd8ec980b8cbbc2",
          "body": "fix: use generation counter to prevent reconnection race in handle_disconnection\n\nWhen a client reconnects quickly, the old connection's handle_disconnection\ncan race with the new connection's service registration:\n\n1. Old connection closes → handle_disconnection starts\n2. Client reconnects → new co\n[…]\nck in case reconnection happened during\n  earlier async work\n\nThis eliminates the 2/3 reconnection flake in test_multiple_clients_reconnection.\n\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: prevent reconnection race in handle_disconnection (#942)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-19T03:58:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "56fea1ca090b8f5a34aca9f663db184085f1efc3",
          "body": "…945)\n\n* feat: add resource limits, admin blocking, and HTTP rate limit improvements (#943)\n\n- Increase HTTP rate limits (20→100 req/s, 100→500 burst) to prevent\n  daemon clients from being rate-limited during normal multi-session use\n- Add Retry-After header to 429 responses for proper client backo\n[…]\nONNECTIONS_PER_USER: 50 → 200\n- HYPHA_MAX_CLIENTS_PER_WORKSPACE: 200 → 1000\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: resource limits, admin blocking & HTTP rate limit fix (#943) (#…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-11T06:48:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "72f55174aced4a3e1217b434e4e1de0acbb93db0",
          "body": "* fix: add per-client WebSocket rate limiting to prevent server crash loops\n\nAnonymous clients spamming RPC calls (65+ service registrations/sec) saturate\nthe event loop, causing liveness probe timeouts and a self-reinforcing\ncrash-restart cycle (28 restarts in 19 hours observed in production).\n\nAdd\n[…]\nuse pattern (sustained 65+ msg/sec\nservice registration spam over minutes).\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: per-client WebSocket rate limiting to prevent crash loops (#937)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-08T10:11:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1cd40f30d37ab46ce92caf523c2af79d43b21ca7",
          "body": "…anup note\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(admin): update SKILL.md: 0.21.78 live, peak scale baselines, cle…",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T12:20:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "835a1167143b45dd5a1fcac7dcac4f51b6b0d44c",
          "body": "Includes:\n- perf(workspace): batch Redis pipeline for list_services, list_clients,\n  delete_workspace, cleanup_client (N HGETALL → 1 pipeline round-trip)\n- feat(admin): fast cleanup cmd + updated alert thresholds for 2000+ connections\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump hypha to 0.21.78 (#935)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-07T11:30:21Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9c412f5bfcd503ac376f8b3d64f09f937dd47b60",
          "body": "…e (#934)\n\n* perf(workspace): batch HGETALL calls in list_services() using Redis pipeline\n\nReplace N sequential HGETALL Redis calls with a single pipeline round-trip.\nPreviously, list_services() scanned for matching keys (fast), then fetched\neach key's hash individually in a for loop — N+1 Redis rou\n[…]\n,\n  cleanup timing note, _cleanup_orphaned_client_services scale gotcha\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(workspace): batch HGETALL in list_services() using Redis pipelin…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-07T10:46:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "68619edbb381a711bea949b2aea9af66727d9d6d",
          "body": "…ts fix\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(admin): update SKILL.md: 0.21.77 live, document limit_max_reques…",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T07:31:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "79b9390e4033e023155286da66a3a634867b990c",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump hypha to 0.21.77",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T07:04:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "70926abad3c15355ecde5a099bf57d79adb86ef4",
          "body": "Includes: fix: remove limit_max_requests from uvicorn (#932)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump hypha to 0.21.76",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T06:54:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "27202d9efdc5d407c3aa64b64197eadaa70df027",
          "body": "… failures (#932)\n\nSetting limit_max_requests=10000 caused uvicorn to restart the worker\nprocess after 10k requests. During reconnection storms (server upgrade,\n100+ clients reconnecting), this limit was hit in ~12 minutes, causing\na brief window where the server stopped accepting TCP connections.\n\n\n[…]\n and GC fixes in\nrecent PRs (#920, #921, #923, #924, #925) provide proper memory management\nwithout needing periodic uvicorn worker respawns.\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: remove limit_max_requests from uvicorn to prevent liveness probe…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-07T06:53:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2c68cbeaa26628839c6727dd3554c57482bbc69e",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(admin): update SKILL.md: 0.21.75 live, Redis pool threshold 900",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T04:54:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1a3fba32e1da15be24d4090fd0770135e2af7c87",
          "body": "At 521+ active RPC connections, ~562 Redis clients is proportional\nand expected (ratio ~1.08 per connection). The old threshold of 500\nwas set for 80-130 active connections. 900 allows up to ~830 active\nconnections before alerting, appropriate alarm for a real pool explosion\nlike the 1218 pre-upgrade incident.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(admin): raise HIGH REDIS POOL threshold 500→900",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T04:53:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "06459f25ab47e570f9b121278d047427baca3eaa",
          "body": "- Raise HIGH WS SERVICES threshold: 200 → 1000 for hypha-agents\n- Update health baselines to reflect current high-load operation\n  (Active RPC 150-350, services 300-750, etc.)\n- Update hc-* known issue: 4Gi → 6Gi (bumped Mar 7 2026)\n- Update version notes: 0.21.74 LIVE, 0.21.75 building\n- Fix hypha-server memory note (currently ~2Gi RSS)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(admin): update SKILL.md with current baselines and thresholds",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T04:31:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9f4c0f548ae55d1369829845535aa94e3cfb3da9",
          "body": "The exec_py code was calling kickout_client(client_id, context=...)\nbut the actual signature is kickout_client(workspace, client_id, code, reason).\nFixed to pass all required positional args, no context kwarg.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(admin): fix kickout_client call signature",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T04:28:49Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4a827639d68c0b02220a715d818202f3fe632ee3",
          "body": "With hypha-agents running 600-750+ services (compute worker proxy\nregistrations), the 1000 threshold was firing as noise. 1500 gives\nheadroom while still catching real leaks.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(admin): raise HIGH SERVICES threshold to 1500",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T04:07:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f7ee0ad6ed048d3e91f00f15d77b8e5ea552511d",
          "body": "Includes: fix(apps): preserve worker_managed sessions on client disconnect (#899) (#930)\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump hypha to 0.21.75 (#931)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-07T04:05:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c6f401ff54e55ddaaba39cf96bdf8fdb9fce5de7",
          "body": "- HIGH RPC threshold: 300 → 600 (369 is now normal with many hc-compute sandboxes)\n- HIGH WS SERVICES threshold for hypha-agents: 200 → 1000 (628 services is expected with many deployed apps)\n- HC POD HIGH MEM threshold: 60% → 75% (60% has lots of headroom, alert at true danger zone)\n- Add hc_pods.total/running/oom_killed summary counts to report JSON output\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(admin): tune thresholds and add hc_pods summary to report",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-07T03:50:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d6a2b726cdecf81857b6c0187a9e7a01ea69c1c0",
          "body": "…9) (#930)\n\n* feat(admin): add version-check command to compare live vs latest GitHub release\n\nQuickly shows if the live server is behind the latest GitHub release.\nOutput: live version, latest release tag+date, UP TO DATE / UPGRADE AVAILABLE status.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthr\n[…]\npha-compute self-install pattern (installs from GitHub main at startup)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(apps): preserve worker_managed sessions on client disconnect (#89…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-07T03:04:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c496a9d354d56cb642d3c0e104dbaf723e1fa797",
          "body": "* chore: bump hypha to 0.21.74\n\nIncludes fixes merged to main since 0.21.73:\n- fix: clean up ghost _last_seen entries in idle cleanup loop (#925)\n- fix: propagate worker_id from install() through commit_app() to start() (#926)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n\n* feat: add s\n[…]\nte SKILL.md — 0.21.73 deployed, OOM detection note, known issues update\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump hypha to 0.21.74 (#928)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-07T02:15:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d9e8f02205ccb5b591349fe77574707d9f6d9499",
          "body": "…ly ignoring them (#929)\n\n* fix: delete null session metadata fields from Redis instead of silently ignoring them\n\nWhen `_store_session_in_redis` encountered a key with value `None`, it\nsilently skipped it. This meant that if a caller set a field to `None`\nintending to clear it, the previous value f\n[…]\nelds are never written\n- multiple null fields in one update all deleted\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: delete null session metadata fields from Redis instead of silent…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-07T00:51:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c2105c796fbc70492ac8e295fe9cce5275703199",
          "body": "feat(admin): add version-check command to compare live vs latest GitHub release\n\nQuickly shows if the live server is behind the latest GitHub release.\nOutput: live version, latest release tag+date, UP TO DATE / UPGRADE AVAILABLE status.\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(admin): add version-check command (#927)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-06T23:52:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ca8216c1d0d66cff07bdc5542b286428139b77d4",
          "body": "…() (#926)\n\nWhen apps.install(worker_id=...) was called with a cross-workspace\nworker (e.g. hypha-agents/hypha-compute-worker), the worker_id was\nused for the compilation step but silently dropped when calling\ncommit_app() for the verification run. commit_app() then fell back\nto get_server_app_worke\n[…]\n start() call. The worker selection logic in start() already\nhandles cross-workspace worker IDs correctly via get_worker_by_id().\n\nFixes #922\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: propagate worker_id from install() through commit_app() to start…",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-06T23:13:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e4389f27f6beb60f7b08236025bf0b61cef85405",
          "body": "Read /sys/fs/cgroup/memory.current when available (cgroups v2) for\naccurate container memory reporting instead of summing psutil RSS values\nper-process, which overcounts shared memory pages.\n\nFalls back to proc_rss + children_mb on non-cgroup environments.\n\nCgroup reports ~1947 MB vs kubectl top 1703 Mi (working set, excludes\npage cache) — both are accurate; cgroup includes cached pages.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(admin): use cgroup memory.current for accurate container_mem_mb",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-06T21:53:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9b1c10d984671e4c90caaeb0e480b1dd76a6f498",
          "body": "… pattern\n\n- Add pending_rpc_calls and top_types to Patterns & Gotchas section\n- Add pending_rpc_calls baseline row to Health Baselines table\n- Document memory growth ~2-3 MB per service (not a leak)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(admin): document pending_rpc_calls, top_types, and memory growth…",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-06T21:23:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cefde2b0c091ca395da6ce4b1aa1d131851474c2",
          "body": "- Capture task snapshot once (_task_snap) to avoid calling all_tasks() 4x\n- Add top_types: top 8 task coroutine types by count — shows WS infra,\n  heartbeats, Timer._job (pending RPC calls) and any accumulating patterns\n- Add pending_rpc_calls: count of Timer._job tasks (each active RPC call\n  creat\n[…]\nis makes task bursts (e.g. 467 Timer._job during hypha-agents burst)\nvisible in the report without needing to run a separate 'tasks' command.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(admin): add top_types and pending_rpc_calls to report tasks section",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-06T21:22:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b7885c238e5e9dc772986b5c0a96a5510dffa33e",
          "body": "Adds not_in_ws field to connections in the JSON report. This shows how\nmany clients have services registered in Redis but are not in the active\nWebSocket dict (potential HTTP transport clients or zombies). Also adds\nSUSPECT CLIENTS alert when not_in_ws > 5 to prompt running 'zombies'.\n\nThis avoids the need to run quick-zombies as a separate command in most\nroutine health check iterations.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(admin): add not_in_ws count to report connections section",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-06T21:03:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b46bfad6ae6f75279a3d1f4c096746a30bc68fe3",
          "body": "…weaviate new pod\n\nContainer memory baseline raised from 1200-1600 to 1400-1800 Mi to reflect\nhypha-agents running 120+ services (compute worker proxy registrations).\n\nhypha-weaviate pod replaced on Mar 6 2026; old pod had 85 OOM restarts.\nNew pod (58d9745f9) is stable at ~115 Mi with 0 restarts.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(admin): update baselines — container memory 1400-1800 Mi, hypha-…",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-06T20:47:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e39f3149b22ef7ac35b5f7d8c7c465339242c5b0",
          "body": "…threshold\n\n- Add rpc_object_entries to report tasks section (gc scan for RPC._object_store);\n  baseline 50K-80K; alert threshold 200K\n- Raise HIGH WS SERVICES alert threshold for hypha-agents to 200 (was 100);\n  hypha-compute-worker legitimately registers 120+ proxy services\n- Update SKILL.md baselines: RSS 800-1200 MB, new rpc_object_entries row,\n  updated hypha-agents service count documentation\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(admin): add rpc_object_entries metric and tune HIGH WS SERVICES …",
          "author_name": "oeway",
          "author_login": "oeway",
          "committed_at": "2026-03-06T20:45:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1896f72966095d7d2d0c7540143f8a43c65af43a",
          "body": "The _do_idle_cleanup() method only removed _last_seen entries when an\nactive WebSocket was found. Ghost entries (in _last_seen but not in\n_websockets) were silently skipped and accumulated indefinitely.\n\nRoot cause: a client entry created during a reconnection race where the\nold connection's handler\n[…]\nalled.\n\nObserved live: ws-user-github|478667/r0u78ukody client persisted in\n_last_seen for 9+ hours with no active WebSocket and no services.\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: clean up ghost _last_seen entries in idle cleanup loop (#925)",
          "author_name": "Wei Ouyang",
          "author_login": "oeway",
          "committed_at": "2026-03-06T20:05:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 100,
      "commits_last_year": 284,
      "latest_release_at": "2026-07-31T03:07:38Z",
      "latest_release_tag": "v0.21.127",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 30,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 0.8
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 37,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "hypha",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "pypi",
          "matches_repo": true,
          "registry_url": "https://pypi.org/project/hypha/",
          "is_deprecated": false,
          "latest_version": "0.21.127",
          "repository_url": "http://github.com/amun-ai/hypha",
          "versions_count": 401,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 5442,
          "first_published_at": "2021-10-16T20:02:42.140881Z",
          "latest_published_at": "2026-07-31T03:07:33.519840Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 14,
      "stars": 24,
      "watchers": 2,
      "fork_history": {
        "days": [
          {
            "date": "2022-07-19",
            "count": 1
          },
          {
            "date": "2022-07-26",
            "count": 1
          },
          {
            "date": "2022-12-01",
            "count": 1
          },
          {
            "date": "2023-06-25",
            "count": 1
          },
          {
            "date": "2023-09-18",
            "count": 1
          },
          {
            "date": "2025-01-21",
            "count": 1
          },
          {
            "date": "2025-10-02",
            "count": 1
          },
          {
            "date": "2025-10-16",
            "count": 1
          },
          {
            "date": "2026-01-14",
            "count": 1
          },
          {
            "date": "2026-01-23",
            "count": 1
          },
          {
            "date": "2026-03-01",
            "count": 1
          },
          {
            "date": "2026-03-12",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 12,
        "total_forks": 14
      },
      "star_history": null,
      "open_issues_and_prs": 20
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "notebooks"
      ],
      "has_llms_txt": true,
      "has_dockerfile": true,
      "has_mcp_signal": true,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 512705,
      "source_files_sampled": 201,
      "oversized_source_files": 25,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 55402
    },
    "dependencies": {
      "manifests": [
        "requirements.txt",
        "requirements_dev.txt",
        "requirements_lint.txt",
        "requirements_pypi.txt",
        "requirements_test.txt",
        "setup.cfg",
        "setup.py"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "black",
            "direct": false,
            "version": "24.10.0",
            "severity": "critical",
            "ecosystem": "pypi",
            "cvss_score": 9.8,
            "advisory_ids": [
              "GHSA-3936-cmfr-pm3m",
              "PYSEC-2026-2120",
              "PYSEC-2026-2121"
            ],
            "fixed_version": "26.3.1",
            "advisory_count": 3,
            "oldest_advisory_days": 141
          },
          {
            "name": "python-jose",
            "direct": false,
            "version": "3.3.0",
            "severity": "critical",
            "ecosystem": "pypi",
            "cvss_score": 9.1,
            "advisory_ids": [
              "GHSA-6c5p-j8vq-pqhj",
              "GHSA-cjwg-qfpm-7377",
              "PYSEC-2024-232",
              "PYSEC-2024-233",
              "PYSEC-2025-185"
            ],
            "fixed_version": "3.4.0",
            "advisory_count": 5,
            "oldest_advisory_days": 826
          },
          {
            "name": "jinja2",
            "direct": false,
            "version": "3.1.4",
            "severity": "high",
            "ecosystem": "pypi",
            "cvss_score": 8.8,
            "advisory_ids": [
              "GHSA-cpwx-vrp4-4pq7",
              "GHSA-gmj6-6f8f-6699",
              "GHSA-q2x7-8rv6-6q7h",
              "PYSEC-2026-1471",
              "PYSEC-2026-1472",
              "PYSEC-2026-1475"
            ],
            "fixed_version": "3.1.6",
            "advisory_count": 6,
            "oldest_advisory_days": 584
          },
          {
            "name": "lxml",
            "direct": false,
            "version": "4.9.3",
            "severity": "high",
            "ecosystem": "pypi",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-vfmq-68hx-4jfw",
              "PYSEC-2026-87"
            ],
            "fixed_version": "6.1.0",
            "advisory_count": 2,
            "oldest_advisory_days": 100
          },
          {
            "name": "mcp",
            "direct": false,
            "version": "1.11.0",
            "severity": "high",
            "ecosystem": "pypi",
            "cvss_score": 7.1,
            "advisory_ids": [
              "GHSA-9h52-p55h-vw2f",
              "GHSA-jpw9-pfvf-9f58",
              "GHSA-vj7q-gjh5-988w",
              "PYSEC-2026-1617",
              "PYSEC-2026-3482",
              "PYSEC-2026-3483"
            ],
            "fixed_version": "1.28.1",
            "advisory_count": 6,
            "oldest_advisory_days": 240
          },
          {
            "name": "msgpack",
            "direct": false,
            "version": "1.0.8",
            "severity": "high",
            "ecosystem": "pypi",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-6v7p-g79w-8964"
            ],
            "fixed_version": "1.2.1",
            "advisory_count": 1,
            "oldest_advisory_days": 41
          },
          {
            "name": "setuptools",
            "direct": false,
            "version": "69.0.3",
            "severity": "high",
            "ecosystem": "pypi",
            "cvss_score": 8.8,
            "advisory_ids": [
              "GHSA-5rjg-fvgr-3xxf",
              "GHSA-cx63-2mw6-8hw5",
              "GHSA-h35f-9h28-mq5c",
              "PYSEC-2025-49",
              "PYSEC-2026-1918",
              "PYSEC-2026-3447"
            ],
            "fixed_version": "83.0.0",
            "advisory_count": 6,
            "oldest_advisory_days": 745
          },
          {
            "name": "wheel",
            "direct": false,
            "version": "0.41.1",
            "severity": "high",
            "ecosystem": "pypi",
            "cvss_score": 7.1,
            "advisory_ids": [
              "GHSA-8rrh-rw8j-w5fx",
              "PYSEC-2026-2047"
            ],
            "fixed_version": "0.46.2",
            "advisory_count": 2,
            "oldest_advisory_days": 189
          },
          {
            "name": "pytest",
            "direct": false,
            "version": "7.4.0",
            "severity": "moderate",
            "ecosystem": "pypi",
            "cvss_score": 6.8,
            "advisory_ids": [
              "GHSA-6w46-j5rx-g56g",
              "PYSEC-2026-1845"
            ],
            "fixed_version": "9.0.3",
            "advisory_count": 2,
            "oldest_advisory_days": 189
          },
          {
            "name": "requests",
            "direct": false,
            "version": "2.31.0",
            "severity": "moderate",
            "ecosystem": "pypi",
            "cvss_score": 5.6,
            "advisory_ids": [
              "GHSA-9hjg-9r4m-mvj7",
              "GHSA-9wx4-h78v-vm56",
              "GHSA-gc5v-m9x4-r6x2",
              "PYSEC-2026-1872",
              "PYSEC-2026-1873",
              "PYSEC-2026-2275"
            ],
            "fixed_version": "2.33.0",
            "advisory_count": 6,
            "oldest_advisory_days": 801
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "high": 6,
          "critical": 2,
          "moderate": 2
        },
        "advisory_count": 39,
        "affected_count": 10,
        "assessed_count": 63,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 54,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "pypi"
      ],
      "dependencies": [],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "a2a-sdk",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "a2a-sdk",
            "direct": false,
            "version": "0.3.0",
            "ecosystem": "pypi"
          },
          {
            "name": "aioboto3",
            "direct": false,
            "version": "13.2.0",
            "ecosystem": "pypi"
          },
          {
            "name": "aiobotocore",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "aiocache",
            "direct": false,
            "version": "0.12.2",
            "ecosystem": "pypi"
          },
          {
            "name": "aiofiles",
            "direct": false,
            "version": "23.2.1",
            "ecosystem": "pypi"
          },
          {
            "name": "aiortc",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "aiosqlite",
            "direct": false,
            "version": "0.20.0",
            "ecosystem": "pypi"
          },
          {
            "name": "alembic",
            "direct": false,
            "version": "1.14.0",
            "ecosystem": "pypi"
          },
          {
            "name": "apscheduler",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "asyncpg",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "azure-identity",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "azure-keyvault-secrets",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "azure-storage-blob",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "backoff",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "base58",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "base58",
            "direct": false,
            "version": "2.1.1",
            "ecosystem": "pypi"
          },
          {
            "name": "black",
            "direct": false,
            "version": "24.10.0",
            "ecosystem": "pypi"
          },
          {
            "name": "boto3",
            "direct": false,
            "version": "1.36.0",
            "ecosystem": "pypi"
          },
          {
            "name": "click",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "conda-pack",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "cryptography",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "diskcache",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "dulwich",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "fakeredis",
            "direct": false,
            "version": "2.24.1",
            "ecosystem": "pypi"
          },
          {
            "name": "fastapi",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "fastapi",
            "direct": false,
            "version": "0.115.2",
            "ecosystem": "pypi"
          },
          {
            "name": "fastapi-sso",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "fastembed",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "fastembed",
            "direct": false,
            "version": "0.4.2",
            "ecosystem": "pypi"
          },
          {
            "name": "fastuuid",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "fastuuid",
            "direct": false,
            "version": "0.14.0",
            "ecosystem": "pypi"
          },
          {
            "name": "flake8",
            "direct": false,
            "version": "7.1.1",
            "ecosystem": "pypi"
          },
          {
            "name": "flake8-docstrings",
            "direct": false,
            "version": "1.7.0",
            "ecosystem": "pypi"
          },
          {
            "name": "friendlywords",
            "direct": false,
            "version": "1.1.3",
            "ecosystem": "pypi"
          },
          {
            "name": "google-cloud-iam",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "google-cloud-kms",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "google-genai",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "greenlet",
            "direct": false,
            "version": "3.1.1",
            "ecosystem": "pypi"
          },
          {
            "name": "gunicorn",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "hrid",
            "direct": false,
            "version": "0.3.0",
            "ecosystem": "pypi"
          },
          {
            "name": "httpx",
            "direct": false,
            "version": "0.28.1",
            "ecosystem": "pypi"
          },
          {
            "name": "hypha-rpc",
            "direct": false,
            "version": "0.21.46",
            "ecosystem": "pypi"
          },
          {
            "name": "ipykernel",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "jinja2",
            "direct": false,
            "version": "3.1.4",
            "ecosystem": "pypi"
          },
          {
            "name": "jsonschema",
            "direct": false,
            "version": "4.24.0",
            "ecosystem": "pypi"
          },
          {
            "name": "jupyter-client",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "kubernetes",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "litellm-enterprise",
            "direct": false,
            "version": "0.1.20",
            "ecosystem": "pypi"
          },
          {
            "name": "litellm-proxy-extras",
            "direct": false,
            "version": "0.2.19",
            "ecosystem": "pypi"
          },
          {
            "name": "lxml",
            "direct": false,
            "version": "4.9.3",
            "ecosystem": "pypi"
          },
          {
            "name": "mcp",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "mcp",
            "direct": false,
            "version": "1.11.0",
            "ecosystem": "pypi"
          },
          {
            "name": "mlflow",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "msgpack",
            "direct": false,
            "version": "1.0.8",
            "ecosystem": "pypi"
          },
          {
            "name": "numcodecs",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "numcodecs",
            "direct": false,
            "version": "0.16.2",
            "ecosystem": "pypi"
          },
          {
            "name": "numpy",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "ollama",
            "direct": false,
            "version": "0.5.1",
            "ecosystem": "pypi"
          },
          {
            "name": "openai",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "orjson",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "playwright",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "playwright",
            "direct": false,
            "version": "1.51.0",
            "ecosystem": "pypi"
          },
          {
            "name": "polars",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "prisma",
            "direct": false,
            "version": "0.11.0",
            "ecosystem": "pypi"
          },
          {
            "name": "prometheus-client",
            "direct": false,
            "version": "0.21.1",
            "ecosystem": "pypi"
          },
          {
            "name": "prompt-toolkit",
            "direct": false,
            "version": "3.0.50",
            "ecosystem": "pypi"
          },
          {
            "name": "psutil",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "psycopg2-binary",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "psycopg2-binary",
            "direct": false,
            "version": "2.9.10",
            "ecosystem": "pypi"
          },
          {
            "name": "ptpython",
            "direct": false,
            "version": "3.0.29",
            "ecosystem": "pypi"
          },
          {
            "name": "ptyprocess",
            "direct": false,
            "version": "0.7.0",
            "ecosystem": "pypi"
          },
          {
            "name": "pydantic",
            "direct": false,
            "version": "2.11.3",
            "ecosystem": "pypi"
          },
          {
            "name": "pyjwt",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pylint",
            "direct": false,
            "version": "3.2.6",
            "ecosystem": "pypi"
          },
          {
            "name": "pymultihash",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pymultihash",
            "direct": false,
            "version": "0.8.2",
            "ecosystem": "pypi"
          },
          {
            "name": "pynacl",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pyotritonclient",
            "direct": false,
            "version": "0.2.6",
            "ecosystem": "pypi"
          },
          {
            "name": "pytest",
            "direct": false,
            "version": "7.4.0",
            "ecosystem": "pypi"
          },
          {
            "name": "pytest-asyncio",
            "direct": false,
            "version": "0.21.1",
            "ecosystem": "pypi"
          },
          {
            "name": "pytest-cov",
            "direct": false,
            "version": "4.1.0",
            "ecosystem": "pypi"
          },
          {
            "name": "pytest-timeout",
            "direct": false,
            "version": "2.3.1",
            "ecosystem": "pypi"
          },
          {
            "name": "python-dotenv",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "python-jose",
            "direct": false,
            "version": "3.3.0",
            "ecosystem": "pypi"
          },
          {
            "name": "python-multipart",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pyyaml",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "redis",
            "direct": false,
            "version": "5.2.0",
            "ecosystem": "pypi"
          },
          {
            "name": "redis",
            "direct": false,
            "version": "6.2.0",
            "ecosystem": "pypi"
          },
          {
            "name": "requests",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "requests",
            "direct": false,
            "version": "2.31.0",
            "ecosystem": "pypi"
          },
          {
            "name": "resend",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "rich",
            "direct": false,
            "version": "13.7.1",
            "ecosystem": "pypi"
          },
          {
            "name": "rq",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "scikit-learn",
            "direct": false,
            "version": "1.7.1",
            "ecosystem": "pypi"
          },
          {
            "name": "semantic-router",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "setuptools",
            "direct": false,
            "version": "69.0.3",
            "ecosystem": "pypi"
          },
          {
            "name": "shortuuid",
            "direct": false,
            "version": "1.0.13",
            "ecosystem": "pypi"
          },
          {
            "name": "simpervisor",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "pypi"
          },
          {
            "name": "sqlalchemy",
            "direct": false,
            "version": "2.0.35",
            "ecosystem": "pypi"
          },
          {
            "name": "sqlmodel",
            "direct": false,
            "version": "0.0.34",
            "ecosystem": "pypi"
          },
          {
            "name": "starlette-compress",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "stream-zip",
            "direct": false,
            "version": "0.0.83",
            "ecosystem": "pypi"
          },
          {
            "name": "tiktoken",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tokenizers",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tox",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "twine",
            "direct": false,
            "version": "4.0.2",
            "ecosystem": "pypi"
          },
          {
            "name": "uuid-utils",
            "direct": false,
            "version": "0.9.0",
            "ecosystem": "pypi"
          },
          {
            "name": "uvicorn",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "uvicorn",
            "direct": false,
            "version": "0.23.2",
            "ecosystem": "pypi"
          },
          {
            "name": "uvloop",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "websocket-client",
            "direct": false,
            "version": "1.6.1",
            "ecosystem": "pypi"
          },
          {
            "name": "websockets",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "websockets",
            "direct": false,
            "version": "15.0.1",
            "ecosystem": "pypi"
          },
          {
            "name": "wheel",
            "direct": false,
            "version": "0.41.1",
            "ecosystem": "pypi"
          },
          {
            "name": "zarr",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "zarr",
            "direct": false,
            "version": "3.1.2",
            "ecosystem": "pypi"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 117,
        "direct_count": 0,
        "indirect_count": 117
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 20,
        "merged_prs": 637,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 30,
        "closed_unmerged_prs": 351
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "oeway",
          "commits": 1387,
          "avatar_url": "https://avatars.githubusercontent.com/u/478667?v=4"
        },
        {
          "type": "User",
          "login": "MartinHjelmare",
          "commits": 43,
          "avatar_url": "https://avatars.githubusercontent.com/u/3181692?v=4"
        },
        {
          "type": "User",
          "login": "aaristov",
          "commits": 5,
          "avatar_url": "https://avatars.githubusercontent.com/u/11408456?v=4"
        },
        {
          "type": "User",
          "login": "ctr26",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/15238739?v=4"
        },
        {
          "type": "User",
          "login": "supermanhuyu",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/24794811?v=4"
        },
        {
          "type": "User",
          "login": "muellerflorian",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/10832779?v=4"
        },
        {
          "type": "User",
          "login": "avivbd",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/20915857?v=4"
        },
        {
          "type": "User",
          "login": "FynnBe",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/15139589?v=4"
        },
        {
          "type": "User",
          "login": "hugokallander",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/63727864?v=4"
        },
        {
          "type": "User",
          "login": "kmdouglass",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/3697676?v=4"
        }
      ],
      "contributors_sampled": 12,
      "top_contributor_share": 0.957
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "draft-release.yml",
        "labeler.yml",
        "publish-container.yml",
        "publish.yml",
        "release.yml",
        "test-helm-chart.yml",
        "test.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        "tox.ini"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": true
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": null,
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-31T02:25:42Z",
      "oldest_open_prs": [
        {
          "number": 994,
          "created_at": "2026-06-26T10:22:18Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 995,
          "created_at": "2026-06-26T10:22:21Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 996,
          "created_at": "2026-06-26T10:22:25Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 997,
          "created_at": "2026-06-26T10:22:28Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 998,
          "created_at": "2026-06-26T10:22:30Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 999,
          "created_at": "2026-06-26T10:22:33Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1000,
          "created_at": "2026-06-26T10:22:36Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1001,
          "created_at": "2026-06-26T10:22:40Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1002,
          "created_at": "2026-06-26T10:22:43Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1003,
          "created_at": "2026-06-26T10:22:46Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1004,
          "created_at": "2026-06-29T10:22:34Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1005,
          "created_at": "2026-06-29T10:22:37Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1006,
          "created_at": "2026-06-29T10:22:41Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1007,
          "created_at": "2026-06-29T10:22:48Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1008,
          "created_at": "2026-06-29T10:22:53Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1009,
          "created_at": "2026-06-29T10:22:55Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1010,
          "created_at": "2026-06-29T10:22:59Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1011,
          "created_at": "2026-06-29T10:23:04Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1012,
          "created_at": "2026-06-29T10:23:10Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 1013,
          "created_at": "2026-06-29T10:23:13Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-31T02:24:00Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/amun-ai/hypha",
    "host": "github.com",
    "name": "hypha",
    "owner": "amun-ai"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "excellent",
      "name": "Overall health",
      "note": "The weighted overall 68 is calibrated to 80 on the published index scale (record calibration 2026-08-02).",
      "notes": [
        {
          "code": "overall_calibration",
          "params": {
            "raw": 68,
            "calibrated": 80,
            "calibration": "2026-08-02"
          }
        }
      ],
      "value": 80,
      "inputs": {
        "security": 46,
        "vitality": 90,
        "community": 45,
        "governance": 62,
        "calibration": "2026-08-02",
        "engineering": 91,
        "ai_readiness": 72,
        "weighted_overall_raw": 68
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 90,
        "weight": 0.21,
        "metrics": [
          {
            "key": "development_activity",
            "band": "excellent",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 83,
            "inputs": {
              "commits_last_year": 284,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 30
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "30/52 weeks with commits",
                "points": 20.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 30
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "284 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 284
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "OpenSSF Scorecard unavailable",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "exceptional",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "releases_count": 100,
              "latest_release_tag": "v0.21.127",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 0.8
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "100 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~0.8 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0.8
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "OpenSSF Scorecard unavailable",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "exceptional",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 4,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 4 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "weak",
        "name": "Community & Adoption",
        "value": 45,
        "weight": 0.17,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 31,
            "inputs": {
              "forks": 14,
              "stars": 24,
              "watchers": 2,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "24 stars",
                "points": 22.1,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 24
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "14 forks",
                "points": 9.3,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 14
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "2 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "readme_badges": null,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "readme_badge_services": [],
              "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
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 62,
            "inputs": {
              "packages": [
                "hypha"
              ],
              "dependents": null,
              "ecosystems": "pypi",
              "total_downloads": null,
              "monthly_downloads": 5442
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "5,442 downloads/month across pypi",
                "points": 49.8,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 5442,
                      "ecosystems": "pypi"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 62,
        "weight": 0.23,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 26,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 12,
              "top_contributor_share": 0.957
            },
            "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 96% of commits",
                "points": 1,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 96
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "12 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 12
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "OpenSSF Scorecard unavailable",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Newcomer PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "newcomer_pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 85,
            "inputs": {
              "merged_prs": 637,
              "open_issues": 0,
              "closed_issues": 30,
              "prs_merged_7d": null,
              "prs_decided_7d": null,
              "prs_merged_30d": null,
              "prs_decided_30d": null,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 351,
              "first_time_authors_30d": null,
              "first_time_prs_merged_30d": null,
              "first_time_prs_decided_30d": null
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 42,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 42
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "637/988 decided PRs merged",
                "points": 19.3,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 637,
                      "decided": 988
                    }
                  }
                ],
                "max_points": 30
              },
              {
                "key": "newcomer_pr_acceptance",
                "name": "Newcomer PR acceptance",
                "detail": "no first-time contributor's PR decided in 30d",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_newcomer_prs",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 13
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "OpenSSF Scorecard unavailable",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 53,
            "inputs": {
              "followers": 4,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "amun-ai",
              "public_repos": 8,
              "account_age_days": 2047
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "4 followers of amun-ai",
                "points": 5,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 4,
                      "login": "amun-ai"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "8 public repos, account ~5 yr old",
                "points": 18.2,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 8
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 5
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "exceptional",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "hypha"
              ],
              "ecosystems": "pypi",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on pypi",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "pypi"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 0 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "401 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 401
                    }
                  }
                ],
                "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": 91,
        "weight": 0.19,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "excellent",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "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": "7 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "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": "tox.ini",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tox.ini"
                    }
                  }
                ],
                "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": "OpenSSF Scorecard unavailable",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": "https://docs.amun.ai",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://docs.amun.ai",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "weak",
        "name": "Security",
        "value": 46,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dependency lockfiles. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dependency_lockfiles"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 33,
            "inputs": {
              "source": "file_signals",
              "lockfiles": [],
              "manifests": [
                "requirements.txt",
                "requirements_dev.txt",
                "requirements_lint.txt",
                "requirements_pypi.txt",
                "requirements_test.txt",
                "setup.cfg",
                "setup.py"
              ],
              "has_codeql_workflow": false,
              "has_security_policy": false,
              "has_dependabot_config": true
            },
            "components": [
              {
                "key": "security_policy_security_md",
                "name": "Security policy (SECURITY.md)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 30
              },
              {
                "key": "dependabot_config",
                "name": "Dependabot config",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "dependency_lockfiles",
                "name": "Dependency lockfiles",
                "detail": "published library — lockfiles are an application concern, not expected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "lockfiles_not_expected",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "codeql_workflow",
                "name": "CodeQL workflow",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "exceptional",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 63 resolved dependencies against OSV; 54 could not be assessed (no resolved version, an unsupported ecosystem, or beyond the reported package list). This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories",
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 63
                }
              },
              {
                "code": "advisories_unassessed",
                "params": {
                  "count": 54
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 39,
              "affected_packages": 10,
              "assessed_packages": 63,
              "unassessed_packages": 54,
              "affected_by_severity": "critical 2, high 6, moderate 2",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "transitive set not separable from development and test dependencies in this scope",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_scope_not_separable",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "exceptional",
            "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": 63,
              "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": "exceptional",
            "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"
              ],
              "commit_weight_rule": {
                "min_commits": 50,
                "min_commit_share": 0.1
              },
              "review_only_matches": 0,
              "below_threshold_exposures": [],
              "assessed_self_published_locations": 14
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 72,
        "weight": 0.04,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "exceptional",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "has_llms_txt": true,
              "legible_history_share": 1,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 55402
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": "llms.txt present",
                "points": 15,
                "status": "met",
                "details": [
                  {
                    "code": "llms_txt_present",
                    "params": {}
                  }
                ],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 64,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": true,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0.96,
              "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": "tox.ini",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tox.ini"
                    }
                  }
                ],
                "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": "Dockerfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "96 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 96,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "dependency automation configured, none observed in the sampled commits",
                "points": 5,
                "status": "partial",
                "details": [
                  {
                    "code": "dependency_bot_config_only",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "OpenSSF Scorecard unavailable",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "weak",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 48,
            "inputs": {
              "primary_language": "Python",
              "largest_source_bytes": 512705,
              "source_files_sampled": 201,
              "oversized_source_files": 25
            },
            "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": "25/201 source files over 60KB",
                "points": 48.2,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 201,
                      "oversized": 25
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "moderate",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "example_dirs": [
                "notebooks"
              ],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "notebooks",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "notebooks"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
      }
    ],
    "classification": {
      "labels": [
        "library"
      ],
      "scores": {
        "library": 6,
        "framework": 2,
        "mcp-server": 3
      },
      "primary": "library",
      "evidence": [
        {
          "tier": "distribution",
          "label": "library",
          "source": "registry:pypi",
          "weight": 6
        },
        {
          "tier": "structure",
          "label": "mcp-server",
          "source": "mcp_signal",
          "weight": 3
        },
        {
          "tier": "description",
          "label": "framework",
          "source": "description:framework",
          "weight": 2
        }
      ],
      "artifacts": [],
      "confidence": "medium",
      "host_extension": false,
      "runs_as_process": false,
      "consumed_by_code": true
    },
    "metrics_version": "2.3.2"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "deps.dev does not index pypi:hypha@0.21.127; advisories assessed against the repository dependency graph instead",
    "OpenSSF Scorecard did not return a usable result (exit code -9); skipping Scorecard checks"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-31T03:10:04.335070Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/a/amun-ai/hypha.svg",
  "full_name": "amun-ai/hypha",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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