Публічний реєстр
Звіт про здоров'я програмного забезпеченнясхема 0.23.0 · метрики 1.13.0 · 2026-07-21 21:26 UTC

duyet / agentstate

TypeScriptMIT★ 2 зірки⑂ 1 форкз бер. 2026 р.Переглянути на GitHub ↗

duyet/agentstate має індекс здоров’я 66 зі 100, що відповідає смузі «Помірний». Найвищий показник — Engineering Quality (82/100), найнижчий — Community & Adoption (41/100). Останнє оновлення було 4 дні тому. Більшість нещодавньої роботи виконує один учасник.

66
загалом / 100
Помірний

Індекс здоров'я програмного забезпечення

Метрики згруповано у зважені категорії на шкалі 1–100. Загальна оцінка починається як їхнє середнє; коли публічні дані активують Політику юрисдикцій високого ризику, рейтинг коригується й отримує верхню межу 49 («Під ризиком»). Готовність до ШІ не входить до індексу.

66
Відмінний85-100Зразковий; відповідає практично всім перевіреним критеріям
Добрий70-84Здоровий; незначні прогалини
Помірний50-69Прийнятний, але з помітними прогалинами; рекомендовано перевірку
У зоні ризику30-49Суттєві слабкі місця; впровадження потребує обережності
Критичний1-29Серйозні проблеми (покинутий, єдиний мейнтейнер, без базової гігієни)
ЖиттєздатністьСпільнота тавпровадженняСталість таврядуванняІнженернаякістьБезпекаГотовність доШІ

Профіль оцінок

Кожна вісь — окрема категорія. Форма важить більше, ніж середнє: здоровий об'єкт заповнює всю фігуру, тоді як профіль із піками та провалами означає, що сила в одному вимірі маскує ризик в іншому.

Власність

duyetОсобистий обліковий запис
814 підписників544 публічні репозиторіїз лип. 2013 р.

Цей репозиторій належить особистому обліковому запису. Проєкт з єдиним власником несе більший ризик безперервності, ніж підтримуваний організацією.

Пакетні екосистеми

РеєстрПакетВерсіяЗавантажень / місВерсіїОстання публікаціяТеги
npm@agentstate/sdk0.1.48 05254 дні томуai-agentsagent-memoryconversation-historylanggraphvercel-ai-sdkmcpagent-statecloudflare-workers
PyPIagentstateвказує на інший репозиторій — не оцінюється1.0.2-3333 дні томуaiagentsstatemanagementfirebasepersistentstoragereal-time

Метрики за категоріями

Життєздатність

Чи живий проєкт — чи пишеться код і чи виходять релізи?

79Добрий · 22% загального індексу
Як обчислюється оцінка
36/36Свіжість push — останній push 4 дн. тому
8.3/36Ритм комітів — 12/52 тижнів із комітами
18/18Обсяг комітів — 452 комітів за останній рік
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
Використані вхідні дані
commits_last_year452
human_commit_share0,92
days_since_last_push4
active_weeks_last_year12
Як обчислюється оцінка
27/27Випускає релізи — опубліковано 4 релізів
36/36Свіжість релізів — останній реліз 30 дн. тому
27/27Ритм релізів — реліз кожні ~2,3 дн.
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Використані вхідні дані
releases_count4
latest_release_tagv0.1.4
releases_from_tagsні
days_since_latest_release30
mean_days_between_releases2,3

Спільнота та впровадження

Чи має проєкт користувачів, завантаження, увагу та влаштовані умови для контриб’юторів?

