Registro público
Informe de salud del softwareesquema 0.27.0 · métricas 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 estrellas⑂ 14 forksdesde oct 2021Ver en GitHub ↗
TipoBibliotecacómo se determina

amun-ai/hypha tiene un índice de salud de 80 sobre 100, lo que lo sitúa en la banda Excelente. Su puntuación más alta es Engineering Quality (91/100) y la más baja, Community & Adoption (45/100). Se actualizó por última vez hoy. Una sola persona concentra la mayor parte del trabajo reciente.

80
global / 100
Excelente

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala estandarizada de 1 a 100. El resultado global parte de su media ponderada, calibrada contra la distribución del registro público para que las bandas tengan significado percentil; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe un límite «En riesgo» de 34.

80
Excepcional93-100El nivel más alto del registro (≈ el 5% superior); cumple prácticamente todos los criterios evaluados
Excelente80-92Sólido en todos los frentes; carencias menores
Bueno65-79Saludable; carencias limitadas y manejables
Moderado50-64Aceptable con carencias notables; se recomienda revisión
Débil35-49Debilidades sustanciales en varias áreas
En riesgo20-34Debilidades significativas; su adopción exige cautela
Crítico1-19Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

Cada eje es una categoría. La forma importa más que la media: un proyecto sano llena toda la figura, mientras que un perfil de picos y cráteres indica que la fortaleza en una dimensión enmascara el riesgo en otra.

El resultado global ponderado 68 se calibra a 80 en la escala publicada del índice (calibración del registro 2026-08-02).

Titularidad

Amun AIOrganización
4 seguidores8 repositorios públicosdesde dic 2020

Este repositorio está respaldado por una organización: una custodia compartida y responsable que puede sobrevivir a cualquier mantenedor individual.

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicación
PyPIhypha0.21.1275442401hace 0 días

Métricas por categoría

Vitalidad

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

90Excelente · 21% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 0 días
20.8/36Cadencia de commits — 30/52 semanas con commits
18/18Volumen de commits — 284 commits en el último año
0/10OpenSSF Scorecard: Maintained — sin datos
Datos de entrada utilizados
commits_last_year284
human_commit_share1
days_since_last_push0
active_weeks_last_year30
Cómo se puntúa
27/27Publica versiones — 100 versiones publicadas
36/36Recencia de las versiones — última versión hace 0 días
27/27Cadencia de publicación — una versión cada ~0,8 días
0/10OpenSSF Scorecard: Signed-Releases — sin datos
Datos de entrada utilizados
releases_count100
latest_release_tagv0.21.127
releases_from_tagsno
days_since_latest_release0
mean_days_between_releases0,8

Comunidad y Adopción

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

45Débil · 17% del índice global
Cómo se puntúa
22.1/60Estrellas — 24 estrellas
9.3/25Forks — 14 forks
0/15Observadores — 2 observadores
Datos de entrada utilizados
forks14
stars24
watchers2
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
0/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
readme_badges
has_contributingno
has_issue_templateno
has_code_of_conductno
readme_badge_services
has_pull_request_templateno
Cómo se puntúa
49.8/80Descargas mensuales — 5442 descargas/mes en pypi
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packageshypha
dependents
ecosystemspypi
total_downloads
monthly_downloads5442
Excluidos de la puntuación (sin datos o no aplicable): Dependientes en el registro. Los pesos restantes se han renormalizado.

Sostenibilidad y Gobernanza

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

