Registro público
Informe de salud del softwareesquema 0.23.0 · métricas 1.13.0 · 2026-07-21 21:26 UTC

duyet / agentstate

TypeScriptMIT★ 2 estrellas⑂ 1 forkdesde mar 2026Ver en GitHub ↗

duyet/agentstate tiene un índice de salud de 66 sobre 100, lo que lo sitúa en la banda Moderado. Su puntuación más alta es Engineering Quality (82/100) y la más baja, Community & Adoption (41/100). Se actualizó por última vez hace 4 días. Una sola persona concentra la mayor parte del trabajo reciente.

66
global / 100
Moderado

Índice de salud del software

Las métricas se agrupan en categorías ponderadas sobre una escala de 1 a 100. El resultado global parte de su media; cuando la evidencia pública activa la Política de Jurisdicciones de Alto Riesgo, la calificación se ajusta y recibe el límite 49 (En riesgo). Preparación para IA queda fuera.

66
Excelente85-100Ejemplar; cumple prácticamente todos los criterios evaluados
Bueno70-84Saludable; carencias menores
Moderado50-69Aceptable con carencias notables; se recomienda revisión
En riesgo30-49Debilidades significativas; su adopción exige cautela
Crítico1-29Problemas graves (proyecto abandonado, un solo mantenedor, sin higiene)
VitalidadComunidad yAdopciónSostenibilidady GobernanzaCalidad deIngenieríaSeguridadPreparaciónpara IA

Perfil de puntuación

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

Titularidad

duyetCuenta personal
814 seguidores544 repositorios públicosdesde jul 2013

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

Ecosistemas de paquetes

RegistroPaqueteVersiónDescargas / mesVersionesÚltima publicaciónEtiquetas
npm@agentstate/sdk0.1.480525hace 4 díasai-agentsagent-memoryconversation-historylanggraphvercel-ai-sdkmcpagent-statecloudflare-workers
PyPIagentstateapunta a otro repositorio; no se puntúa1.0.2-3hace 333 díasaiagentsstatemanagementfirebasepersistentstoragereal-time

Métricas por categoría

Vitalidad

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

79Bueno · 22% del índice global
Cómo se puntúa
36/36Recencia de push — último push hace 4 días
8.3/36Cadencia de commits — 12/52 semanas con commits
18/18Volumen de commits — 452 commits en el último año
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
Datos de entrada utilizados
commits_last_year452
human_commit_share0,92
days_since_last_push4
active_weeks_last_year12
Cómo se puntúa
27/27Publica versiones — 4 versiones publicadas
36/36Recencia de las versiones — última versión hace 30 días
27/27Cadencia de publicación — una versión cada ~2,3 días
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Datos de entrada utilizados
releases_count4
latest_release_tagv0.1.4
releases_from_tagsno
days_since_latest_release30
mean_days_between_releases2,3

Comunidad y Adopción

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

41En riesgo · 18% del índice global
Cómo se puntúa
0/60Estrellas — 2 estrellas
0/25Forks — 1 forks
0/15Observadores — 0 observadores
Datos de entrada utilizados
forks1
stars2
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonbelow_threshold
Cómo se puntúa
22.5/22.5README
22.5/22.5Licencia — licencia reconocida (MIT)
18/18Guía CONTRIBUTING
0/13.5Código de conducta
0/7.2Plantilla de issues
0/6.3Plantilla de PR
Datos de entrada utilizados
has_readme
has_license
has_contributing
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno
Cómo se puntúa
52.1/80Descargas mensuales — 8052 descargas/mes en npm
0/20Dependientes en el registro — no lo informa este ecosistema
Datos de entrada utilizados
packages@agentstate/sdk
dependents
ecosystemsnpm
total_downloads
monthly_downloads8052
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?

65Moderado · 24% del índice global
Cómo se puntúa
9/54Factor bus — la mitad de los commits recae en 1 contribuyente(s)
9/22.5Distribución de commits — el principal contribuyente firma el 60% de los commits
4.1/13.5Amplitud de contribuyentes — 3 contribuyentes
10/10OpenSSF Scorecard: Contributors — project has 5 contributing companies or organizations
Datos de entrada utilizados
bus_factor1
contributors_sampled3
top_contributor_share0,6
Cómo se puntúa
36.3/46.8Resolución de issues — 78% de issues cerradas
35.8/38.3Aceptación de PR — 259/277 PR decididos fusionados
0/15OpenSSF Scorecard: Code-Review — Found 2/27 approved changesets -- score normalized to 0
Datos de entrada utilizados
merged_prs259
open_issues25
closed_issues87
issue_closed_ratio0,777
closed_unmerged_prs18
Cómo se puntúa
10/30Respaldo de la propiedad — cuenta personal (usuario)
0/20Dominio verificado — no aplicable a cuentas de usuario
20.9/25Alcance del propietario — 814 seguidores de duyet
25/25Trayectoria — 544 repos públicos, cuenta de ~13 años
Datos de entrada utilizados
followers814
owner_typeUser
is_verified
owner_loginduyet
public_repos544
account_age_days4754
Excluidos de la puntuación (sin datos o no aplicable): Dominio verificado. Los pesos restantes se han renormalizado.
Cómo se puntúa
25/25Publicado y resoluble — 1 paquete(s) en npm
35/35Recencia de publicación — última publicación hace 4 días
20/20Historial de versiones — 5 versiones en el registro
20/20No obsoleto — activo, ni obsoleto ni retirado
Datos de entrada utilizados
packages@agentstate/sdk
ecosystemsnpm
any_deprecatedno
min_days_since_publish4

Calidad de Ingeniería

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

82Bueno · 20% del índice global
Cómo se puntúa
24/24Flujos de trabajo de CI — 4 flujo(s) de trabajo
24/24Pruebas presentes
16/16Configuración de linter — biome.json
0/9.6Hooks de pre-commit
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 28 out of 28 merged PRs checked by a CI test -- score normalized to 10
Datos de entrada utilizados
has_ci
has_tests
has_editorconfigno
has_linter_config
has_precommit_configno
Cómo se puntúa
30/30README
25/25Directorio de documentación
15/15Sitio de documentación / página del proyecto — https://agentstate.app
0/10Descripción del repositorio
0/10Topics
10/10Wiki
Datos de entrada utilizados
topics
has_wiki
homepagehttps://agentstate.app
has_readme
has_docs_dir
has_descriptionno

Seguridad

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

58Moderado · 16% del índice global
Cómo se puntúa
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.5/2.5CI-Tests — 28 out of 28 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 2/27 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 5 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Licencia — license file detected
7.5/7.5Maintained — 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 28 existing vulnerabilities detected
Datos de entrada utilizados
sourceopenssf_scorecard
checks_evaluated18
scorecard_versionv5.5.0
checks_inconclusive0
scorecard_aggregate4,8
Cómo se puntúa
35/35Dependencias directas libres de avisos conocidos — ninguna dependencia directa tiene un aviso conocido
25/25Dependencias indirectas libres de avisos conocidos — ninguna dependencia indirecta tiene un aviso conocido
0/40Sin avisos pendientes — ningún aviso tiene fecha de publicación
Datos de entrada utilizados
sourceosv
advisories0
affected_packages0
assessed_packages5
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
Excluidos de la puntuación (sin datos o no aplicable): Sin avisos pendientes. Los pesos restantes se han renormalizado. Se cotejó el cierre de dependencias en tiempo de ejecución de pypi:agentstate@1.0.2 —lo que arrastra la instalación del paquete publicado—: 5 paquetes. No se analiza la alcanzabilidad.

Preparación para IA

¿Hasta qué punto está el repositorio preparado para desarrollarse y mantenerse con agentes de codificación de IA? Es una insignia independiente y experimental — peso 0,0, de modo que se presenta por separado y no afecta a la puntuación de salud global.

76Bueno · 0% del índice global
Cómo se puntúa
45/45Instrucciones para agentes — AGENTS.md, CLAUDE.md, packages/api/src/content/agents.md, packages/dashboard/public/agents.md
15/15Documentación legible por máquinas (llms.txt) — llms.txt presente
40/40Historial de commits legible — 91 de 92 commits humanos declaran su intención (asunto estructurado o cuerpo explicativo)
Datos de entrada utilizados
has_llms_txt
legible_history_share0,989
agent_instruction_filesAGENTS.md, CLAUDE.md, packages/api/src/content/agents.md, packages/dashboard/public/agents.md
agent_instruction_max_bytes19.307
Cómo se puntúa
0/18Arranque con un solo comando
22/22Pruebas automatizadas
11/11Configuración de lint / formato — biome.json
11/11Verificación estática de tipos — examples/fleet-leases/tsconfig.json, packages/api/tsconfig.json, packages/dashboard/tsconfig.json, packages/mcp/tsconfig.json, packages/sdk/tsconfig.json, packages/shared/tsconfig.json, tsconfig.json
0/10Entorno reproducible
2/10Práctica demostrada con agentes — 1 de los últimos 100 commits con autoría o crédito de agente
8/8Mantenimiento automatizado — 7 de los últimos 100 commits son actualizaciones automáticas de dependencias
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Datos de entrada utilizados
has_nixno
has_tests
lockfiles
has_dockerfileno
typed_language
bootstrap_files
has_devcontainerno
has_linter_config
typecheck_configsexamples/fleet-leases/tsconfig.json, packages/api/tsconfig.json, packages/dashboard/tsconfig.json, packages/mcp/tsconfig.json, packages/sdk/tsconfig.json, packages/shared/tsconfig.json, tsconfig.json
agent_commit_share0,01
toolchain_manifests
dependency_bot_commit_share0,07
Cómo se puntúa
45/45Código verificable por tipos — TypeScript (tipado estático)
54.8/55Tamaños de archivo manejables — 1/321 archivos fuente de más de 60 KB
Datos de entrada utilizados
primary_languageTypeScript
largest_source_bytes65.759
source_files_sampled321
oversized_source_files1
Cómo se puntúa
0/40Esquema de API (OpenAPI/GraphQL/proto)
20/20Servidor MCP
40/40Ejemplos ejecutables — examples, recipes
Datos de entrada utilizados
example_dirsexamples, recipes
has_mcp_signal
api_schema_files

Datos clave

2estrellas de GitHub
3contribuidores
452commits en los últimos 12 meses
4días desde el último push
4versiones publicadas
1factor bus
25issues abiertas
npmecosistemas de paquetes

