Public record
Software health reportschema 0.27.0 · metrics 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 stars⑂ 14 forkssince Oct 2021View on GitHub ↗

amun-ai/hypha holds a health index of 80 out of 100, placing it in the Excellent band. It scores highest on Engineering Quality (91/100) and lowest on Community & Adoption (45/100). It was last updated today. A single contributor accounts for most of its recent work.

80
overall / 100
Excellent

Software health index

Metrics are grouped into weighted categories on one standardized 1–100 scale. Overall starts as their weighted mean, calibrated against the distribution of the public record so bands carry percentile meaning; when public evidence triggers the High-Risk Jurisdiction Policy, the rating is adjusted and receives an At Risk ceiling of 34.

80
Exceptional93-100The record's top tier (≈ top 5%); essentially all checked criteria met
Excellent80-92Strong across the board; minor gaps
Good65-79Healthy; gaps are limited and manageable
Moderate50-64Acceptable with notable gaps; review recommended
Weak35-49Material weaknesses across several areas
At Risk20-34Significant weaknesses; adoption warrants caution
Critical1-19Severe problems (abandoned, single-maintainer, no hygiene)
VitalityCommunity &AdoptionSustainability &GovernanceEngineeringQualitySecurityAI Readiness

Score profile

Each axis is a category. The shape matters more than the average — a healthy subject fills the whole shape, while a spike-and-crater profile means strength in one dimension is masking risk in another.

The weighted overall 68 is calibrated to 80 on the published index scale (record calibration 2026-08-02).

Ownership

Amun AIOrganization
4 followers8 public repossince Dec 2020

This repository is backed by an organization — shared, accountable stewardship that can outlive any single maintainer.

Package ecosystems

RegistryPackageVersionDownloads / moVersionsLast publish
PyPIhypha0.21.1275,4424010 days ago

Metrics by category

Vitality

Is the project alive — is code being written and are releases shipping?

90Excellent · 21% of overall
How it's scored
36/36Push recency — last push 0 days ago
20.8/36Commit cadence — 30/52 weeks with commits
18/18Commit volume — 284 commits in the last year
0/10OpenSSF Scorecard: Maintained — no data
Inputs used
commits_last_year284
human_commit_share1
days_since_last_push0
active_weeks_last_year30

Release discipline

100Exceptional
How it's scored
27/27Ships releases — 100 releases published
36/36Release recency — latest release 0 days ago
27/27Release cadence — a release every ~0.8 days
0/10OpenSSF Scorecard: Signed-Releases — no data
Inputs used
releases_count100
latest_release_tagv0.21.127
releases_from_tagsno
days_since_latest_release0
mean_days_between_releases0.8

Community & Adoption

Does the project have users, downloads, attention, and a welcoming setup for contributors?

45Weak · 17% of overall
How it's scored
22.1/60Stars — 24 stars
9.3/25Forks — 14 forks
0/15Watchers — 2 watchers
Inputs used
forks14
stars24
watchers2
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
How it's scored
22.5/22.5README
22.5/22.5License — recognized license (MIT)
0/18CONTRIBUTING guide
0/13.5Code of conduct
0/7.2Issue template
0/6.3PR template
Inputs used
has_readmeyes
has_licenseyes
readme_badges
has_contributingno
has_issue_templateno
has_code_of_conductno
readme_badge_services
has_pull_request_templateno
How it's scored
49.8/80Monthly downloads — 5,442 downloads/month across pypi
0/20Registry dependents — not reported by this ecosystem
Inputs used
packageshypha
dependents
ecosystemspypi
total_downloads
monthly_downloads5,442
Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.

Sustainability & Governance

Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?

62Moderate · 23% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
1/22.5Commit distribution — top contributor authored 96% of commits
13.5/13.5Contributor breadth — 12 contributors
0/10OpenSSF Scorecard: Contributors — no data
Inputs used
bus_factor1
contributors_sampled12
top_contributor_share0.957
How it's scored
42/42Issue resolution — 100% of issues closed
19.3/30PR acceptance — 637/988 decided PRs merged
0/13Newcomer PR acceptance — no first-time contributor's PR decided in 30d
0/15OpenSSF Scorecard: Code-Review — no data
Inputs used
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
Excluded from scoring (no data or not applicable): newcomer_pr_acceptance. Remaining weights renormalized.
How it's scored
30/30Ownership backing — organization-owned
0/20Verified domain
5/25Owner reach — 4 followers of amun-ai
18.2/25Track record — 8 public repos, account ~5 yr old
Inputs used
followers4
owner_typeOrganization
is_verified
owner_loginamun-ai
public_repos8
account_age_days2,047

Package maintenance

100Exceptional
How it's scored
25/25Published & resolvable — 1 package(s) on pypi
35/35Publish recency — latest publish 0 days ago
20/20Version history — 401 published versions
20/20Not deprecated — active, not deprecated or yanked
Inputs used
packageshypha
ecosystemspypi
any_deprecatedno
min_days_since_publish0

Engineering Quality

Are baseline engineering and documentation practices in place?