62Moderado · 23% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
1/22.5Distribución de commits — el principal contribuyente firma el 96% de los commits
13.5/13.5Amplitud de contribuyentes — 12 contribuyentes
0/10OpenSSF Scorecard: Contributors — sin datos
Datos de entrada utilizados
bus_factor1
contributors_sampled12
top_contributor_share0,957
Cómo se puntúa
42/42Resolución de issues — 100% de issues cerradas
19.3/30Aceptación de PR — 637/988 PR decididos fusionados
0/13Newcomer PR acceptance — ningún PR de un contribuyente primerizo decidido en 30 d
0/15OpenSSF Scorecard: Code-Review — sin datos
Datos de entrada utilizados
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
Excluidos de la puntuación (sin datos o no aplicable): newcomer_pr_acceptance. Los pesos restantes se han renormalizado.
Cómo se puntúa
30/30Respaldo de la propiedad — propiedad de una organización
0/20Dominio verificado
5/25Alcance del propietario — 4 seguidores de amun-ai
18.2/25Trayectoria — 8 repos públicos, cuenta de ~5 años
Datos de entrada utilizados
followers4
owner_typeOrganization
is_verified
owner_loginamun-ai
public_repos8
account_age_days2047
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en pypi
35/35Recencia de publicación — última publicación hace 0 días
20/20Historial de versiones — 401 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packageshypha
ecosystemspypi
any_deprecatedno
min_days_since_publish0

Calidad de Ingeniería

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

91Excelente · 19% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 7 flujo(s) de trabajo
24/24Pruebas presentes
16/16Configuración de linter — tox.ini
9.6/9.6Hooks de pre-commit
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — sin datos
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_config
has_precommit_config

Documentación

90Excelente
Cómo se puntúa
30/30README
25/25Directorio de documentación
15/15Sitio de documentación / página del proyecto — https://docs.amun.ai
10/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepagehttps://docs.amun.ai
has_readme
has_docs_dir
has_description

Seguridad

¿Son sólidas las prácticas visibles de seguridad y de cadena de suministro, sin exposición jurisdiccional de alto riesgo sin resolver?

46Débil · 16% del índice global
Cómo se puntúa
0/30Política de seguridad (SECURITY.md)
25/25Configuración de Dependabot
0/25Lockfiles de dependencias — biblioteca publicada — los lockfiles son cosa de las aplicaciones, no se esperan aquí
0/20Flujo de trabajo de CodeQL
Datos de entrada utilizados
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_config
Excluidos de la puntuación (sin datos o no aplicable): Lockfiles de dependencias. Los pesos restantes se han renormalizado.
Cómo se puntúa
35/35Dependencias directas libres de avisos conocidos — ninguna dependencia directa tiene un aviso conocido
0/25Dependencias indirectas libres de avisos conocidos — el conjunto transitivo no es separable de las dependencias de desarrollo y prueba en este alcance
0/40Sin avisos pendientes — ningún aviso tiene fecha de publicación
Datos de entrada utilizados
sourceosv
advisories39
affected_packages10
assessed_packages63
unassessed_packages54
affected_by_severitycritical 2, high 6, moderate 2
direct_affected_packages0
Excluidos de la puntuación (sin datos o no aplicable): Dependencias indirectas libres de avisos conocidos, Sin avisos pendientes. Los pesos restantes se han renormalizado. Se cotejaron 63 dependencias resueltas con OSV. 54 no pudieron evaluarse: sin versión resuelta, ecosistema no admitido o fuera de la lista de paquetes informada. Este repositorio no publica ningún paquete que el índice resuelva, por lo que se evaluó en su lugar el grafo de dependencias del repositorio. Ese grafo mezcla fijaciones de desarrollo y prueba con las dependencias distribuidas, de modo que solo se puntúan las dependencias declaradas en tiempo de ejecución; los hallazgos transitivos se informan como contexto y quedan excluidos de la puntuación. No se analiza la alcanzabilidad.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Tiene un peso deliberadamente pequeño (4%): las herramientas para agentes son una señal real de mantenimiento, pero un repositorio sin ninguna puede alcanzar igualmente 100/100.