Advertencias de recopilación de datos

  • Could not fetch npm package '@agentstate/mcp' from its registry
  • pypi package 'agentstate' points at a different repository (https://github.com/ayushmi/agentstate); excluded from ecosystem scoring

Más detalle

Historial de estrellas y forks 2 ★ / 1 ⇿
2Estrellas
1Forks
2Versiones

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.

0011222112026-032026-052026-06
Mayor 0Menor 0Parche 2
OpenSSF Scorecard 4.8 / 10
4.8agregado

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
10CI-Tests28 out of 28 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 2/27 approved changesets -- score normalized to 0
10Contributorsproject has 5 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
10Security-Policysecurity policy file detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities28 existing vulnerabilities detected
Dependencias directas 27
RegistroPaqueteRestricción de versiónManifiesto
npm@clerk/backend^3.7.0packages/api/package.json
npmdrizzle-orm^0.45.2packages/api/package.json
npmhono^4.12.21packages/api/package.json
npmnanoid^5.1.0packages/api/package.json
npmzod^3.24.0packages/api/package.json
npmzod-to-json-schema^3.25.2packages/api/package.json
npm@agentstate/sharedworkspace:*packages/dashboard/package.json
npm@clerk/react^6.6.6packages/dashboard/package.json
npm@fontsource-variable/hanken-grotesk^5.2.8packages/dashboard/package.json
npm@fontsource-variable/jetbrains-mono^5.2.6packages/dashboard/package.json
npm@fontsource-variable/space-grotesk^5.2.8packages/dashboard/package.json
npm@phosphor-icons/react^2.1.10packages/dashboard/package.json
npmclsx^2.1.1packages/dashboard/package.json
npmecharts^6.1.0packages/dashboard/package.json
npmmotion^12.38.0packages/dashboard/package.json
npmnext-themes^0.4.6packages/dashboard/package.json
npmreact19.2.7packages/dashboard/package.json
npmreact-dom19.2.7packages/dashboard/package.json
npmreact-markdown^10.1.0packages/dashboard/package.json
npmremark-gfm^4.0.1packages/dashboard/package.json
npmsonner^2.0.7packages/dashboard/package.json
npmtailwind-merge^3.5.0packages/dashboard/package.json
npmtw-animate-css^1.4.0packages/dashboard/package.json
npmzod^4.4.3packages/dashboard/package.json
npm@modelcontextprotocol/sdk^1.29.0packages/mcp/package.json
npmzod^3.25packages/mcp/package.json
PyPIhttpx>=0.28.1packages/python-sdk/pyproject.toml
Todas las dependencias 57

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

RegistroPaqueteVersiónRelación
npm@clerk/backend^3.7.0directa
npm@clerk/react^6.6.6directa
npm@fontsource-variable/hanken-grotesk^5.2.8directa
npm@fontsource-variable/jetbrains-mono^5.2.6directa
npm@fontsource-variable/space-grotesk^5.2.8directa
npm@modelcontextprotocol/sdk^1.29.0directa
npm@phosphor-icons/react^2.1.10directa
npmclsx^2.1.1directa
npmdrizzle-orm^0.45.2directa
npmecharts^6.1.0directa
npmhono^4.12.21directa
npmmotion^12.38.0directa
npmnanoid^5.1.0directa
npmnext-themes^0.4.6directa
npmreact19.2.7directa
npmreact-dom19.2.7directa
npmreact-markdown^10.1.0directa
npmremark-gfm^4.0.1directa
npmsonner^2.0.7directa
npmtailwind-merge^3.5.0directa
npmtw-animate-css^1.4.0directa
npmzod^3.24.0directa
npmzod^3.25directa
npmzod^4.4.3directa
npmzod-to-json-schema^3.25.2directa
PyPIhttpxdirecta
npm@astrojs/check^0.9.9indirecta
npm@astrojs/react^6.0.0indirecta
npm@cloudflare/vitest-pool-workers^0.18.0indirecta
npm@cloudflare/workers-types^5.0.0indirecta
npm@langchain/core^1.1.49indirecta
npm@langchain/langgraph-checkpoint^1.1.1indirecta
npm@resvg/resvg-js^2.6.2indirecta
npm@rollup/rollup-linux-x64-gnu^4.60.0indirecta
npm@tailwindcss/vite^4.3.0indirecta
npm@types/node^26.0.0indirecta
npm@types/react^19indirecta
npm@types/react-dom^19indirecta
npmastro^7.0.0indirecta
npmdrizzle-kit^0.31.10indirecta
npmesbuild0.28.1indirecta
npmshadcn^4.10.0indirecta
npmtailwindcss^4indirecta
npmtsup^8.5.1indirecta
npmtypescript^5indirecta
npmtypescript^5.7.0indirecta
npmtypescript^5.9.3indirecta
npmtypescript^6.0.3indirecta
npmvitest^4.1.6indirecta
npmvitest^4.1.9indirecta
npmwrangler^4.93.0indirecta
PyPIlanggraphindirecta
PyPIlanggraph-checkpointindirecta
PyPIpytestindirecta
PyPIpytest-asyncioindirecta
PyPIrespxindirecta
PyPIsetuptoolsindirecta
Avisos de dependencias 0

Instalar pypi:agentstate@1.0.2 arrastra 5 paquetes, directos y transitivos: 0 tienen avisos conocidos, de los cuales 0 son dependencias directas.

Ningún aviso conocido afecta a las dependencias evaluadas.

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": 2877,
      "has_wiki": true,
      "homepage": "https://agentstate.app",
      "languages": {
        "CSS": 13378,
        "Astro": 92569,
        "Shell": 3822,
        "Python": 91557,
        "JavaScript": 34735,
        "TypeScript": 1428819
      },
      "pushed_at": "2026-07-17T16:17:36Z",
      "created_at": "2026-03-15T13:07:17Z",
      "owner_type": "User",
      "updated_at": "2026-07-17T16:17:47Z",
      "description": null,
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript"
      ]
    },
    "owner": {
      "blog": "https://duyet.net",
      "name": "duyet",
      "type": "User",
      "login": "duyet",
      "company": null,
      "location": "Earth",
      "followers": 814,
      "avatar_url": "https://avatars.githubusercontent.com/u/5009534?v=4",
      "created_at": "2013-07-15T01:54:31Z",
      "is_verified": null,
      "public_repos": 544,
      "account_age_days": 4754
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.1.4",
          "kind": "patch",
          "published_at": "2026-06-21T04:16:59Z"
        },
        {
          "tag": "v0.1.3",
          "kind": "patch",
          "published_at": "2026-06-17T07:25:29Z"
        },
        {
          "tag": "v0.1.2",
          "kind": "patch",
          "published_at": "2026-06-14T06:17:32Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-06-14T06:08:09Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "9a12ed2e8c11f61bc1e42471c4b1c60b5182cb34",
          "body": "… org (#391)\n\n* fix(dashboard): render code-tabs lines as blocks + auto-activate sole org\n\nTwo landing/dashboard fixes:\n\n- code-tabs: each highlighted code line was an inline <span> with no newline\n  between siblings, so inside <pre> the whole snippet collapsed onto one\n  horizontal row. Render each\n[…]\n setActive that clears the guard and skips the reload on failure.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(dashboard): render code-tabs lines as blocks + auto-activate sole…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T16:17:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5ff291a5fed3a3e90c213d0f7cae74f2bc783148",
          "body": "* feat(dashboard): show and switch the active org in the sidebar\n\nThe sidebar had no active-org indicator and no switcher — the only org\nsurface was a settings link. But the org id is load-bearing for every\nproject-scoped read, so a mismatch presented as an empty account with no\nway to see or correc\n[…]\neaving the mobile label unassociated. Derive the id with useId().\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix: make the active org visible and org orphaning observable (#390)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T13:17:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "935527c8a48d2dea696d9404a10d0af70dc391f3",
          "body": "…nt (#386)\n\nAdd .omo/ and .commandcode/ (local Ralph loop / Command Code scratch\nstate) to .gitignore, and let biome reflow a long import line in\ncreate-org-content.tsx.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "chore: gitignore local agent-tool state dirs, format create-org-conte…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T07:53:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "817467e461fd36fdb591972cbdaeb2b76fb3e477",
          "body": "Plan 006. The Idempotency-Key flow on state PUT/DELETE was read-then-\nmutate-then-store: two concurrent requests with the same key could both\nmiss the initial read, both run the mutation (each appending a\nstate_events row), and then silently lose the second idempotency record\nto INSERT OR IGNORE. Id\n[…]\n isn't stuck behind a dead claim.\n\nRoute handlers wrap the mutation in try/finally so any failure path\n(service error or thrown exception) releases the claim.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): claim idempotency keys before state mutations (#385)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T07:51:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7bb864036af0bd4eccad4638c289f675c15e380c",
          "body": "validation.ts and webhook.ts each declared their own copy of the\nsupported webhook event list; adding a new event to only one would\nsilently split validation from delivery. webhook.ts now imports\nWEBHOOK_EVENT_TYPES from validation.ts instead of redeclaring it.\n\nFixes #378\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): dedupe supported webhook event types into one constant (#384)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T06:35:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bc0b32a4da14ca5bb1dec0bad4baad98f2e7f678",
          "body": "…ations, error states (#379)\n\n* fix(dashboard): trap and restore focus in Dialog component\n\nAdds WAI-ARIA modal focus management to the shared Dialog primitive:\nfocus moves into the panel on open, Tab/Shift+Tab cycles within it,\nand focus is restored to the triggering element on close. Fixes the\ngap\n[…]\nc.).\n\nCloses #298\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n* merge main into claude/w12-dashboard-a11y-ux\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(dashboard): a11y and UX fixes — focus trap, keyboard nav, confirm…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T06:31:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "331738794113f1b6ce6cf2b92ad238eb7afbf979",
          "body": "…d dashboard CSP (#383)\n\n* fix(api): pad scope-denied timing and share AUTH_CACHE in scopedAuth\n\nAuth failures were already padded to a 300ms floor so invalid\ncredentials are indistinguishable by timing, but scopedAuth's\nscope-denied 403 branches returned immediately, letting a caller\nconfirm creden\n[…]\nhould do a final live-browser check before flipping to\nenforcing.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): pad scope-denied timing, share AUTH_CACHE in scopedAuth, ad…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T06:30:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1ea590745f001480c296957d19846e0fa0d7fec3",
          "body": "* fix(api): correct listTraces pagination to prevent false has_more and dropped rows\n\nlistTraces fetched exactly `limit` rows and set has_more = rows.length ===\nlimit, so an exactly-full final page reported a bogus next page. It also\ncursored on a bare updated_at with no tie-break, so traces sharing\n[…]\nm:write keeps working for create + verify\nunchanged.\n\nCloses #348\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): traces pagination, trace scoping, and claim:read scope (#381)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T06:16:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fd306ea899ddf4460a3b5c7d4927f5246e82dd80",
          "body": "PR #356 restored the comparison page (compare.astro) but the sitemap\ndrift check added in #358 fails CI because /compare is missing from\nsitemap.xml. Add the entry so main + dependents go green.\n\nCo-authored-by: CommandCodeBot <noreply@commandcode.ai>",
          "is_bot": false,
          "headline": "fix(dashboard): add /compare to sitemap.xml",
          "author_name": "Duyet Le",
          "author_login": "duyet",
          "committed_at": "2026-07-17T04:25:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d3a329e2eeb141f90c77a2f85afeecb2a0c94118",
          "body": "Plan 007. renewLease/releaseLease did check-then-act: SELECT the lease,\nbranch in JS, then UPDATE with no state guard in the WHERE. A concurrent\nrelease or expiry-driven re-acquire between the select and the update\ncould let renewLease stamp a fresh future expires_at onto an\nalready-released lease, \n[…]\ns so client-visible\nsemantics are unchanged. Mutual exclusion on acquire was already safe\nvia the partial unique index; this is a correctness-of-response fix.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): guard lease renew/release updates with state predicates (#382)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:41:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3a582a3df60dd7aeecbd1f6d16659eb790cfc43a",
          "body": "…-safe signatures (#380)\n\n* fix(api): exact-match webhook event subscriptions via json_each\n\ngetActiveWebhooksForEvent matched events with a substring LIKE over the\nJSON-serialized array, so overlapping event names (e.g. \"state.update\"\nvs \"state.updated\") would cross-match. Use json_each membership \n[…]\n\nreference implementation, and retry/dedup behavior.\n\nCloses #344\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): webhook exact-match, parallel delivery, retry tests, replay…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:41:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2cf90e0de162772be54f96062c57dfe1db479380",
          "body": "* docs: fix conversations/messages API reference to match live code\n\nThe \"current\" /api/v1 sections described a fictional \"V2\" convention set\n(PATCH update, ?include=messages opt-in, 204 append response, created_at\ncursor) that was drafted but never actually shipped. The real shared\nhandler (used by\n[…]\ny so this\ndoesn't recur.\n\nFollow-up to #333 per team-lead review.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs: fix API reference and project docs to match live code (#377)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:41:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a6a0650a666c8ed6b40a0e5de3b5abd840793447",
          "body": "…376)\n\n* fix(api): stop reflecting localhost origins and wildcard-with-credentials in CORS\n\nALLOWED_ORIGINS hardcoded localhost/127.0.0.1 entries that were also served in\nproduction (single Worker, no per-env origin list), letting any page open on\nthose loopback ports make credentialed cross-origin \n[…]\ns column null or absent) keep full access unchanged.\n\nCloses #346\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): CORS credential leak + empty-scopes privilege escalation (#…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:40:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "370f2ac024fb82808d2bb4010bf9d8b8d94790db",
          "body": "* docs(plans): track the plans directory and add a status index\n\nThe 10 implementation plans were untracked, so they existed only on one\nmachine while every PR referenced them by path, and no worktree could see\nthem. Each plan also instructs its executor to \"update this plan's row in\nplans/README.md\n[…]\nleteConversation\nand will conflict, plus a suggested merge order.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(plans): track the plans directory and add a status index (#371)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:40:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "943f2d8860483f435e65e6108099f314cfb9c557",
          "body": "…370)\n\nThe dashboard analytics endpoint (GET /v1/projects/:id/analytics)\ncaches results in AUTH_CACHE for 60-300s under\nanalytics:public:{projectId}:{range}, but createConversation and\ndeleteConversation never busted it. Deleting conversations showed\nstale, too-high counts for up to 5 minutes.\n\nExpl\n[…]\n of time, so bust all three cached\nranges (7d/30d/90d) for the project via a new\nlib/analytics-cache.ts helper, fire-and-forget via executionCtx.\n\nCloses #352\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): invalidate analytics cache on conversation create/delete (#…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:40:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "93c28791f3d544dfd5512d754d83a98703895b41",
          "body": "…#359)\n\nZero tests existed for GET /v1/conversations/search despite it being a\nsecurity-relevant query path (LIKE-wildcard escaping) with composite-cursor\npagination. Characterizes: happy-path snippet matching, literal '%'/'_'\nescaping (excluding non-literal variants), the intentionally-unescaped '['\ncase, q validation, malformed/legacy cursor handling, and a two-page cursor\nwalk asserting no overlap/gaps.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "test(api): cover conversation search escaping and cursor pagination (…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:40:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2657e5d978faec1f21d8d5b47e6f0a7f99f316d4",
          "body": "…, README badges (#358)\n\n* feat(seo): add robots.txt with sitemap pointer\n\nThe Workers asset binding's SPA fallback silently served index.html for\n/robots.txt since the file never existed, giving crawlers no crawl\ndirectives and hiding the sitemap location.\n\nCloses #307\n\nCo-Authored-By: Duyet Le <me\n[…]\ndges alongside the existing\nLicense/PRs-welcome row.\n\nCloses #313\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(seo): robots.txt, noindex, JSON-LD, sitemap drift check, keywords…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:40:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f25b2dcd3d34bfa6a8c41e7b2f81d1f81792fa44",
          "body": "* fix(api): rate-limit the states router\n\nEvery write-heavy states route (watch, query, lease, events, PUT, GET,\nDELETE) attached scopedAuth per-route but never chained\nrateLimitMiddleware, so an authenticated key could drive unlimited D1\nwrites and Durable Object notify traffic. Add the limiter aft\n[…]\nstates PUT still\nsucceeds under the limit.\n\nRefs #340, #349, #350\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): rate-limit states/leases/claims/mcp coordination routes (#357)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:40:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f5f811fc12e7acccd3b92620a726ef2cea9e6391",
          "body": "…ce (#356)\n\n* feat(dashboard): restore primitives grid, comparison table, API surface\n\nPR #339 (shadcn redesign) dropped three content blocks from the landing\npage that existed nowhere else: the five-primitives grid, the\nmemory-vs-AgentState comparison table, and the API-surface endpoint\ntable. Reco\n[…]\nit to API_BASE_URL to match every other\noccurrence in docs.astro.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): restore primitives grid, comparison table, API surfa…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T03:40:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5e6abe422d0ea634cdfd0a3b4ab85e2531ec7f76",
          "body": "Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(deps): update dependency picomatch to v4 (#282)",
          "author_name": "renovate[bot]",
          "author_login": "renovate[bot]",
          "committed_at": "2026-07-17T02:05:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aaf05ac2df312b586602b7b3b1215df280013d3c",
          "body": "…(#355)\n\n* fix(states): atomically gate writes on leases and idempotency keys\n\nCloses two TOCTOU races in the state mutation path:\n\n- Leases (#289): the lease check was a separate SELECT before the write\n  batch, so a lease that expired or was handed off between check and write\n  still let the stale\n[…]\nlready fixed in code for #327) is corrected\nto match.\n\nFixes #325\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix: batch of triaged correctness bugs and small dashboard/SDK fixes …",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-17T01:28:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ce9a1fac824e599ae83be5ea3cc3fdc42a0c2f5d",
          "body": "…, chat components (#339)\n\n* feat(dashboard): add shadcn semantic token aliases to design system\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n* feat(dashboard): rebuild landing page with shadcn-style blocks\n\nSplit hero with code demo, numbered workflow, feature \n[…]\n\nconsistent px-6/gap-6 shells and bg-card/border-border surfaces.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): shadcn/ui redesign — landing page, dashboard spacing…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-16T19:27:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42b30dc443e36a1377f2cd82681b99199f50ffb2",
          "body": "…olish\n\n- Add dedicated /dashboard/keys page with secure one-time key copy (sessionStorage, never echoed in table)\n- Add \"API Keys\" sidebar nav item and link it from the landing-page feature card\n- Replace static agent.ts hero snippet with a tabbed CodeTabs demo for TypeScript, Vercel AI, LangGraph,\n[…]\nsive features showcase (all 23 features)\n- UI polish: theme-toggle cross-fade, concentric radii, press feedback + 40px hit areas on raw buttons\n\nCo-Authored-By: CommandCodeBot <noreply@commandcode.ai>",
          "is_bot": false,
          "headline": "feat(dashboard): add API Keys page, tabbed hero demo, and interface p…",
          "author_name": "Duyet Le",
          "author_login": "duyet",
          "committed_at": "2026-07-15T05:49:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "46025acc80dceeb512034fd2a5b6157d2d187601",
          "body": "* chore(deps): update dependency @cloudflare/workers-types to v5\n\n* fix(api): type ExecutionContext generically for workers-types v5\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>\nCo-authored-by: duyetbot <bot@duyet.net>\nCo-authored-by: Duyet Le <me@duyet.net>",
          "is_bot": true,
          "headline": "chore(deps): update dependency @cloudflare/workers-types to v5 (#280)",
          "author_name": "renovate[bot]",
          "author_login": "renovate[bot]",
          "committed_at": "2026-07-10T00:12:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dcea99958118ca2b696a0f1556b57437cd5d3e2f",
          "body": "…(#281)\n\n* feat: enable Cloudflare Workers Cache for public read-only endpoints\n\nEnable Workers Cache (\"cache\": { enabled: true }) on the API Worker and set\nCache-Control: public on the genuinely public, unauthenticated, static GETs\nonly: /api (health, max-age=60/swr=300) and /llms.txt, /agents.md,\n\n[…]\nject — no re-parse cost on cache misses/bypasses or in local dev.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat: enable Cloudflare Workers Cache for public read-only endpoints …",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-07T00:23:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4c09ba28d59d56888ccba9f2c60dcf21e0557efd",
          "body": "…18.0 (#279)\n\nCo-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(deps): update dependency @cloudflare/vitest-pool-workers to ^0.…",
          "author_name": "renovate[bot]",
          "author_login": "renovate[bot]",
          "committed_at": "2026-07-07T00:23:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ed75ef48da7cb87e6de1cc52f0c9e591f6f342c",
          "body": "…shboard (#276)\n\n* fix(auth): isolate org-less users per-account instead of a shared default\n\nDerive a per-user org discriminator (personal:${clerkUserId}) when a Clerk\nsession has no active organization, and drop the \"default\" fallbacks in\nclerk-session.ts and routes/projects.ts. Previously every o\n[…]\no the panel doesn't show the previous conversation while loading.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix: address codebase-analysis findings across API, SDKs, MCP, and da…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-03T00:14:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ac52fb50b6845a3e03619d5358b7d151033db83f",
          "body": "…252)\n\n* refactor(dashboard): redesign traces page to design-system v2\n\nReplace traces-page.tsx's inline duplicate PageHeader with the shared\ncomponents/dashboard/page-header. Swap the hand-rolled <table> waterfall\nlist for the canonical Table/TableHeader/TableRow/TableHead/TableCell/\nTableSkeleton \n[…]\nmestamps (0 is valid)\n\nApplies CodeRabbit suggestions on PR #252.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "refactor(dashboard): redesign traces page to design-system v2 (D4) (#…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T06:40:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "909566680e37c6e3bf751dd4e564fb23cc2f8eb9",
          "body": "* refactor(dashboard): redesign domains page to v2 design system\n\nReplace the inline header with the shared PageHeader, flatten the\nover-nested domain-card sub-components (fold actions + status badge\ninto the card, drop the redundant _components.tsx re-export), swap\nthe hand-rolled domain input for \n[…]\nor showAddForm toggle\n\nApplies CodeRabbit suggestions on PR #248.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "style(dashboard): redesign Domains page to design-system v2 (D6) (#248)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T06:38:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "48986c6ef947b0e8ecd55d8a0448d2f454655cfe",
          "body": "…tem v2 (D7) (#247)\n\n* feat(dashboard): redesign organizations settings to design-system v2\n\nConvert list/create/members pages under settings/organizations to the\ncanonical vermilion-accent design system: shared PageHeader on all three\nroutes, Input/Select primitives replace raw <input>/<select>, Ta\n[…]\nIndex/preventDefault)\n\nApplies CodeRabbit suggestions on PR #247.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "style(dashboard): redesign organizations/settings pages to design-sys…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T06:38:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c62c181bd2698e93d146d4b8343fc610db46a49a",
          "body": "…(D1) (#250)\n\n* feat(dashboard): bold premium redesign of marketing home page\n\nRework the landing page hero, primitives section, and CTA to match\nVercel/Linear/Resend-tier polish while staying strictly within the\ndesign-system-v2 token vocabulary (vermilion accent, canonical color/\nspacing/radius to\n[…]\nnditional\ninner shapes. Applies CodeRabbit suggestion on PR #250.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): bold redesign of marketing home to design-system v2 …",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T06:37:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "309d96536cf1c50d49a4aebe50887e492b978738",
          "body": "…2) (#249)\n\n* style(dashboard): align docs/brand/oauth pages to design-system v2 tokens\n\nReplace hardcoded blue accent (#3b82f6 -> vermilion #e2664d) on the brand\nsheet, fix stale \"accent blue\" copy, and align the radius showcase with\nthe true --radius-sm/--radius/--radius-lg/--radius-xl scale.\n\nMig\n[…]\nfore\ncalling closest(). Applies CodeRabbit suggestion on PR #249.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "style(dashboard): align docs/brand/oauth pages to design-system v2 (D…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T06:37:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "205136e6001a34c7e7602ee85188b30f37c4fbff",
          "body": "…(D8) (#246)\n\n* style(dashboard): convert Integrate page to canonical design tokens\n\nReplace the shared brand `Pill`/`CodeBlock` imports (still on legacy\nshadcn-alias tokens like border-border/bg-card/text-muted-foreground)\nwith the canonical `Badge` primitive and a page-local `CodeBlock` that\nuses \n[…]\ne-after-unmount. Applies\nCodeRabbit review suggestion on PR #246.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "style(dashboard): redesign Integrate page to canonical design tokens …",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T06:36:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c46186c1e716543be295e903da50b3b08c0da055",
          "body": "…253)\n\nMigrate the Projects listing and project-detail pages to the v2 design\nsystem: adopt the shared PageHeader, use canonical spacing utilities\n(page-padding, space-y-section, gap-component, card-padding, etc.)\ninstead of ad-hoc padding/gaps, remove redundant heading weight\noverrides now handled \n[…]\ndead _dashboard-header\nafter switching to the shared PageHeader. No functional changes —\ncreate project, key management, tabs, and empty states all preserved.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): redesign projects listing and project detail (D3) (#…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T06:33:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "35b9fcf7548b79633e8cfe27d42909ecbc4e5500",
          "body": "style(dashboard): redesign Analytics page to design-system v2 (D5)",
          "is_bot": false,
          "headline": "Merge pull request #251 from duyet/redesign/d5-analytics",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T06:22:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3e0669a45e96ac3f5af93169a377db721bc56982",
          "body": "Replace hardcoded chart colors (#3b82f6, #34d399, #f59e0b, #f87171) and\necharts chrome colors (tooltip, axis, gridlines) with the chart-1..5\ndesign tokens, resolved at runtime via getComputedStyle so series and\nchrome colors track the active light/dark theme automatically.\n\n- area-chart.tsx: colorTo\n[…]\nused for a \"+X% above avg\"\n  stat that isn't negative — should read text-pos like the sibling\n  TokenTrendSummary card\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): redesign analytics to design-system v2 tokens",
          "author_name": "Duyet Le",
          "author_login": "duyet",
          "committed_at": "2026-07-02T04:33:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "29e236dfa3981b2418577a5f97b17c78e25cf9d2",
          "body": "feat: merge redesign/v2 (design-system v2 + API reference reconcile) into main",
          "is_bot": false,
          "headline": "Merge pull request #245 from duyet/redesign/v2",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T04:20:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d7178fd9e1b0f6aebccf23673ff02321e24d6961",
          "body": "# Conflicts:\n#\tdocs/INDEX.md\n#\tdocs/api-reference.md\n#\tpackages/dashboard/src/layouts/MarketingLayout.astro\n#\tpackages/dashboard/src/styles/tokens.css",
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'origin/main' into redesign/v2",
          "author_name": "Duyet Le",
          "author_login": "duyet",
          "committed_at": "2026-07-02T04:17:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "67b38024b0ef1a6b8e9776b38ac081a9ed0dbb66",
          "body": "* feat(dashboard): migrate marketing scope to design-system-v2 fonts\n\nRetire Geist from the marketing/brand scope and unify on the v2 type\nsystem already used by the dashboard: Space Grotesk (display),\nHanken Grotesk (body), JetBrains Mono (code).\n\n- tokens.css: swap @theme font families, add --font\n[…]\nine collapsing surfaced by the\npre-commit hook. No logic changes.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "style: apply biome formatting to api and sdk sources (#244)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T04:16:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "86ef71cdfce3fc133426c197ca08e79d8ff7e1e8",
          "body": "The api-reference \"Current API\" section documented a never-deployed \"v2\"\nbehavior (PATCH updates, ?include=messages, pagination.total, messages\nexcluded from create, 204 on append, timestamp message cursors, key_id/\nproject_id field renames, project_id analytics query param). The v2 router\nwas remov\n[…]\nion analytics, bulk delete, export, tags,\n  AI features, dashboard project views)\n- Rewrite docs/v2-migration.md as a short historical note; fix INDEX.md link\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs: reconcile API reference with the live /api/v1 router (#243)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T04:13:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "200bd9bec4c632b05406f262c7a468f2c2861b5d",
          "body": "…241)\n\nRetire Geist from the marketing/brand scope and unify on the v2 type\nsystem already used by the dashboard: Space Grotesk (display),\nHanken Grotesk (body), JetBrains Mono (code).\n\n- tokens.css: swap @theme font families, add --font-display\n- MarketingLayout: load the new @fontsource-variable packages\n- brand.astro: relabel the type specimen (Display/Sans/Mono) so it\n  accurately describes the fonts the page now renders\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): migrate marketing scope to design-system-v2 fonts (#…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T03:57:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9c8be76b2bec87fc531bebed9050160fa8d71f61",
          "body": "…ids (#238)\n\n* fix(api): tighten input validation for slugs, tags, and conversation ids\n\n- Project slugs now have a 255-char upper bound (previously unbounded)\n- Unify conversation-tag and state-tag max length to 50 chars via a\n  shared TAG_MAX_LENGTH constant, replacing the inconsistent 50 vs 64\n  \n[…]\not <bot@duyet.net>\n\n* style(api): biome format after merging main\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): tighten input validation for slugs, tags, and conversation …",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T03:54:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "af3bbbd92908d816c43d63d3a4f4b6698ad7b3b1",
          "body": "…ns (#239)\n\nAudit unit A2 (V2 keys security + minor consistency):\n\n- Finding 1 (CRITICAL, keys route missing scope enforcement) was already\n  fixed upstream: the unmounted routes/v2/keys router this finding targeted\n  was removed entirely by #228's v2->v1 collapse, and the live route\n  (routes/v1-ke\n[…]\n the RFC 6749\n  { error, error_description } shape instead of the standard API error\n  format, and that the rest of the oauth router uses the standard format.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(api): document keys/leases/states/webhooks/oauth scope conventio…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T03:52:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cec40c0c2fd14b928a6233036f644ec623ffcf47",
          "body": "- environment-variables.md: fix VECTORIZE_INDEX / STATE_STREAM_HUB\n  references from stale /v2/* paths to the real mounted paths\n  (GET /api/v1/conversations/search, GET /api/v1/states/watch)\n- api-reference.md: add total_cost_microdollars and total_tokens to\n  conversation response examples and the\n[…]\n() and the create handler serialization\n- docs-data.ts: fix conversation update method PATCH -> PUT to match\n  the mounted routes/conversations/crud.ts router\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs: correct stale route paths and missing response fields (#235)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T03:51:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f6b10804e6cd3883c9e7d934713e64ea6e78881e",
          "body": "Merge docs/integration-guide.md into the canonical docs/integration.md\n(the more widely referenced file) and turn the former into a short\npointer. Preserves all unique content: chat-app patterns, LLM tracing,\nmulti-tenant SaaS, full REST reference, AI SDK UI/RSC stores, Cloudflare\nAgents SDK, generi\n[…]\nardize base URL and as_live_ + 40 base62 key format.\n- Update internal links in INDEX.md (dedupe the two entries) and\n  integrations/clickhouse-monitoring.md.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs: consolidate integration guides + add LangChain example (#234)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T03:51:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d5a4c166a6bf334aac92deed3c843e24e5521d70",
          "body": "…mples (#233)\n\n- Clarify that https://agentstate.app/api (TS default) and\n  https://api.agentstate.app (Python default) are equivalent aliases,\n  documented in docs/sdk.md, python-sdk README, and client.py docstring.\n- Add a message response-shape example to docs/sdk.md showing the real\n  fields the API returns (model, input_tokens, output_tokens, metadata),\n  matching deserializeMessage in packages/api/src/lib/serialization.ts.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(sdk): align SDK base-url notation and complete message-field exa…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-07-02T03:51:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3bfeb48041c08415de3147647b05c5f5087d35ab",
          "body": "…foundation' into redesign/v2",
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'origin/feat/dashboard-design-system-v2-…",
          "author_name": "Duyet Le",
          "author_login": "duyet",
          "committed_at": "2026-07-02T03:22:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a96906c91189e4d246a8119781d81ac4762ce8cc",
          "body": "Merge tokens.css and global.css's competing color/type systems into one\nsource of truth. tokens.css is now the canonical @theme (vermilion accent\nreplaces blue, unified on Space Grotesk/Hanken Grotesk/JetBrains Mono,\nretiring Geist); global.css imports it and layers shadcn-style aliases\n(bg-card, te\n[…]\npec for downstream page workers: token\nnames, type/spacing/radius scale, primitive component APIs, and do/don't\nrules.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): unified design-system v2 foundation",
          "author_name": "Duyet Le",
          "author_login": "duyet",
          "committed_at": "2026-07-02T03:09:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b3e77dea879977171db62a8d8e9a6677004efef7",
          "body": "Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(deps): update dependency node to v24 (#232)",
          "author_name": "renovate[bot]",
          "author_login": "renovate[bot]",
          "committed_at": "2026-06-30T00:09:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fd4dddcab86d369de9382de4afd92fa47e72dd92",
          "body": "Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(deps): update dependency @types/node to v26 (#231)",
          "author_name": "renovate[bot]",
          "author_login": "renovate[bot]",
          "committed_at": "2026-06-30T00:08:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "54aa2426d594bebcdbd23aa92c61a78187f87283",
          "body": "Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(deps): update astro monorepo (major) (#230)",
          "author_name": "renovate[bot]",
          "author_login": "renovate[bot]",
          "committed_at": "2026-06-23T00:08:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d3de5878ff3eda07061cd7cabdafdcc5ad59938b",
          "body": "Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(deps): update actions/checkout action to v7 (#229)",
          "author_name": "renovate[bot]",
          "author_login": "renovate[bot]",
          "committed_at": "2026-06-23T00:07:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ec68b8b222e5fdcafa67a0b0ed31c39006aef914",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "chore(main): release 0.1.4 (#176)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-06-21T04:16:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "61af5f4aeba1e5cfc5d5145641c0ef79ec051b8a",
          "body": "…el stack (#228)\n\nRemoves the unmounted routes/v2 trees, orphaned semantic-search plumbing, the\nduplicate v2-projects service (updateProject inlined into services/projects),\nstale v2 *.skip.ts suites, the orphaned analytics service, and callerless\nhelpers. Flattens routes/v2 into routes/ and renames v2-conversations to\nmcp-conversations. No behavior change; 327 tests pass.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "refactor: finish the v2→v1 collapse — remove the dead \"API v2\" parall…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-20T06:15:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1dc75aabce2fd6fee11b5ec20e6329fde35e6abe",
          "body": "…laim:write) (#227)\n\nThe scoped-keys taxonomy used plural `leases:write` / `claims:write`, but the\npre-existing convention — the v2 lease/claim route guards (scopedAuth), the\ncapability-token scopes, and already-issued as_cap_ tokens — uses singular\n`lease:write` / `claim:write`. The mismatch meant \n[…]\nonical scope form across keys, capability tokens,\nroutes, and MCP — no mapping.\n\nAdds a regression test: a key scoped to lease:write can use the leases route.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): standardize lease/claim scopes to singular (lease:write / c…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T12:24:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a12fe9e812cd40f361d013f1369c0b27aa8cf484",
          "body": "Adds create_api_key, list_api_keys, and revoke_api_key tools so MCP clients can\nmanage project API keys (with scopes) directly — matching the hosted remote MCP\nserver. They call the keyless /api/v1/keys endpoints (project from the auth\ncontext). create_api_key enforces the subset-of-caller scope rul\n[…]\nde.\n\n- src/index.ts: 3 new tools + an apiScopeSchema enum of the API scopes\n- tests: cover the new tools' request URL/method/body\n- README: list the new tools\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(mcp): add API-key management tools to the stdio MCP server (#226)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T12:09:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "985de3d93f53b45c6889f82e7c54aa004f35c0e3",
          "body": "… connect (#225)\n\n- API key creation: \"Full access\" (default) vs \"Custom\" permission selector with\n  a grouped scope checklist; keys table shows per-key permission badges\n- New OAuth consent screen at /oauth/consent (Clerk-gated): shows the requesting\n  client, requested scopes, and a project select\n[…]\nsection with the hosted MCP URL and config\n  snippets for token auth and OAuth\n- Shared dashboard scope catalog (src/lib/scopes.ts) mirroring the API taxonomy\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): scoped-key permissions UI, OAuth consent screen, MCP…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T12:01:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8c7932dabfba2a1b6872174676acf422f28b2dd2",
          "body": "Document the hosted remote MCP server at POST /api/mcp (Bearer token or\nOAuth), the OAuth 2.1 + PKCE flow with discovery and consent, and scoped\nAPI keys.\n\n- docs/mcp.md: add \"Remote MCP server (hosted)\" section, keep local stdio below\n- docs/oauth.md: new — discovery, DCR, authorize/consent/token, \n[…]\novery, scopes field, /api/v1/keys\n- dashboard /docs: add Remote MCP, OAuth, Permissions sections + nav\n- packages/mcp/README.md: note the hosted remote server\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs: remote MCP server, OAuth 2.1, and key permissions (#222)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T11:48:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42a2323de6e3a8629b7ffd336ea0f1ffc9a8868a",
          "body": "…tes (#224)\n\nAdd a stateless Streamable HTTP MCP server (spec 2025-06-18) at POST /api/mcp\nso agents can connect over the network with an AgentState API key or an\nOAuth/capability access token, instead of running the local stdio bridge.\n\n- middleware/mcp-auth.ts: accepts `as_live_` keys and `as_cap_\n[…]\n/list, tools/call, scope\nenforcement, capability-token lease delegation, protocol-version negotiation,\n401 challenge, and 405 on GET. Full suite: 302 passing.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(api): remote MCP server at /api/mcp + keyless key-management rou…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T11:46:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5517c4b5e6c080ae9a85621bd3f3ad4abf596d0c",
          "body": "…(#223)\n\nCo-hosts an OAuth 2.1 (authorization-code + PKCE S256) server in the Worker so\nMCP clients can obtain scoped access tokens. Access tokens reuse the existing\ncapability-token mechanism (as_cap_ tokens), so they validate through the\nexisting scopedAuth path unchanged.\n\nEndpoints:\n- GET /.well\n[…]\n\nconsent decision incl. cross-org rejection, full code exchange, PKCE mismatch,\ncode replay, refresh rotation + reuse rejection). Full API suite: 317 passing.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(api): OAuth 2.1 authorization server + discovery for remote MCP …",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T11:39:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "29b28373087d9feb6a182328de9eb35f9b83173f",
          "body": "Add a permission-scope model to API keys so a key can be restricted and can\nonly mint child keys/tokens within its own scopes — the foundation for the\nremote MCP server + OAuth consent work.\n\n- lib/scopes.ts: canonical API_SCOPES taxonomy + scopeSatisfies /\n  scopesSatisfyAll / effectiveKeyScopes he\n[…]\n rate limit + webhooks:write\n- shared: ApiKeyResponse.scopes + ApiScope type\n\nLegacy/unscoped keys resolve to full access (\"*\") so existing keys keep working.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(api): scoped API keys foundation (permissions + enforcement) (#221)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T11:07:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8c7a57c9fe989f984d39f56bd3bef64115362819",
          "body": "… sidebar project scope (#220)\n\n* fix(dashboard): repair delete-project and retention confirmation dialogs\n\nBoth reused DialogTrigger (a self-contained component) alongside their own\nopen-state + Dialog, producing a phantom modal showing only the trigger's\nicon + label. Retention was worse: its Chan\n[…]\n.json, plus an `npx skills add duyet/agentstate`\ninstall snippet.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(dashboard): dialogs, traces auth, markdown, project sort + global…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T09:06:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "63f7fc2b216740f3d5e675b78ef7f1e85c36a44d",
          "body": "… $NaN cost (#219)\n\nThe project Data tab rendered every message as a role badge + raw text, so\nassistant markdown showed literal **bold**, ### headings, and * bullets, and\nthe cost column showed \"$NaN\".\n\n- Render messages as a chat (assistant-ui style): user messages in a\n  right-aligned bubble; ass\n[…]\non-finite as\n  $0.00 (the conversation list API omits per-conversation cost).\n\nNew deps: react-markdown@10, remark-gfm@4 (client-only, in the message island).\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): chat-style conversation rendering with markdown; fix…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T06:52:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c09606399193e8d1ba96803226a0fa7985d2bcc2",
          "body": "…evoke) (#218)\n\nThe members page could only display members and pending invitations —\nrevoking an invitation punted to the Clerk Dashboard and there was no way\nto remove a member or change a role in-app.\n\nAdd admin-only management via Clerk's client SDK (which enforces admin\nauthorization server-sid\n[…]\ning state.\n\nNo backend/auth changes — all actions go through Clerk. Org data is already\nscoped by the session's active org, so members see shared org content.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): in-app org member management (remove, role change, r…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T06:42:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1f635a3c50c12e709acf2b0aa418c423444a3c34",
          "body": "… nav links (#217)\n\nTwo related dashboard fixes:\n\n1. `text-base` was used as a color (with `bg-fg`) in the primary button and\n   landing-page CTAs, but Tailwind reads `text-base` as a font-size utility, not\n   the `--color-base` token. The text color fell back to the inherited muted\n   body color → \n[…]\nnks with an external-link affordance, are never\n   highlighted as active (removed from active-URL resolution), and are pinned to\n   the bottom of the sidebar.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(dashboard): correct primary-button text color + restyle secondary…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T06:30:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bf510136d12cd223743c9d30c2a1a4c5e1edf229",
          "body": "…(#216)\n\nThe projects list only showed name, key count, and created date. Add\nper-project aggregates — conversations, messages, tokens, and last\nactivity — plus a name/slug filter input above the table.\n\n- API: listProjects now returns conversation_count, message_count,\n  total_tokens, and last_acti\n[…]\nhe four stat fields.\n- dashboard: new responsive columns (secondary columns hide on smaller\n  viewports) and a client-side filter; empty-match state included.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): show per-project stats and filter in projects table …",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T05:57:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2b8d1e0099891a555394e8a25653a608b5120583",
          "body": "The sidebar used per-item exact matching, so detail routes like\n/dashboard/project (where the projects table links) matched no nav\nentry and left nothing highlighted. Replace with longest-prefix\nmatching: a child route resolves to its closest parent (Projects),\nwhile deeper exact matches (Conversations, Analytics) still win, and\nthe root \"/\" only matches the root path.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(dashboard): highlight correct sidebar item on child routes (#215)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T05:54:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "02bc74b5aa73bd559c449ebda636d63814c9a323",
          "body": "…) (#214)\n\nAdds honest `biome-ignore: used in the template below` to the page-component and\nDashboardLayout imports on the seven dashboard app pages (analytics,\nconversations, domains, index, integrate, project, create-org). Biome can't see\nAstro template usage, so it flagged these as unused — but e\n[…]\n. Completes the QUAL-2 cleanup for the app pages; these 7 files now lint\nclean.\n\nRisk: 🟢 comments only, zero output change (build 13 pages). Rollback: revert.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "chore(dashboard): silence import false-positives on app pages (QUAL-2…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T04:44:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d28ca7290892e434721f1aa9f8ebe6050d4fa1aa",
          "body": "Silence the recurring biome warnings without changing any rendered output:\n- Remove 4 ineffective JSX biome-ignore comments (conversations-page, _table-\n  skeleton ×2, _keys-tab) that biome reported as having no effect (misplaced /\n  rule not firing).\n- Fix the global.css reduced-motion override: mo\n[…]\ning\nrendered was removed). Dashboard biome warnings 68 → 48. No behavior change.\n\nRisk: 🟢 comments only, zero runtime/output change. Rollback: revert this PR.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "chore(dashboard): clean up lint-debt suppressions (QUAL-2) (#213)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T04:34:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e903d4569779238a55b42aa1c6acf2a63f134e92",
          "body": "… (#212)\n\nAdds a comparison section to the landing page contrasting AgentState with\nmemory/history-only tools and roll-your-own setups. A 6-row table covers\nconversation history, versioned state, distributed leases, capability tokens,\nverifiable claims, and pricing/hosting — emphasizing the coordina\n[…]\nw deps. Visually verified\n(desktop + mobile; table wraps without overflow; dark = token-only). Sections\nabove/below intact. Rollback: revert this single file.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): add \"vs memory-only tools\" comparison section (LP-3)…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T04:34:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a77bbee08cd39b63f3748131e58210b5eefc632d",
          "body": "Introduce a minimal AIProvider interface (generateTitle, generateFollowUps,\ngenerateTitleAndFollowUps, generateEmbedding) with WorkersAIProvider as the\ndefault implementation. The existing logic (models, prompts, parsing) is MOVED\nverbatim from ai.ts into the provider; the exported service functions\n[…]\n same parsing/fallbacks; vitest 280/280 unchanged.\n\nRisk: 🟢 behavior-preserving extraction; no call-site or API change, no new deps.\nRollback: revert this PR.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "refactor(api): extract AIProvider seam over Workers AI (DEHARD-2) (#211)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T04:19:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "03d149e29c034e63412d74e6b84e7325e608c751",
          "body": "The public pages had a stale title/description and no social/canonical meta;\nsitemap.xml 404'd. This adds proper SEO to the marketing surface:\n\n- MarketingLayout now accepts title/description/ogImage/canonical props and emits\n  <title>, meta description, OpenGraph, Twitter Card (summary_large_image)\n[…]\n/twitter:card/canonical; sitemap emitted to out/.\n\nRisk: 🟢 additive head meta + one static file; no body/layout change, no new deps.\nRollback: revert this PR.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): SEO meta + sitemap for marketing pages (LP-4) (#210)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T04:17:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dc0aaf482c4c646a1b71093dfbe2b6c71be7bd4a",
          "body": "…ets (LP-1) (#209)\n\nThe homepage hero undersold the product — \"The state layer for AI agents\" with a\nmemory/adapters framing read like a chat-history store, not a coordination layer\nfor multi-agent systems. The README already had the right message; this aligns\nthe homepage with it.\n\n- H1: \"State & c\n[…]\nno new deps/components. Visually\nverified (build 13 pages; light desktop+mobile+full-page screenshots; dark = same\ntokens). Rollback: revert this single file.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(dashboard): reframe landing hero around coordination & agent fle…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T04:01:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a4dee462bea72d4c28a6cf05a6d83f56fcd7b07a",
          "body": "Documents @agentstate/mcp (shipped in #207): prerequisites, npx/global install,\nenv vars (AGENTSTATE_API_KEY, AGENTSTATE_BASE_URL), ready-to-paste mcpServers\nconfig for Claude Desktop / Cursor / Windsurf, the 12 tools grouped by primitive,\na \"verify it works\" step, and a free-key CTA. Linked from do\n[…]\nDEX.md.\n\nEvery tool/env documented was checked against packages/mcp/src/index.ts — no\nfabricated tools or flags.\n\nRisk: 🟢 docs-only. Rollback: revert this PR.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(mcp): add MCP server install & usage guide (MCP-2) (#208)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T04:00:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b7b6429bcf2779b1eda3000e1858faa0ebf27f9e",
          "body": "…tives (MCP-1) (#207)\n\nNew package that lets agents use AgentState from Cursor / Claude Desktop /\nWindsurf via the Model Context Protocol. Self-contained stdio server built on\n@modelcontextprotocol/sdk; talks to the AgentState REST API over fetch (no\nworkspace coupling). Tools: store/recall/list con\n[…]\nkey.\n\nRisk: 🟡 new package; not imported by api/dashboard so zero production runtime\nimpact. Rollback: revert this PR (removes the package + lockfile entries).\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(mcp): add @agentstate/mcp — MCP server exposing AgentState primi…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T03:46:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "709015b0e5bbf74b272afb87477936d2964d5dbd",
          "body": "…D-1) (#206)\n\nExtract scattered magic numbers (cache TTLs, lease default TTL, retention\nbatch size + time budget, ms-per-day) into a single lib/config.ts module so\nthe values have one authoritative home. Pure refactor — every constant keeps\nits exact prior value; behavior is byte-identical (vitest 2\n[…]\nliberately left next to their security-critical\nlogic (protected code, human-gated).\n\nRisk: 🟢 none (no runtime behavior change). Rollback: revert this commit.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "refactor(api): centralize tunable constants into lib/config.ts (DEHAR…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T03:45:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "625efe240bb6afbc4f2945f998b46f0a24df6cae",
          "body": "* chore(content): add generator for served llms.txt/agents.md content\n\nstatic.ts is served at /llms.txt and /agents.md but was hand-maintained despite an\n'auto-generated' header. Add scripts/generate-content.mjs (bun run gen:content) so it\ncan no longer drift from the source files.\n\nCo-Authored-By: \n[…]\nlds=!messages omits).\n- Regenerate served static.ts from the sources.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyet <me@duyet.net>",
          "is_bot": false,
          "headline": "docs: make AI-agent integration content accurate and complete (#183)",
          "author_name": "duyetbot",
          "author_login": "duyetbot",
          "committed_at": "2026-06-18T02:15:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "91a831c8ce3a92c6540d01ea2c958fe8d89fb43a",
          "body": "POV post on attesting agent output with claims + text_hash/json_value/\nstate_event evidence and the verify flow. All API shapes grounded in\ndocs/recipes/claims.md and the claims service; no fabricated metrics. (CONTENT-2)\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(blog): verifiable agent output with claims and evidence (#203)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T02:06:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5880bee5f543dde3ad45c4be7d048a05b7066704",
          "body": "…(#204)\n\ngetting-started: drop the broken keyless \"create project via curl\" example\n(project creation requires dashboard/Clerk auth) and point to dashboard signup;\nadd a leases-recipe pointer. README: fix dashboard dev port (3000->4321) and use\n$CONVERSATION_ID in the retrieve example. Accuracy verified vs /api/v1 routes.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs: tighten 2-minute quickstart + fix stale references (CONTENT-4) …",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T02:06:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b6b36739ca071e2d96f914ff0fc9f72b1d266598",
          "body": "…ouble-release (QUAL-3) (#205)\n\nAdds 5 tests (audited existing v2-* coverage first; these were genuinely\nmissing): expired lease re-acquisition with strictly higher fencing token\n(+ active lease still blocks with 409), expired capability token -> 401\n(+ valid token authenticates), double-release lease -> 404. Deterministic\nvia DB-level expiry (no real sleeps). 280 tests pass.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "test(api): coordination edge cases — lease eviction, expired token, d…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T02:05:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5844c896cff0b351919d15bf5e7882890826b375",
          "body": "…ems (#201)\n\nCategory POV post mapping multi-agent coordination needs to AgentState\nprimitives (leases/claims/capability-tokens/states). Claims grounded in\nreal /api/v1 routes; no fabricated metrics. (CONTENT-3)\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(blog): why agent memory tools aren't enough for multi-agent syst…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T01:46:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e7866be32946ff99ee146b6808cfc36d2a73a5d3",
          "body": "The migration guide's body contradicted its own \"all v1 now\" banner and\ndocumented /api/v2 paths that 404. Reconcile to the real /api/v1 routes;\nground deprecation/sunset claims in lib/deprecation.ts — no routes\nactually call setDeprecationHeaders in production. Frame the v2 proposal\nsections clearly as historical reference. (DOC-4)\n\nCo-authored-by: Duet Le <me@duet.net>\nCo-authored-by: duyetbot <bot@duet.net>",
          "is_bot": false,
          "headline": "docs: align v2-migration guide with unified /api/v1 reality (#200)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T01:46:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6cb57ed91f6771911fe018399ed8afb0b1b109db",
          "body": "Type-only changes — db→DrizzleD1Database, executionCtx→ExecutionContext,\nremove unsafe casts. No behavior change; 275 tests still pass. (QUAL-4)\n\nCo-authored-by: Duet Le <me@duet.net>\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "refactor(api): replace `any` with precise types in services (#202)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T01:46:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f626ee3e31afaa62fa7d0901c11bcd91d2708df1",
          "body": "…ases (CONTENT-1) (#199)\n\nAdd docs/blog/ with an index and the first post: a runnable walkthrough of the\nlease primitive for exactly-once processing across an agent fleet (curl + TS\nSDK). All /api/v1 endpoints, the 409 LEASE_CONFLICT code, SDK method names, and\nfencing-token semantics verified against the codebase; links to the\nexamples/fleet-leases script.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(blog): scaffold + first post — coordinating agent fleets with le…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T01:11:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90476da3e815baf882e25efa7001e979fb432a0c",
          "body": "Add a Primitives section to docs/sdk.md with a short, runnable\nTypeScript snippet for each of the five primitives (States, Leases,\nCapability Tokens, Claims, Conversations). All method names verified\nagainst packages/sdk/src/index.ts — no invented APIs.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(sdk): runnable per-primitive usage snippets (SDK-3) (#196)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T00:50:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "81f027c7a31b72a0834fd7489411d98cc7ecb790",
          "body": "Add a \"never commit secrets\" section, document all Worker bindings\n(required + optional), Worker secrets (CLERK_SECRET_KEY, CLERK_JWT_KEY),\nwrangler vars tuning knobs (RATE_LIMIT_MAX, PROJECT_CREATION_RATE_LIMIT_MAX),\nand the RATE_LIMITS / VECTORIZE_INDEX / STATE_STREAM_HUB optional bindings\nthat were absent from the previous version.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(security): secret-scan sweep + env handling guide (SEC-1) (#198)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T00:48:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1a1161b7b26cd93a2e5176f836a609f5f9c1516f",
          "body": "Add a prominent markdown table near the top of docs/INDEX.md listing\nthe five coordination primitives (States, Leases, Capability Tokens,\nClaims, Conversations) with one-line descriptions and links to each\nrecipe file.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(index): 5-primitives table linking each recipe (MSG-2) (#195)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T00:43:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3a02b04b4483981728f9c1c2f29cc9a6891c5c7e",
          "body": "…o /api/v1 (#194)\n\n* fix(api): restore project retention PATCH — converge /api/v/ scar onto /api/v1\n\nThe /api/v2/→/api/v1/ rename swept the backend (index.ts + tests) but not\nthe dashboard, leaving project-management mounts at the version-less\n/api/v/projects. The dashboard's retention setting calle\n[…]\nession test to assert `id` is\npresent and `project_id` is absent.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(api): restore project retention PATCH — converge /api/v/ scar ont…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-18T00:35:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b31a7dabd0587a8b7f7b691431b282b9fe8f1d9b",
          "body": "…rites (EX-1) (#193)\n\n* feat(examples): add fleet-leases example (coordinate N agents, zero double-writes)\n\nA runnable script spawning K workers that coordinate via leases so each\ntask is processed exactly once; asserts zero double-processing. Reads\nAGENTSTATE_API_KEY from env. Implements EX-1.\n\nCo-\n[…]\nase\nand concurrent workers double-process, failing the assertion.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(examples): fleet-leases — coordinate N agents with zero double-w…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T19:32:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "11e7bea5b8ce6534ab64ab31535584f940ba0a38",
          "body": "* docs(trust): add data-handling & data-ownership guide\n\nDocuments what data is stored, export (\"your data is yours\"), deletion\nand control, actual retention behavior, data security, and the\nself-host option. Verified against schema and routes. Implements TRUST-3.\n\nCo-Authored-By: Duyet Le <me@duyet\n[…]\ns)\n\nCorrect three endpoint references in the data-handling guide.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(trust): data-handling & ownership guide (TRUST-3) (#191)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T19:32:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e8f1de1dbf61b86a9148af2d48dcf01b7e416af1",
          "body": "Adds a securityHeaders middleware setting X-Content-Type-Options,\nX-Frame-Options, Referrer-Policy, and HSTS on every response (incl.\nerrors and static assets). Additive only — no change to auth, rate\nlimiting, or CORS. Implements SEC-2.\n\nCo-authored-by: Duyet Le <me@duet.net>\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "feat(api): add standard security response headers (#192)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T19:32:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7726b986f3539daf2435cfd686bf535d8ab5d4a0",
          "body": "… (#188)\n\nReframes the intro and Features so AgentState reads as the state &\ncoordination layer for agent fleets — States, Leases, Claims, Capability\nTokens, Conversations — with memory as one of five primitives rather\nthan the headline. Preserves badges, trust line, and docs table.\nImplements MSG-1.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(readme): lead with the coordination & state story (5 primitives)…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T19:12:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5f74b91a5b781bd6a8b305337dca0db51d5c752a",
          "body": "…) (#190)\n\nCompletes the five primitive recipes with runnable curl + TS/Python\nexamples for states (versioned event log, idempotency, time-travel,\nSSE watch) and conversations (CRUD, search, bulk, AI). Linked from\ndocs/INDEX.md. Implements backlog DOC (primitive recipes).\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(recipes): add states and conversations recipes (complete the set…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T19:12:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e87eb5415fd7d29f92e7872307cadcafec57fdfe",
          "body": "…cope denial (#189)\n\nAdds regression tests for the exactly-one-writer guarantee (lease\nacquire → 409 on contention → release → re-acquire with higher fencing\ntoken), json_value claim verification (pass + fail), and\ncapability-token scope denial on lease/claim writes. Implements QUAL-3.\n\nCo-authored-by: Duyet Le <me@duet.net>\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "test(api): cover lease contention/acquire, claim json_value verify, s…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T19:12:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6ba2d665b4eda5ee8495649f54fb8b8a9357171e",
          "body": "…lity tokens) (#186)\n\n* docs(recipes): add coordination primitive recipes (leases, claims, capability tokens)\n\nRunnable curl + TS/Python SDK recipes for the three coordination\nprimitives, each with key-concept notes. Linked from docs/INDEX.md.\nImplements backlog DOC-1/2/3 (Month-1 coordination wedge\n[…]\nx.HTTPStatusError (only 401/404/422/429 map to typed exceptions).\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(recipes): coordination primitive recipes (leases, claims, capabi…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T18:56:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a22c7210eda3fc9de0f6068cb69c023541f86875",
          "body": "Adds a public product roadmap (themes, no internal strategy) and\nminimal trust signals (MIT badge, self-host/free-to-start line,\nroadmap link) to the README. Implements backlog TRUST-4.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs: add public ROADMAP and OSS trust signals to README (#185)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T18:56:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aab0d49ac394e25aeed6c5fa0949d4c4af7d1377",
          "body": "* docs(security): add SECURITY.md responsible disclosure policy\n\nAdds a coordinated-disclosure policy (GitHub private reporting +\nfallback email), supported-versions note, scope, and a summary of\nexisting security practices. Implements backlog SEC-6.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Autho\n[…]\n\n/api/v1 is served) and drop an unverified runtime-secrets claim.\n\nCo-Authored-By: Duyet Le <me@duyet.net>\nCo-Authored-By: duyetbot <bot@duyet.net>\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "docs(security): add SECURITY.md responsible disclosure policy (#184)",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T18:56:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f1d451e4ac4a46ab0b887af8e76c77264440eb4f",
          "body": "… (#187)\n\ntsup's --dts build (rollup-plugin-dts) injects a `baseUrl` compiler\noption, which TS 5.9+ escalates to error TS5101 (deprecated, removed in\nTS 7.0). With CI on bun-version: latest, a recent TS bump turned this\ninto a hard failure: `bun run build` for the SDK fails, reddening main\nCI and bl\n[…]\net baseUrl ourselves — add\n\"ignoreDeprecations\": \"6.0\" to the SDK tsconfig so the dts build keeps\nworking across TS upgrades. No API or emitted-output change.\n\nCo-authored-by: duyetbot <bot@duyet.net>",
          "is_bot": false,
          "headline": "fix(sdk): silence injected baseUrl deprecation breaking the dts build…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T18:52:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ea3051f876e2ccd722a2d0950135e0f1ee362c65",
          "body": "…ons (#181)\n\n* chore(sdk): remove stale compiled artifacts from src/\n\nThe committed .js/.d.ts/.map files under packages/sdk/src shadowed the\nTypeScript sources under Vite's .js-before-.ts module resolution, causing\ntests that import ../src/index to run against stale output. The package\nonly ships di\n[…]\nc.com>\nClaude-Session: https://claude.ai/code/session_01AVRtn1t17iNe74i8ius8Ch\n\n---------\n\nCo-authored-by: duyetbot <bot@duyet.net>\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(sdk): add tag filter to listConversations for consumer integrati…",
          "author_name": "duyet",
          "author_login": "duyet",
          "committed_at": "2026-06-17T17:23:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "36ae481e97de103cbbdb4ced330931ead1bec6ac",
          "body": "Co-authored-by: duyet <me@duyet.net>",
          "is_bot": false,
          "headline": "docs: refresh SDK + API docs, fix v1/v2 README inconsistency (#179)",
          "author_name": "duyetbot",
          "author_login": "duyetbot",
          "committed_at": "2026-06-17T17:07:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 4,
      "commits_last_year": 452,
      "latest_release_at": "2026-06-21T04:16:59Z",
      "latest_release_tag": "v0.1.4",
      "releases_from_tags": false,
      "days_since_last_push": 4,
      "active_weeks_last_year": 12,
      "days_since_latest_release": 30,
      "mean_days_between_releases": 2.3
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": false,
      "has_contributing": true,
      "health_percentage": 57,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@agentstate/sdk",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "ai-agents",
            "agent-memory",
            "conversation-history",
            "langgraph",
            "vercel-ai-sdk",
            "mcp",
            "agent-state",
            "cloudflare-workers"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@agentstate/sdk",
          "is_deprecated": false,
          "latest_version": "0.1.4",
          "repository_url": "https://github.com/duyet/agentstate",
          "versions_count": 5,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 8052,
          "first_published_at": "2026-06-06T13:16:15.400000Z",
          "latest_published_at": "2026-07-17T03:41:11.417000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 4
        },
        {
          "name": "agentstate",
          "exists": true,
          "license": null,
          "keywords": [
            "ai",
            "agents",
            "state",
            "management",
            "firebase",
            "persistent",
            "storage",
            "real-time",
            "Development Status :: 5 - Production/Stable",
            "Intended Audience :: Developers",
            "License :: OSI Approved :: MIT License",
            "Operating System :: OS Independent",
            "Programming Language :: Python :: 3",
            "Programming Language :: Python :: 3.10",
            "Programming Language :: Python :: 3.11",
            "Programming Language :: Python :: 3.12",
            "Programming Language :: Python :: 3.9",
            "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
            "Topic :: Scientific/Engineering :: Artificial Intelligence",
            "Topic :: Software Development :: Libraries :: Python Modules"
          ],
          "ecosystem": "pypi",
          "matches_repo": false,
          "registry_url": "https://pypi.org/project/agentstate/",
          "is_deprecated": false,
          "latest_version": "1.0.2",
          "repository_url": "https://github.com/ayushmi/agentstate",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2025-08-21T13:55:17.347539Z",
          "latest_published_at": "2025-08-22T19:22:03.621675Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 333
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 2,
      "watchers": 0,
      "fork_history": {
        "days": [
          {
            "date": "2026-03-30",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": {
        "days": [
          {
            "date": "2026-06-05",
            "count": 1
          },
          {
            "date": "2026-06-15",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 2,
        "total_stars": 2
      },
      "open_issues_and_prs": 27
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples",
        "recipes"
      ],
      "has_llms_txt": true,
      "has_dockerfile": false,
      "has_mcp_signal": true,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "examples/fleet-leases/tsconfig.json",
        "packages/api/tsconfig.json",
        "packages/dashboard/tsconfig.json",
        "packages/mcp/tsconfig.json",
        "packages/sdk/tsconfig.json",
        "packages/shared/tsconfig.json",
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 65759,
      "source_files_sampled": 321,
      "oversized_source_files": 1,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md",
        "packages/api/src/content/agents.md",
        "packages/dashboard/public/agents.md"
      ],
      "agent_instruction_max_bytes": 19307
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [],
        "collected": true,
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 5,
        "assessed_package": "pypi:agentstate@1.0.2",
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@clerk/backend",
          "manifest": "packages/api/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.7.0"
        },
        {
          "name": "drizzle-orm",
          "manifest": "packages/api/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.45.2"
        },
        {
          "name": "hono",
          "manifest": "packages/api/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.12.21"
        },
        {
          "name": "nanoid",
          "manifest": "packages/api/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.1.0"
        },
        {
          "name": "zod",
          "manifest": "packages/api/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.24.0"
        },
        {
          "name": "zod-to-json-schema",
          "manifest": "packages/api/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.25.2"
        },
        {
          "name": "@agentstate/shared",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@clerk/react",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.6.6"
        },
        {
          "name": "@fontsource-variable/hanken-grotesk",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.2.8"
        },
        {
          "name": "@fontsource-variable/jetbrains-mono",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.2.6"
        },
        {
          "name": "@fontsource-variable/space-grotesk",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.2.8"
        },
        {
          "name": "@phosphor-icons/react",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.10"
        },
        {
          "name": "clsx",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.1"
        },
        {
          "name": "echarts",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.1.0"
        },
        {
          "name": "motion",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^12.38.0"
        },
        {
          "name": "next-themes",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.4.6"
        },
        {
          "name": "react",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "19.2.7"
        },
        {
          "name": "react-dom",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "19.2.7"
        },
        {
          "name": "react-markdown",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.1.0"
        },
        {
          "name": "remark-gfm",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.0.1"
        },
        {
          "name": "sonner",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.0.7"
        },
        {
          "name": "tailwind-merge",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.5.0"
        },
        {
          "name": "tw-animate-css",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.4.0"
        },
        {
          "name": "zod",
          "manifest": "packages/dashboard/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.4.3"
        },
        {
          "name": "@modelcontextprotocol/sdk",
          "manifest": "packages/mcp/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.29.0"
        },
        {
          "name": "zod",
          "manifest": "packages/mcp/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.25"
        },
        {
          "name": "httpx",
          "manifest": "packages/python-sdk/pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.28.1"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "@clerk/backend",
            "direct": true,
            "version": "^3.7.0",
            "ecosystem": "npm"
          },
          {
            "name": "@clerk/react",
            "direct": true,
            "version": "^6.6.6",
            "ecosystem": "npm"
          },
          {
            "name": "@fontsource-variable/hanken-grotesk",
            "direct": true,
            "version": "^5.2.8",
            "ecosystem": "npm"
          },
          {
            "name": "@fontsource-variable/jetbrains-mono",
            "direct": true,
            "version": "^5.2.6",
            "ecosystem": "npm"
          },
          {
            "name": "@fontsource-variable/space-grotesk",
            "direct": true,
            "version": "^5.2.8",
            "ecosystem": "npm"
          },
          {
            "name": "@modelcontextprotocol/sdk",
            "direct": true,
            "version": "^1.29.0",
            "ecosystem": "npm"
          },
          {
            "name": "@phosphor-icons/react",
            "direct": true,
            "version": "^2.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "clsx",
            "direct": true,
            "version": "^2.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "drizzle-orm",
            "direct": true,
            "version": "^0.45.2",
            "ecosystem": "npm"
          },
          {
            "name": "echarts",
            "direct": true,
            "version": "^6.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "hono",
            "direct": true,
            "version": "^4.12.21",
            "ecosystem": "npm"
          },
          {
            "name": "motion",
            "direct": true,
            "version": "^12.38.0",
            "ecosystem": "npm"
          },
          {
            "name": "nanoid",
            "direct": true,
            "version": "^5.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "next-themes",
            "direct": true,
            "version": "^0.4.6",
            "ecosystem": "npm"
          },
          {
            "name": "react",
            "direct": true,
            "version": "19.2.7",
            "ecosystem": "npm"
          },
          {
            "name": "react-dom",
            "direct": true,
            "version": "19.2.7",
            "ecosystem": "npm"
          },
          {
            "name": "react-markdown",
            "direct": true,
            "version": "^10.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "remark-gfm",
            "direct": true,
            "version": "^4.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "sonner",
            "direct": true,
            "version": "^2.0.7",
            "ecosystem": "npm"
          },
          {
            "name": "tailwind-merge",
            "direct": true,
            "version": "^3.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "tw-animate-css",
            "direct": true,
            "version": "^1.4.0",
            "ecosystem": "npm"
          },
          {
            "name": "zod",
            "direct": true,
            "version": "^3.24.0",
            "ecosystem": "npm"
          },
          {
            "name": "zod",
            "direct": true,
            "version": "^3.25",
            "ecosystem": "npm"
          },
          {
            "name": "zod",
            "direct": true,
            "version": "^4.4.3",
            "ecosystem": "npm"
          },
          {
            "name": "zod-to-json-schema",
            "direct": true,
            "version": "^3.25.2",
            "ecosystem": "npm"
          },
          {
            "name": "httpx",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "@astrojs/check",
            "direct": false,
            "version": "^0.9.9",
            "ecosystem": "npm"
          },
          {
            "name": "@astrojs/react",
            "direct": false,
            "version": "^6.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "@cloudflare/vitest-pool-workers",
            "direct": false,
            "version": "^0.18.0",
            "ecosystem": "npm"
          },
          {
            "name": "@cloudflare/workers-types",
            "direct": false,
            "version": "^5.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "@langchain/core",
            "direct": false,
            "version": "^1.1.49",
            "ecosystem": "npm"
          },
          {
            "name": "@langchain/langgraph-checkpoint",
            "direct": false,
            "version": "^1.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "@resvg/resvg-js",
            "direct": false,
            "version": "^2.6.2",
            "ecosystem": "npm"
          },
          {
            "name": "@rollup/rollup-linux-x64-gnu",
            "direct": false,
            "version": "^4.60.0",
            "ecosystem": "npm"
          },
          {
            "name": "@tailwindcss/vite",
            "direct": false,
            "version": "^4.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "@types/node",
            "direct": false,
            "version": "^26.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "@types/react",
            "direct": false,
            "version": "^19",
            "ecosystem": "npm"
          },
          {
            "name": "@types/react-dom",
            "direct": false,
            "version": "^19",
            "ecosystem": "npm"
          },
          {
            "name": "astro",
            "direct": false,
            "version": "^7.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "drizzle-kit",
            "direct": false,
            "version": "^0.31.10",
            "ecosystem": "npm"
          },
          {
            "name": "esbuild",
            "direct": false,
            "version": "0.28.1",
            "ecosystem": "npm"
          },
          {
            "name": "shadcn",
            "direct": false,
            "version": "^4.10.0",
            "ecosystem": "npm"
          },
          {
            "name": "tailwindcss",
            "direct": false,
            "version": "^4",
            "ecosystem": "npm"
          },
          {
            "name": "tsup",
            "direct": false,
            "version": "^8.5.1",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "^5",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "^5.7.0",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "^5.9.3",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "^6.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "vitest",
            "direct": false,
            "version": "^4.1.6",
            "ecosystem": "npm"
          },
          {
            "name": "vitest",
            "direct": false,
            "version": "^4.1.9",
            "ecosystem": "npm"
          },
          {
            "name": "wrangler",
            "direct": false,
            "version": "^4.93.0",
            "ecosystem": "npm"
          },
          {
            "name": "langgraph",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "langgraph-checkpoint",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pytest",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pytest-asyncio",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "respx",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "setuptools",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 57,
        "direct_count": 26,
        "indirect_count": 31
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 2,
        "merged_prs": 259,
        "open_issues": 25,
        "closed_ratio": 0.777,
        "closed_issues": 87,
        "closed_unmerged_prs": 18
      },
      "bus_factor": 1,
      "bot_contributors": 3,
      "top_contributors": [
        {
          "type": "User",
          "login": "duyet",
          "commits": 255,
          "avatar_url": "https://avatars.githubusercontent.com/u/5009534?v=4"
        },
        {
          "type": "User",
          "login": "claude",
          "commits": 156,
          "avatar_url": "https://avatars.githubusercontent.com/u/81847?v=4"
        },
        {
          "type": "User",
          "login": "duyetbot",
          "commits": 14,
          "avatar_url": "https://avatars.githubusercontent.com/u/101855044?v=4"
        }
      ],
      "contributors_sampled": 3,
      "top_contributor_share": 0.6
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "publish-sdk.yml",
        "release-please.yml",
        "release.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        "biome.json"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 2/27 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 5 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "28 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "9a12ed2e8c11f61bc1e42471c4b1c60b5182cb34",
        "ran_at": "2026-07-21T21:26:06Z",
        "aggregate_score": 4.8,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": false
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/duyet/agentstate",
    "host": "github.com",
    "name": "agentstate",
    "owner": "duyet"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 66,
      "inputs": {
        "security": 58,
        "vitality": 79,
        "community": 41,
        "governance": 65,
        "engineering": 82
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 79,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 72,
            "inputs": {
              "commits_last_year": 452,
              "human_commit_share": 0.92,
              "days_since_last_push": 4,
              "active_weeks_last_year": 12
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 4 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "12/52 weeks with commits",
                "points": 8.3,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 12
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "452 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 452
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 4,
              "latest_release_tag": "v0.1.4",
              "releases_from_tags": false,
              "days_since_latest_release": 30,
              "mean_days_between_releases": 2.3
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "4 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 30 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~2.3 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 2.3
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 41,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 1,
              "stars": 2,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "below_threshold"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "2 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "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": 65,
            "inputs": {
              "packages": [
                "@agentstate/sdk"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 8052
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "8,052 downloads/month across npm",
                "points": 52.1,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 8052,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "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": 65,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 32,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 3,
              "top_contributor_share": 0.6
            },
            "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 60% of commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 60
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "3 contributors",
                "points": 4.1,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 72,
            "inputs": {
              "merged_prs": 259,
              "open_issues": 25,
              "closed_issues": 87,
              "issue_closed_ratio": 0.777,
              "closed_unmerged_prs": 18
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "78% of issues closed",
                "points": 36.3,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 78
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "259/277 decided PRs merged",
                "points": 35.8,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 259,
                      "decided": 277
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 2/27 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "good",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 70,
            "inputs": {
              "followers": 814,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "duyet",
              "public_repos": 544,
              "account_age_days": 4754
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "814 followers of duyet",
                "points": 20.9,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 814,
                      "login": "duyet"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "544 public repos, account ~13 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 544
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 13
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@agentstate/sdk"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 4
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 4 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "5 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "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": "good",
        "name": "Engineering Quality",
        "value": 82,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "4 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "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": "biome.json",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "biome.json"
                    }
                  }
                ],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": "https://agentstate.app",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": false
            },
            "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://agentstate.app",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": "moderate",
        "name": "Security",
        "value": 58,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": null,
            "notes": [],
            "value": 48,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 18,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 0,
              "scorecard_aggregate": 4.8
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 2/27 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "28 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): No advisories left outstanding. Remaining weights renormalized. Matched the pypi:agentstate@1.0.2 runtime dependency closure — what installing the published package pulls in — 5 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "pypi:agentstate@1.0.2",
                  "assessed": 5
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 0,
              "affected_packages": 0,
              "assessed_packages": 5,
              "unassessed_packages": 0,
              "affected_by_severity": "none",
              "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": "no indirect dependency carries a known advisory",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "no_indirect_advisories",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 5,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 3
            },
            "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": 76,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "has_llms_txt": true,
              "legible_history_share": 0.989,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md",
                "packages/api/src/content/agents.md",
                "packages/dashboard/public/agents.md"
              ],
              "agent_instruction_max_bytes": 19307
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md, packages/api/src/content/agents.md, packages/dashboard/public/agents.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md, packages/api/src/content/agents.md, packages/dashboard/public/agents.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": "91 of 92 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 91,
                      "sampled": 92
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 54,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "examples/fleet-leases/tsconfig.json",
                "packages/api/tsconfig.json",
                "packages/dashboard/tsconfig.json",
                "packages/mcp/tsconfig.json",
                "packages/sdk/tsconfig.json",
                "packages/shared/tsconfig.json",
                "tsconfig.json"
              ],
              "agent_commit_share": 0.01,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0.07
            },
            "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": "biome.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "biome.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "examples/fleet-leases/tsconfig.json, packages/api/tsconfig.json, packages/dashboard/tsconfig.json, packages/mcp/tsconfig.json, packages/sdk/tsconfig.json, packages/shared/tsconfig.json, tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples/fleet-leases/tsconfig.json, packages/api/tsconfig.json, packages/dashboard/tsconfig.json, packages/mcp/tsconfig.json, packages/sdk/tsconfig.json, packages/shared/tsconfig.json, tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "1 of the last 100 commits agent-authored or agent-credited",
                "points": 2,
                "status": "partial",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 1,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "7 of the last 100 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 7,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 65759,
              "source_files_sampled": 321,
              "oversized_source_files": 1
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "1/321 source files over 60KB",
                "points": 54.8,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 321,
                      "oversized": 1
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "moderate",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "example_dirs": [
                "examples",
                "recipes"
              ],
              "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": "examples, recipes",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples, recipes"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Could not fetch npm package '@agentstate/mcp' from its registry",
    "pypi package 'agentstate' points at a different repository (https://github.com/ayushmi/agentstate); excluded from ecosystem scoring"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-21T21:26:25.528564Z",
  "schema_version": "0.23.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/d/duyet/agentstate.svg",
  "full_name": "duyet/agentstate",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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