41У зоні ризику · 18% загального індексу
Як обчислюється оцінка
0/60Зірки — 2 зірок
0/25Форки — 1 форків
0/15Спостерігачі — 0 спостерігачів
Використані вхідні дані
forks1
stars2
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonbelow_threshold
Як обчислюється оцінка
22.5/22.5README
22.5/22.5Ліцензія — визнана ліцензія (MIT)
18/18Настанови CONTRIBUTING
0/13.5Кодекс поведінки
0/7.2Шаблон issue
0/6.3Шаблон PR
Використані вхідні дані
has_readmeтак
has_licenseтак
has_contributingтак
has_issue_templateні
has_code_of_conductні
has_pull_request_templateні
Як обчислюється оцінка
52.1/80Щомісячні завантаження — 8 052 завантажень/місяць у npm
0/20Залежні пакети в реєстрі — ця екосистема цього не повідомляє
Використані вхідні дані
packages@agentstate/sdk
dependents
ecosystemsnpm
total_downloads
monthly_downloads8 052
Виключено з оцінювання (немає даних або не застосовно): Залежні пакети в реєстрі. Залишкові ваги перенормовано.

Сталість та врядування

Чи переживе проєкт своїх людей — бас-фактор, реактивність, хто за ним стоїть і як супроводжуються пакети?

65Помірний · 24% загального індексу
Як обчислюється оцінка
9/54Бас-фактор — на 1 контриб’ютор(ів) припадає половина всіх комітів
9/22.5Розподіл комітів — головний контриб’ютор — автор 60% комітів
4.1/13.5Широта контриб’юторів — 3 контриб’юторів
10/10OpenSSF Scorecard: Contributors — project has 5 contributing companies or organizations
Використані вхідні дані
bus_factor1
contributors_sampled3
top_contributor_share0,6
Як обчислюється оцінка
36.3/46.8Вирішення issue — закрито 78% issue
35.8/38.3Прийняття PR — злито 259/277 вирішених PR
0/15OpenSSF Scorecard: Code-Review — Found 2/27 approved changesets -- score normalized to 0
Використані вхідні дані
merged_prs259
open_issues25
closed_issues87
issue_closed_ratio0,777
closed_unmerged_prs18
Як обчислюється оцінка
10/30Підтримка власника — особистий (користувацький) обліковий запис
0/20Верифікований домен — не застосовно до користувацьких облікових записів
20.9/25Охоплення власника — 814 підписників у duyet
25/25Послужний список — 544 публічних репозиторіїв, вік облікового запису ~13 р.
Використані вхідні дані
followers814
owner_typeUser
is_verified
owner_loginduyet
public_repos544
account_age_days4 754
Виключено з оцінювання (немає даних або не застосовно): Верифікований домен. Залишкові ваги перенормовано.

Супровід пакетів

100Відмінний
Як обчислюється оцінка
25/25Опубліковано й доступно — 1 пакет(ів) у npm
35/35Свіжість публікацій — остання публікація 4 дн. тому
20/20Історія версій — 5 опублікованих версій
20/20Не застарілий — активний, не deprecated і не yanked
Використані вхідні дані
packages@agentstate/sdk
ecosystemsnpm
any_deprecatedні
min_days_since_publish4

Інженерна якість

Чи наявні базові інженерні практики та документація?

82Добрий · 20% загального індексу
Як обчислюється оцінка
24/24Процеси CI — 4 процес(ів) CI
24/24Наявні тести
16/16Конфігурація лінтера — biome.json
0/9.6Pre-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
Використані вхідні дані
has_ciтак
has_testsтак
has_editorconfigні
has_linter_configтак
has_precommit_configні
Як обчислюється оцінка
30/30README
25/25Каталог документації
15/15Сайт документації / домашня сторінка — https://agentstate.app
0/10Опис репозиторію
0/10Теми
10/10Wiki
Використані вхідні дані
topics
has_wikiтак
homepagehttps://agentstate.app
has_readmeтак
has_docs_dirтак
has_descriptionні

Безпека

Чи міцні видимі практики безпеки й ланцюга постачання, без непослабленої пов’язаності з юрисдикціями високого ризику?

58Помірний · 16% загального індексу

Стан безпеки