72Bueno · 4% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — CLAUDE.md
15/15Documentación legible por máquinas (llms.txt) — llms.txt presente
40/40Historial de commits legible — 100 de 100 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txt
legible_history_share1
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes55.402
Cómo se puntúa
0/18Arranque con un solo comando
22/22Pruebas automatizadas
11/11Configuración de lint / formato — tox.ini
0/11Verificación estática de tipos
10/10Entorno reproducible — Dockerfile
10/10Práctica demostrada con agentes — 96 de los últimos 100 commits con autoría o crédito de agente
5/8Mantenimiento automatizado — automatización de dependencias configurada, no observada en los commits muestreados
0/10OpenSSF Scorecard: Pinned-Dependencies — sin datos
Datos de entrada utilizados
has_nixno
has_tests
lockfiles
has_dockerfile
typed_languageno
bootstrap_files
has_devcontainerno
has_linter_config
typecheck_configs
agent_commit_share0,96
toolchain_manifests
dependency_bot_commit_share0
Cómo se puntúa
0/45Código verificable por tipos — Python sin configuración de verificación de tipos
48.2/55Tamaños de archivo manejables — 25/201 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languagePython
largest_source_bytes512.705
source_files_sampled201
oversized_source_files25
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
20/20Servidor MCP
40/40Ejemplos ejecutables — notebooks
Datos de entrada utilizados
example_dirsnotebooks
has_mcp_signal
api_schema_files

Datos clave

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

Advertencias de recopilación de datos

  • 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

Más detalle

Historial de estrellas y forks 0 ★ / 14 ⇿
0Estrellas
14Forks
61Versiones

Cuándo se añadió cada estrella y fork, recopilado de GitHub y agrupado por día. El crecimiento acumulado se sitúa justo encima de las adiciones diarias que lo componen, de modo que ambos se leen en conjunto: la acumulación orgánica sostenida no se parece en nada a un pico abrupto y efímero. Cuando esa diferencia es medible, se informa como autenticidad del crecimiento.

0246810121212022-072024-052026-03
Mayor 0Menor 0Parche 61

Cada punto abarca 4 días.

Todas las dependencias 117

Conjunto completo de dependencias resueltas según el grafo de dependencias de GitHub: 0 paquetes directos y 117 indirectos (transitivos). El cierre transitivo es completo cuando el repositorio incluye un lockfile.