91Excellent · 19% of overall
How it's scored
24/24CI workflows — 7 workflow(s)
24/24Tests present
16/16Linter config — tox.ini
9.6/9.6Pre-commit hooks
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — no data
Inputs used
has_ciyes
has_testsyes
has_editorconfigno
has_linter_configyes
has_precommit_configyes

Documentation

90Excellent
How it's scored
30/30README
25/25Documentation directory
15/15Documentation / homepage site — https://docs.amun.ai
10/10Repository description
0/10Topics
10/10Wiki
Inputs used
topics
has_wikiyes
homepagehttps://docs.amun.ai
has_readmeyes
has_docs_diryes
has_descriptionyes

Security

Are visible security and supply-chain practices strong, without unresolved high-risk jurisdiction exposure?

46Weak · 16% of overall
How it's scored
0/30Security policy (SECURITY.md)
25/25Dependabot config
0/25Dependency lockfiles — published library — lockfiles are an application concern, not expected
0/20CodeQL workflow
Inputs used
sourcefile_signals
lockfiles
manifestsrequirements.txt, requirements_dev.txt, requirements_lint.txt, requirements_pypi.txt, requirements_test.txt, setup.cfg, setup.py
has_codeql_workflowno
has_security_policyno
has_dependabot_configyes
Excluded from scoring (no data or not applicable): Dependency lockfiles. Remaining weights renormalized.

Dependency advisories

100Exceptional
How it's scored
35/35Direct dependencies free of known advisories — no direct dependency carries a known advisory
0/25Indirect dependencies free of known advisories — transitive set not separable from development and test dependencies in this scope
0/40No advisories left outstanding — no advisory carries a publication date
Inputs used
sourceosv
advisories39
affected_packages10
assessed_packages63
unassessed_packages54
affected_by_severitycritical 2, high 6, moderate 2
direct_affected_packages0
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.

AI Readiness

How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight (4%): agent tooling is a real maintenance signal, but a repository with none can still reach 100/100.

72Good · 4% of overall
How it's scored
45/45Agent instructions — CLAUDE.md
15/15Machine-readable docs (llms.txt) — llms.txt present
40/40Legible commit history — 100 of 100 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtyes
legible_history_share1
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes55,402
How it's scored
0/18One-command bootstrap
22/22Automated tests
11/11Lint / format config — tox.ini
0/11Static type checking
10/10Reproducible environment — Dockerfile
10/10Demonstrated agent practice — 96 of the last 100 commits agent-authored or agent-credited
5/8Automated maintenance — dependency automation configured, none observed in the sampled commits
0/10OpenSSF Scorecard: Pinned-Dependencies — no data
Inputs used
has_nixno
has_testsyes
lockfiles
has_dockerfileyes
typed_languageno
bootstrap_files
has_devcontainerno
has_linter_configyes
typecheck_configs
agent_commit_share0.96
toolchain_manifests
dependency_bot_commit_share0
How it's scored
0/45Type-checkable code — Python without a type-check config
48.2/55Manageable file sizes — 25/201 source files over 60KB
Inputs used
primary_languagePython
largest_source_bytes512,705
source_files_sampled201
oversized_source_files25
How it's scored
0/40API schema (OpenAPI/GraphQL/proto)
20/20MCP server
40/40Runnable examples — notebooks
Inputs used
example_dirsnotebooks
has_mcp_signalyes
api_schema_files

Key facts

24GitHub stars
12contributors
284commits, last 12 months
0days since last push
100releases
1bus factor
0open issues
PyPIpackage ecosystems

Data collection 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

More detail

Star and fork history 0 ★ / 14 ⇿
0Stars
14Forks
61Releases

When each star and fork was added, collected from GitHub and bucketed by day. Cumulative growth sits directly above the daily additions it is made of, so the two read against each other: steady organic accretion looks nothing like an abrupt, short-lived burst. Where that difference is measurable, it is reported as growth authenticity.

0246810121212022-072024-052026-03
Major 0Minor 0Patch 61

Each point covers 4 days.

All dependencies 117

Full resolved dependency set from the GitHub dependency graph: 0 direct and 117 indirect (transitive) packages. The transitive closure is complete when the repository commits a lockfile.