48У зоні ризику
Як обчислюється оцінка
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.5Ліцензія — 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
Використані вхідні дані
sourceopenssf_scorecard
checks_evaluated18
scorecard_versionv5.5.0
checks_inconclusive0
scorecard_aggregate4,8
Як обчислюється оцінка
35/35Прямі залежності без відомих сповіщень — жодна пряма залежність не має відомих сповіщень
25/25Непрямі залежності без відомих сповіщень — жодна непряма залежність не має відомих сповіщень
0/40Немає задавнених сповіщень — жодне сповіщення не має дати публікації
Використані вхідні дані
sourceosv
advisories0
affected_packages0
assessed_packages5
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
Виключено з оцінювання (немає даних або не застосовно): Немає задавнених сповіщень. Залишкові ваги перенормовано. Звірено з runtime-замиканням залежностей pypi:agentstate@1.0.2 — тим, що тягне за собою встановлення опублікованого пакета, — 5 пакетів. Досяжність не аналізується.

Готовність до ШІ

Наскільки репозиторій оснащений для розробки та супроводу за участі ШІ-агентів? Незалежний, експериментальний бейдж — вага 0.0, тож він подається окремо і не впливає на загальний індекс здоров'я.

76Добрий · 0% загального індексу
Як обчислюється оцінка
45/45Інструкції для агентів — AGENTS.md, CLAUDE.md, packages/api/src/content/agents.md, packages/dashboard/public/agents.md
15/15Машиночитана документація (llms.txt) — llms.txt наявний
40/40Читабельна історія комітів — намір зазначено у 91 з 92 людських комітів (структурований заголовок або пояснювальний текст)
Використані вхідні дані
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
Як обчислюється оцінка
0/18Розгортання однією командою
22/22Автоматизовані тести
11/11Конфігурація лінтера / форматера — biome.json
11/11Статична перевірка типів — 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/10Відтворюване середовище
2/10Підтверджена практика роботи з агентами — 1 з останніх 100 комітів створено агентом або з його зазначенням
8/8Автоматизоване супроводження — 7 з останніх 100 комітів — автоматичні оновлення залежностей
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Використані вхідні дані
has_nixні
has_testsтак
lockfiles
has_dockerfileні
typed_languageтак
bootstrap_files
has_devcontainerні
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
Як обчислюється оцінка
45/45Типізований код — TypeScript (статично типізована)
54.8/55Керовані розміри файлів — 1/321 файлів вихідного коду понад 60 КБ
Використані вхідні дані
primary_languageTypeScript
largest_source_bytes65 759
source_files_sampled321
oversized_source_files1
Як обчислюється оцінка
0/40Схема API (OpenAPI/GraphQL/proto)
20/20Сервер MCP
40/40Придатні до запуску приклади — examples, recipes
Використані вхідні дані
example_dirsexamples, recipes
has_mcp_signalтак
api_schema_files

Ключові факти

2зірок GitHub
3контриб'юторів
452комітів за останні 12 місяців
4днів від останнього пушу
4релізів
1бас-фактор
25відкритих issue
npmпакетних екосистем

Попередження щодо збору даних

  • 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

Докладніше

Історія зірок і форків 2 ★ / 1 ⇿
2Зірки
1Форки
2Релізи

Коли додано кожну зірку й форк — зібрано з GitHub і згруповано за днями. Кумулятивне зростання розміщено просто над денними додаваннями, з яких воно складається, тож їх видно одне проти одного: рівномірне органічне накопичення виглядає зовсім інакше, ніж різкий короткочасний сплеск. Там, де цю різницю можна виміряти, її подано як автентичність росту.

0011222112026-032026-052026-06
Мажорні 0Мінорні 0Патчі 2
OpenSSF Scorecard 4.8 / 10
4.8сукупно

Незалежна, не прив'язана до інструментів оцінка безпеки від відкритого проєкту OpenSSF Scorecard. Кожна перевірка винагороджує практику безпеки, а не інструмент конкретного постачальника. Перевірки, які Scorecard не зміг визначити, позначено н/д і виключено з оцінки безпеки (вони ніколи не зараховуються як нуль).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
Прямі залежності 27
РеєстрПакетОбмеження версіїМаніфест
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
Усі залежності 57