RegistroPaqueteVersiónRelación
PyPIa2a-sdkindirecta
PyPIa2a-sdk0.3.0indirecta
PyPIaioboto313.2.0indirecta
PyPIaiobotocoreindirecta
PyPIaiocache0.12.2indirecta
PyPIaiofiles23.2.1indirecta
PyPIaiortcindirecta
PyPIaiosqlite0.20.0indirecta
PyPIalembic1.14.0indirecta
PyPIapschedulerindirecta
PyPIasyncpgindirecta
PyPIazure-identityindirecta
PyPIazure-keyvault-secretsindirecta
PyPIazure-storage-blobindirecta
PyPIbackoffindirecta
PyPIbase58indirecta
PyPIbase582.1.1indirecta
PyPIblack24.10.0indirecta
PyPIboto31.36.0indirecta
PyPIclickindirecta
PyPIconda-packindirecta
PyPIcryptographyindirecta
PyPIdiskcacheindirecta
PyPIdulwichindirecta
PyPIfakeredis2.24.1indirecta
PyPIfastapiindirecta
PyPIfastapi0.115.2indirecta
PyPIfastapi-ssoindirecta
PyPIfastembedindirecta
PyPIfastembed0.4.2indirecta
PyPIfastuuidindirecta
PyPIfastuuid0.14.0indirecta
PyPIflake87.1.1indirecta
PyPIflake8-docstrings1.7.0indirecta
PyPIfriendlywords1.1.3indirecta
PyPIgoogle-cloud-iamindirecta
PyPIgoogle-cloud-kmsindirecta
PyPIgoogle-genaiindirecta
PyPIgreenlet3.1.1indirecta
PyPIgunicornindirecta
PyPIhrid0.3.0indirecta
PyPIhttpx0.28.1indirecta
PyPIhypha-rpc0.21.46indirecta
PyPIipykernelindirecta
PyPIjinja23.1.4indirecta
PyPIjsonschema4.24.0indirecta
PyPIjupyter-clientindirecta
PyPIkubernetesindirecta
PyPIlitellm-enterprise0.1.20indirecta
PyPIlitellm-proxy-extras0.2.19indirecta
PyPIlxml4.9.3indirecta
PyPImcpindirecta
PyPImcp1.11.0indirecta
PyPImlflowindirecta
PyPImsgpack1.0.8indirecta
PyPInumcodecsindirecta
PyPInumcodecs0.16.2indirecta
PyPInumpyindirecta
PyPIollama0.5.1indirecta
PyPIopenaiindirecta
PyPIorjsonindirecta
PyPIplaywrightindirecta
PyPIplaywright1.51.0indirecta
PyPIpolarsindirecta
PyPIprisma0.11.0indirecta
PyPIprometheus-client0.21.1indirecta
PyPIprompt-toolkit3.0.50indirecta
PyPIpsutilindirecta
PyPIpsycopg2-binaryindirecta
PyPIpsycopg2-binary2.9.10indirecta
PyPIptpython3.0.29indirecta
PyPIptyprocess0.7.0indirecta
PyPIpydantic2.11.3indirecta
PyPIpyjwtindirecta
PyPIpylint3.2.6indirecta
PyPIpymultihashindirecta
PyPIpymultihash0.8.2indirecta
PyPIpynaclindirecta
PyPIpyotritonclient0.2.6indirecta
PyPIpytest7.4.0indirecta
PyPIpytest-asyncio0.21.1indirecta
PyPIpytest-cov4.1.0indirecta
PyPIpytest-timeout2.3.1indirecta
PyPIpython-dotenvindirecta
PyPIpython-jose3.3.0indirecta
PyPIpython-multipartindirecta
PyPIpyyamlindirecta
PyPIredis5.2.0indirecta
PyPIredis6.2.0indirecta
PyPIrequestsindirecta
PyPIrequests2.31.0indirecta
PyPIresendindirecta
PyPIrich13.7.1indirecta
PyPIrqindirecta
PyPIscikit-learn1.7.1indirecta
PyPIsemantic-routerindirecta
PyPIsetuptools69.0.3indirecta
PyPIshortuuid1.0.13indirecta
PyPIsimpervisor1.0.0indirecta
PyPIsqlalchemy2.0.35indirecta
PyPIsqlmodel0.0.34indirecta
PyPIstarlette-compressindirecta
PyPIstream-zip0.0.83indirecta
PyPItiktokenindirecta
PyPItokenizersindirecta
PyPItoxindirecta
PyPItwine4.0.2indirecta
PyPIuuid-utils0.9.0indirecta
PyPIuvicornindirecta
PyPIuvicorn0.23.2indirecta
PyPIuvloopindirecta
PyPIwebsocket-client1.6.1indirecta
PyPIwebsocketsindirecta
PyPIwebsockets15.0.1indirecta
PyPIwheel0.41.1indirecta
PyPIzarrindirecta
PyPIzarr3.1.2indirecta
Avisos de dependencias 10

Este repositorio no publica ningún paquete que el índice resuelva, así que se evaluó su propio grafo de dependencias — 63 paquetes, que incluyen también fijaciones de desarrollo y prueba que nunca se distribuyen: 10 tienen avisos conocidos, de los cuales 0 son directas. 54 no pudieron evaluarse: sin versión resuelta, ecosistema no admitido, o fuera de la lista de paquetes informada.

PaqueteVersiónRelaciónGravedadAvisosCorregido en
black24.10.0indirectacrítica326.3.1
python-jose3.3.0indirectacrítica53.4.0
jinja23.1.4indirectaalta63.1.6
lxml4.9.3indirectaalta26.1.0
mcp1.11.0indirectaalta61.28.1
msgpack1.0.8indirectaalta11.2.1
setuptools69.0.3indirectaalta683.0.0
wheel0.41.1indirectaalta20.46.2
pytest7.4.0indirectamoderada29.0.3
requests2.31.0indirectamoderada62.33.0

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

Informe JSON sin procesar legible por máquina
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 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"
}

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

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

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