RegistryPackageVersionRelation
PyPIa2a-sdkindirect
PyPIa2a-sdk0.3.0indirect
PyPIaioboto313.2.0indirect
PyPIaiobotocoreindirect
PyPIaiocache0.12.2indirect
PyPIaiofiles23.2.1indirect
PyPIaiortcindirect
PyPIaiosqlite0.20.0indirect
PyPIalembic1.14.0indirect
PyPIapschedulerindirect
PyPIasyncpgindirect
PyPIazure-identityindirect
PyPIazure-keyvault-secretsindirect
PyPIazure-storage-blobindirect
PyPIbackoffindirect
PyPIbase58indirect
PyPIbase582.1.1indirect
PyPIblack24.10.0indirect
PyPIboto31.36.0indirect
PyPIclickindirect
PyPIconda-packindirect
PyPIcryptographyindirect
PyPIdiskcacheindirect
PyPIdulwichindirect
PyPIfakeredis2.24.1indirect
PyPIfastapiindirect
PyPIfastapi0.115.2indirect
PyPIfastapi-ssoindirect
PyPIfastembedindirect
PyPIfastembed0.4.2indirect
PyPIfastuuidindirect
PyPIfastuuid0.14.0indirect
PyPIflake87.1.1indirect
PyPIflake8-docstrings1.7.0indirect
PyPIfriendlywords1.1.3indirect
PyPIgoogle-cloud-iamindirect
PyPIgoogle-cloud-kmsindirect
PyPIgoogle-genaiindirect
PyPIgreenlet3.1.1indirect
PyPIgunicornindirect
PyPIhrid0.3.0indirect
PyPIhttpx0.28.1indirect
PyPIhypha-rpc0.21.46indirect
PyPIipykernelindirect
PyPIjinja23.1.4indirect
PyPIjsonschema4.24.0indirect
PyPIjupyter-clientindirect
PyPIkubernetesindirect
PyPIlitellm-enterprise0.1.20indirect
PyPIlitellm-proxy-extras0.2.19indirect
PyPIlxml4.9.3indirect
PyPImcpindirect
PyPImcp1.11.0indirect
PyPImlflowindirect
PyPImsgpack1.0.8indirect
PyPInumcodecsindirect
PyPInumcodecs0.16.2indirect
PyPInumpyindirect
PyPIollama0.5.1indirect
PyPIopenaiindirect
PyPIorjsonindirect
PyPIplaywrightindirect
PyPIplaywright1.51.0indirect
PyPIpolarsindirect
PyPIprisma0.11.0indirect
PyPIprometheus-client0.21.1indirect
PyPIprompt-toolkit3.0.50indirect
PyPIpsutilindirect
PyPIpsycopg2-binaryindirect
PyPIpsycopg2-binary2.9.10indirect
PyPIptpython3.0.29indirect
PyPIptyprocess0.7.0indirect
PyPIpydantic2.11.3indirect
PyPIpyjwtindirect
PyPIpylint3.2.6indirect
PyPIpymultihashindirect
PyPIpymultihash0.8.2indirect
PyPIpynaclindirect
PyPIpyotritonclient0.2.6indirect
PyPIpytest7.4.0indirect
PyPIpytest-asyncio0.21.1indirect
PyPIpytest-cov4.1.0indirect
PyPIpytest-timeout2.3.1indirect
PyPIpython-dotenvindirect
PyPIpython-jose3.3.0indirect
PyPIpython-multipartindirect
PyPIpyyamlindirect
PyPIredis5.2.0indirect
PyPIredis6.2.0indirect
PyPIrequestsindirect
PyPIrequests2.31.0indirect
PyPIresendindirect
PyPIrich13.7.1indirect
PyPIrqindirect
PyPIscikit-learn1.7.1indirect
PyPIsemantic-routerindirect
PyPIsetuptools69.0.3indirect
PyPIshortuuid1.0.13indirect
PyPIsimpervisor1.0.0indirect
PyPIsqlalchemy2.0.35indirect
PyPIsqlmodel0.0.34indirect
PyPIstarlette-compressindirect
PyPIstream-zip0.0.83indirect
PyPItiktokenindirect
PyPItokenizersindirect
PyPItoxindirect
PyPItwine4.0.2indirect
PyPIuuid-utils0.9.0indirect
PyPIuvicornindirect
PyPIuvicorn0.23.2indirect
PyPIuvloopindirect
PyPIwebsocket-client1.6.1indirect
PyPIwebsocketsindirect
PyPIwebsockets15.0.1indirect
PyPIwheel0.41.1indirect
PyPIzarrindirect
PyPIzarr3.1.2indirect
Dependency advisories 10

This repository publishes no package the index resolves, so its own dependency graph was assessed — 63 packages, which also include development and test pins that never ship: 10 carry known advisories, of which 0 are direct. 54 could not be assessed — no resolved version, an unsupported ecosystem, or beyond the reported package list.

PackageVersionRelationSeverityAdvisoriesFixed in
black24.10.0indirectcritical326.3.1
python-jose3.3.0indirectcritical53.4.0
jinja23.1.4indirecthigh63.1.6
lxml4.9.3indirecthigh26.1.0
mcp1.11.0indirecthigh61.28.1
msgpack1.0.8indirecthigh11.2.1
setuptools69.0.3indirecthigh683.0.0
wheel0.41.1indirecthigh20.46.2
pytest7.4.0indirectmoderate29.0.3
requests2.31.0indirectmoderate62.33.0

An advisory means the version recorded in the dependency graph falls inside an advisory’s affected range. Reachability is not analysed, and the graph includes development and test pins — a finding may concern tooling rather than shipped software.

Raw JSON report machine-readable
{
  "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"
}

Scores are signals, not warranties. They reflect publicly visible practices on GitHub — not a code audit, and not a security guarantee.

Missing data is excluded and weights renormalized, never scored as zero. Methodology is versioned and open: metrics v2.3.2, schema v0.27.0 — full methodology · metrics wiki.

How one result sits in the wider record: aggregate statisticsPyPI.