Повний розв'язаний набір залежностей із графа залежностей GitHub: 26 прямих і 31 непрямих (транзитивних) пакетів. Транзитивне замикання є повним, коли в репозиторії закомічено lockfile.

РеєстрПакетВерсіяЗв'язок
npm@clerk/backend^3.7.0пряма
npm@clerk/react^6.6.6пряма
npm@fontsource-variable/hanken-grotesk^5.2.8пряма
npm@fontsource-variable/jetbrains-mono^5.2.6пряма
npm@fontsource-variable/space-grotesk^5.2.8пряма
npm@modelcontextprotocol/sdk^1.29.0пряма
npm@phosphor-icons/react^2.1.10пряма
npmclsx^2.1.1пряма
npmdrizzle-orm^0.45.2пряма
npmecharts^6.1.0пряма
npmhono^4.12.21пряма
npmmotion^12.38.0пряма
npmnanoid^5.1.0пряма
npmnext-themes^0.4.6пряма
npmreact19.2.7пряма
npmreact-dom19.2.7пряма
npmreact-markdown^10.1.0пряма
npmremark-gfm^4.0.1пряма
npmsonner^2.0.7пряма
npmtailwind-merge^3.5.0пряма
npmtw-animate-css^1.4.0пряма
npmzod^3.24.0пряма
npmzod^3.25пряма
npmzod^4.4.3пряма
npmzod-to-json-schema^3.25.2пряма
PyPIhttpxпряма
npm@astrojs/check^0.9.9непряма
npm@astrojs/react^6.0.0непряма
npm@cloudflare/vitest-pool-workers^0.18.0непряма
npm@cloudflare/workers-types^5.0.0непряма
npm@langchain/core^1.1.49непряма
npm@langchain/langgraph-checkpoint^1.1.1непряма
npm@resvg/resvg-js^2.6.2непряма
npm@rollup/rollup-linux-x64-gnu^4.60.0непряма
npm@tailwindcss/vite^4.3.0непряма
npm@types/node^26.0.0непряма
npm@types/react^19непряма
npm@types/react-dom^19непряма
npmastro^7.0.0непряма
npmdrizzle-kit^0.31.10непряма
npmesbuild0.28.1непряма
npmshadcn^4.10.0непряма
npmtailwindcss^4непряма
npmtsup^8.5.1непряма
npmtypescript^5непряма
npmtypescript^5.7.0непряма
npmtypescript^5.9.3непряма
npmtypescript^6.0.3непряма
npmvitest^4.1.6непряма
npmvitest^4.1.9непряма
npmwrangler^4.93.0непряма
PyPIlanggraphнепряма
PyPIlanggraph-checkpointнепряма
PyPIpytestнепряма
PyPIpytest-asyncioнепряма
PyPIrespxнепряма
PyPIsetuptoolsнепряма
Сповіщення про залежності 0

Встановлення pypi:agentstate@1.0.2 тягне 5 пакетів, прямих і транзитивних: 0 мають відомі сповіщення, з них 0 — прямі залежності.

Жодне відоме сповіщення не стосується оцінених залежностей.

Сповіщення означає, що версія, записана в графі залежностей, потрапляє в уражений діапазон. Досяжність не аналізується, а граф містить піниї розробки й тестування — знахідка може стосуватися інструментів, а не поставленого коду.

Звіт у форматі JSON машиночитний
{
  "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"
}

Оцінки — це сигнали, а не гарантії. Вони відображають публічно видимі практики на GitHub — це не аудит коду й не гарантія безпеки.

Відсутні дані виключаються, а ваги перенормовуються — нуль за відсутність ніколи не ставиться. Методологія версіонована й відкрита: метрики v1.13.0, схема v0.23.0 — повна методологія · вікі метрик.

Як окремий результат виглядає на тлі всього реєстру: сукупна статистикаnpm, PyPI.