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

Foorack / kumidocs

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

Foorack/kumidocs має індекс здоров’я 53 зі 100, що відповідає смузі «Помірний». Найвищий показник — AI Readiness (66/100), найнижчий — Community & Adoption (36/100). Останнє оновлення було 6 днів тому. Більшість нещодавньої роботи виконує один учасник.

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

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

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

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

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

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

Власність

Foorack / Max FaxälvОсобистий обліковий запис
58 підписників80 публічних репозиторіївз лип. 2013 р.Sony Group Corporation

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

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

РеєстрПакетВерсіяЗавантажень / місВерсіїОстання публікаціяТеги
npmkumidocs0.20260720.1568 9971396 днів томуwikidocsmarkdowngitbunself-hosted

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

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

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

45У зоні ризику · 22% загального індексу
Як обчислюється оцінка
36/36Свіжість push — останній push 6 дн. тому
9.7/36Ритм комітів — 14/52 тижнів із комітами
18/18Обсяг комітів — 836 комітів за останній рік
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
Використані вхідні дані
commits_last_year836
human_commit_share1
days_since_last_push6
active_weeks_last_year14
Як обчислюється оцінка
0/27Випускає релізи — релізів не опубліковано
0/36Свіжість релізів — релізів немає
0/27Ритм релізів — релізів немає
0/10OpenSSF Scorecard: Signed-Releases — немає даних
Використані вхідні дані
releases_count0
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: Signed-Releases. Залишкові ваги перенормовано.

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

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

36У зоні ризику · 18% загального індексу
Як обчислюється оцінка
4.9/60Зірки — 3 зірок
0/25Форки — 2 форків
0/15Спостерігачі — 1 спостерігачів
Використані вхідні дані
forks2
stars3
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Як обчислюється оцінка
22.5/22.5README
22.5/22.5Ліцензія — визнана ліцензія (MIT)
0/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.7/80Щомісячні завантаження — 8 997 завантажень/місяць у npm
0/20Залежні пакети в реєстрі — ця екосистема цього не повідомляє
Використані вхідні дані
packageskumidocs
dependents
ecosystemsnpm
total_downloads
monthly_downloads8 997
Виключено з оцінювання (немає даних або не застосовно): Залежні пакети в реєстрі. Залишкові ваги перенормовано.

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

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

63Помірний · 24% загального індексу
Як обчислюється оцінка
9/54Бас-фактор — на 1 контриб’ютор(ів) припадає половина всіх комітів
0/22.5Розподіл комітів — головний контриб’ютор — автор 100% комітів
2.7/13.5Широта контриб’юторів — 2 контриб’юторів
10/10OpenSSF Scorecard: Contributors — project has 5 contributing companies or organizations
Використані вхідні дані
bus_factor1
contributors_sampled2
top_contributor_share0,999
Як обчислюється оцінка
46.8/46.8Вирішення issue — закрито 100% issue
38.2/38.3Прийняття PR — злито 6/6 вирішених PR
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Використані вхідні дані
merged_prs6
open_issues0
closed_issues1
issue_closed_ratio1
closed_unmerged_prs0
Як обчислюється оцінка
10/30Підтримка власника — особистий (користувацький) обліковий запис
0/20Верифікований домен — не застосовно до користувацьких облікових записів
12.7/25Охоплення власника — 58 підписників у Foorack
25/25Послужний список — 80 публічних репозиторіїв, вік облікового запису ~13 р.
Використані вхідні дані
followers58
owner_typeUser
is_verified
owner_loginFoorack
public_repos80
account_age_days4 759
Виключено з оцінювання (немає даних або не застосовно): Верифікований домен. Залишкові ваги перенормовано.

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

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

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

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

58Помірний · 20% загального індексу
Як обчислюється оцінка
24/24Процеси CI — 1 процес(ів) CI
24/24Наявні тести
0/16Конфігурація лінтера
0/9.6Pre-commit-хуки
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — немає даних
Використані вхідні дані
has_ciтак
has_testsтак
has_editorconfigні
has_linter_configні
has_precommit_configні
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: CI-Tests. Залишкові ваги перенормовано.

Документація

55Помірний
Як обчислюється оцінка
30/30README
25/25Каталог документації
0/15Сайт документації / домашня сторінка
0/10Опис репозиторію
0/10Теми
0/10Wiki
Використані вхідні дані
topics
has_wikiні
homepage
has_readmeтак
has_docs_dirтак
has_descriptionні

Безпека

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

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

Стан безпеки

58Помірний
Як обчислюється оцінка
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — немає даних
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 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 1 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 — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — немає даних
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
Використані вхідні дані
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate5,8
Виключено з оцінювання (немає даних або не застосовно): ci_tests, signed_releases. Залишкові ваги перенормовано.
Як обчислюється оцінка
14/35Прямі залежності без відомих сповіщень — уражено 1: js-yaml 5.2.1 (high 7.5)
11/25Непрямі залежності без відомих сповіщень — уражено 1: react-router 7.18.0 (high)
40/40Немає задавнених сповіщень — жодне сповіщення не є публічним довше за 90 дн.
Використані вхідні дані
sourceosv
advisories2
affected_packages2
assessed_packages443
unassessed_packages0
affected_by_severityhigh 2
direct_affected_packages1
Звірено з runtime-замиканням залежностей npm:kumidocs@0.20260720.156 — тим, що тягне за собою встановлення опублікованого пакета, — 443 пакетів. Досяжність не аналізується.

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

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

66Помірний · 0% загального індексу
Як обчислюється оцінка
45/45Інструкції для агентів — AGENTS.md
0/15Машиночитана документація (llms.txt)
34.7/40Читабельна історія комітів — намір зазначено у 65 з 100 людських комітів (структурований заголовок або пояснювальний текст)
Використані вхідні дані
has_llms_txtні
legible_history_share0,65
agent_instruction_filesAGENTS.md
agent_instruction_max_bytes10 645
Як обчислюється оцінка
0/18Розгортання однією командою
22/22Автоматизовані тести
0/11Конфігурація лінтера / форматера
11/11Статична перевірка типів — tsconfig.json
10/10Відтворюване середовище — Dockerfile
0/10Підтверджена практика роботи з агентами — серед останніх 100 комітів немає створених агентом
0/8Автоматизоване супроводження — автоматичних оновлень залежностей не виявлено
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_configstsconfig.json
agent_commit_share0
toolchain_manifests
dependency_bot_commit_share0
Як обчислюється оцінка
45/45Типізований код — TypeScript (статично типізована)
54.6/55Керовані розміри файлів — 1/150 файлів вихідного коду понад 60 КБ
Використані вхідні дані
primary_languageTypeScript
largest_source_bytes419 910
source_files_sampled150
oversized_source_files1

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

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

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

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token

Докладніше

Історія зірок і форків 0 ★ / 2 ⇿
0Зірки
2Форки

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

111222212026-062026-062026-06
OpenSSF Scorecard 5.8 / 10
5.8сукупно

Незалежна, не прив'язана до інструментів оцінка безпеки від відкритого проєкту OpenSSF Scorecard. Кожна перевірка винагороджує практику безпеки, а не інструмент конкретного постачальника. Перевірки, які Scorecard не зміг визначити, позначено н/д і виключено з оцінки безпеки (вони ніколи не зараховуються як нуль).Scorecard v5.5.0 · 2026-07-26 16:35 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
н/дCI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 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 1 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
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
н/дSigned-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
7Vulnerabilities3 existing vulnerabilities detected
Прямі залежності 41
РеєстрПакетОбмеження версіїМаніфест
npm@dnd-kit/core6.3.1package.json
npm@dnd-kit/sortable10.0.0package.json
npm@dnd-kit/utilities3.2.2package.json
npm@iconify-json/devicon1.2.62package.json
npm@iconify-json/flag1.2.12package.json
npm@iconify-json/fluent-color1.2.21package.json
npm@iconify-json/glyphs-poly1.2.0package.json
npm@iconify-json/logos1.2.11package.json
npm@noble/hashes2.2.0package.json
npm@radix-ui/react-label2.1.10package.json
npm@radix-ui/react-select2.3.1package.json
npm@radix-ui/react-slider1.4.2package.json
npm@radix-ui/react-slot1.3.0package.json
npm@streamdown/cjk1.0.3package.json
npm@streamdown/code1.1.1package.json
npm@streamdown/math1.0.2package.json
npm@streamdown/mermaid1.0.2package.json
npmclass-variance-authority0.7.1package.json
npmclsx2.1.1package.json
npmcmdk1.1.1package.json
npmcolor5.0.3package.json
npmdiff9.0.0package.json
npmhtml2canvas-pro2.2.0package.json
npmignore7.0.5package.json
npmjs-yaml5.2.1package.json
npmjspdf4.2.1package.json
npmkhroma2.1.0package.json
npmlinkedom^0.18.13package.json
npmlucide-react1.21.0package.json
npmminisearch7.2.0package.json
npmnext-themes0.4.6package.json
npmradix-ui1.6.0package.json
npmreact19.2.7package.json
npmreact-diff-view3.3.3package.json
npmreact-dom19.2.7package.json
npmreact-router-dom7.18.0package.json
npmrehype-harden1.1.8package.json
npmsonner2.0.7package.json
npmstreamdown2.5.0package.json
npmtailwind-merge3.6.0package.json
npmws8.21.0package.json
Усі залежності 57

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

РеєстрПакетВерсіяЗв'язок
npm@dnd-kit/core6.3.1пряма
npm@dnd-kit/sortable10.0.0пряма
npm@dnd-kit/utilities3.2.2пряма
npm@iconify-json/devicon1.2.62пряма
npm@iconify-json/flag1.2.12пряма
npm@iconify-json/fluent-color1.2.21пряма
npm@iconify-json/glyphs-poly1.2.0пряма
npm@iconify-json/logos1.2.11пряма
npm@noble/hashes2.2.0пряма
npm@radix-ui/react-label2.1.10пряма
npm@radix-ui/react-select2.3.1пряма
npm@radix-ui/react-slider1.4.2пряма
npm@radix-ui/react-slot1.3.0пряма
npm@streamdown/cjk1.0.3пряма
npm@streamdown/code1.1.1пряма
npm@streamdown/math1.0.2пряма
npm@streamdown/mermaid1.0.2пряма
npmclass-variance-authority0.7.1пряма
npmclsx2.1.1пряма
npmcmdk1.1.1пряма
npmcolor5.0.3пряма
npmdiff9.0.0пряма
npmhtml2canvas-pro2.2.0пряма
npmignore7.0.5пряма
npmjs-yaml5.2.1пряма
npmjspdf4.2.1пряма
npmkhroma2.1.0пряма
npmlinkedom^0.18.13пряма
npmlucide-react1.21.0пряма
npmminisearch7.2.0пряма
npmnext-themes0.4.6пряма
npmradix-ui1.6.0пряма
npmreact19.2.7пряма
npmreact-diff-view3.3.3пряма
npmreact-dom19.2.7пряма
npmreact-router-dom7.18.0пряма
npmrehype-harden1.1.8пряма
npmsonner2.0.7пряма
npmstreamdown2.5.0пряма
npmtailwind-merge3.6.0пряма
npmws8.21.0пряма
npm@tailwindcss/typography0.5.20непряма
npm@types/bun1.3.14непряма
npm@types/color4.2.1непряма
npm@types/node26.0.1непряма
npm@types/react19.2.17непряма
npm@types/react-dom19.2.3непряма
npm@types/ws8.18.1непряма
npm@typescript/native-preview7.0.0-dev.20260626.1непряма
npmbun-plugin-tailwind0.1.2непряма
npmcountry-flag-icons1.6.19непряма
npmoxfmt0.56.0непряма
npmoxlint1.71.0непряма
npmoxlint-tsgolint0.23.0непряма
npmtailwindcss4.3.1непряма
npmtw-animate-css1.4.0непряма
npmtypescript6.0.3непряма
Сповіщення про залежності 2

Встановлення npm:kumidocs@0.20260720.156 тягне 443 пакетів, прямих і транзитивних: 2 мають відомі сповіщення, з них 1 — прямі залежності.

ПакетВерсіяЗв'язокКритичністьСповіщеньВиправлено в
js-yaml5.2.1прямависока15.2.2
react-router7.18.0непрямависока18.3.0

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

Звіт у форматі JSON машиночитний
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 27092,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "CSS": 15941,
        "HTML": 547,
        "TypeScript": 1227859
      },
      "pushed_at": "2026-07-20T11:22:58Z",
      "created_at": "2026-03-06T13:07:56Z",
      "owner_type": "User",
      "updated_at": "2026-07-20T11:23:10Z",
      "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://foorack.com/",
      "name": "Foorack / Max Faxälv",
      "type": "User",
      "login": "Foorack",
      "company": "Sony Group Corporation",
      "location": "European Union, SE/DK",
      "followers": 58,
      "avatar_url": "https://avatars.githubusercontent.com/u/5008081?v=4",
      "created_at": "2013-07-14T18:35:59Z",
      "is_verified": null,
      "public_repos": 80,
      "account_age_days": 4759
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [],
      "recent_commits": [
        {
          "oid": "1c3db31da59b81addde1b3cf900396002e649c18",
          "body": "idb-cache.ts, emoji-loader.ts, and register-mermaid-icons.ts use IndexedDB,\nfetch(), and other browser-only APIs. Kept lib/ for framework-independent\nshared code.",
          "is_bot": false,
          "headline": "refactor: move browser-only modules from lib/ to client/",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-20T09:55:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f1870ecc8b53f0523a5ed0c5cf940a2d0b83a39b",
          "body": "slides/utils.ts was mixing three concerns: slide constants (SLIDE_W/H),\nPDF/DOM overlay logic (document.createTreeWalker, jsPDF), and pure\nfunctions (splitSlides, buildCanvasStyle). Now each has its own file.",
          "is_bot": false,
          "headline": "refactor: split slides/utils.ts into constants.ts and pdf-overlay.ts",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-20T08:28:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "06da6d84c25687382bfdbce4a9df9b3e76b93b81",
          "body": "Adds MAGIC_BYTES constant to filetypes.ts with expected byte signatures\nfor PNG, JPEG, GIF, and WEBP. Upload handler now rejects files whose\ncontent doesn't match their declared extension, preventing extension\nrenaming attacks (e.g. .exe -> .png).",
          "is_bot": false,
          "headline": "feat: validate image upload content via magic bytes",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T19:38:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03f924ae63e07cea542178e6fac3675c8ae31a61",
          "body": "File exported components (ContentArea, buildEditorContent) and type helpers,\nnot pure utilities. New name accurately reflects its contents.",
          "is_bot": false,
          "headline": "refactor: rename file-page/utils.tsx to editor-content.tsx",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T17:34:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "abf5033d262c615289c0e5de705742ce5c626cda",
          "body": "sortedObject wrapped objects in a Proxy to force alphabetical key ordering,\nbut js-yaml's sortKeys: true already sorts keys at every nesting level\nduring dump(). The Proxy was redundant.\n\nAdds bun test infrastructure and a test proving sortKeys: true works\nat all nesting levels.",
          "is_bot": false,
          "headline": "refactor: remove redundant sortedObject Proxy, add YAML sorting tests",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T17:27:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c3ecfac310529bd806cf76788cd4e3635458a4af",
          "body": "Add requireUserOr and requireRateLimitOr helpers to replace 16 copies of\nthe requireUser + rate-limit boilerplate pattern across route handlers.\n\nrequireUserOr: authenticate, return user or 401\nrequireRateLimitOr: authenticate + rate-limit, return user or error response",
          "is_bot": false,
          "headline": "refactor: extract auth guard helpers in router.ts",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T16:25:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "17b02bc4b073836fcef4801c225e86e4b8a13c2c",
          "body": "Function was copy-pasted in both lib/utils.ts and server/api-utils.ts.\nRemoved the server copy and pointed api-file.ts to the canonical lib/utils.ts version.",
          "is_bot": false,
          "headline": "refactor: consolidate duplicated assertJsonObject",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T16:15:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ea7702083aee767a7672223c6345d4188895c631",
          "body": "- Delete unused shadcn card.tsx and textarea.tsx components\n- Remove sendSaveConflict function (zero callers)\n- Remove /api/sidebar route and handler (never consumed by frontend)\n\nRemoves 121 lines.",
          "is_bot": false,
          "headline": "chore: remove dead code",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T15:43:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7fdc8c55a62657b4ce7cedd05565ff6c5322972e",
          "body": null,
          "is_bot": false,
          "headline": "refactor: relocate ticket dialog components to components/dialogs/ticket",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T15:34:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6f34866090402457e0bae43022cda6a76f27b4cd",
          "body": null,
          "is_bot": false,
          "headline": "refactor: centralize allowed background URL prefixes in slide.ts",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T07:01:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59362636ae1013ae29be9e3e935b1d3afa131c0f",
          "body": null,
          "is_bot": false,
          "headline": "fix: handle missing git repository in file GET endpoint",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T06:57:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f715bc73d05ea75467012fbb7682effc43ac2931",
          "body": null,
          "is_bot": false,
          "headline": "fix: log invalid WebSocket messages for debugging",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T06:54:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "34433c7e01eac1d61630e7fd0cbb787dbae58fea",
          "body": null,
          "is_bot": false,
          "headline": "fix: improve email validation in auth endpoint to match RFC 5321",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T06:51:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ec198ddb67098df1748fb8fd10b36db5bb212d59",
          "body": null,
          "is_bot": false,
          "headline": "fix: resolve symlinks in isSafePath to prevent path traversal bypass",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-18T21:36:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae96f58338d892688b37e619c2cbe879b3d5ad42",
          "body": "…ipts",
          "is_bot": false,
          "headline": "feat: add full-page mermaid diagram view and relax CSP for inline scr…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-18T21:12:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83704929dfa0ec1ed74277f955500c99c49f9e43",
          "body": null,
          "is_bot": false,
          "headline": "feat: add mermaid file type with icon and rendering support",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-18T20:46:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7ffb340edd384aebd478b1696cf9c3af70e5e861",
          "body": "Adds ok: true/false discriminant to the return type so callers\nuse proper type narrowing via result.ok instead of fragile\n'error' in result duck-checking.",
          "is_bot": false,
          "headline": "refactor: use discriminated union for duplicatePage return type",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T12:28:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ea4ff6324ec76b5cdf26b91eac00228dfc80841",
          "body": "Replaces the verbose allProps intermediary with direct parameter\ndestructuring in both components.",
          "is_bot": false,
          "headline": "style: destructure children directly in ThemeProvider and Providers",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T10:46:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9b644f0d432f6519b2656c9b491f0a6c4f97730a",
          "body": "Previously returned 'just now' for any future timestamp. Now formats\nfuture dates more usefully (e.g. 'in 3 days') with sub-minute future\ndates still resolving to 'just now' for natural clock skew handling.",
          "is_bot": false,
          "headline": "fix: return 'in X units' for future dates in relativeTime",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T10:36:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c70db494814bab1a265629183279e41281cda818",
          "body": "Adds optional JWT verification using a base64-encoded JWKS passed via\nthe --jwks-base64 CLI flag or KUMIDOCS_JWKS_BASE64 env var. No outbound\nrequests are made -- keys are loaded at startup.\n\n- crypto.createPublicKey with JWK format validates RSA key material\n- Supports RS256, RS384, RS512 algorithms\n- Rejects alg:none, missing kid, unknown kid, and bad signatures\n- Fail-open when no JWKS configured (backward compatible)\n- Exposes jwtKids array in /api/me for client visibility",
          "is_bot": false,
          "headline": "feat: add JWT signature verification via --jwks-base64",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T10:33:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "609f951606a23998fb8c037c20d8d7dc2d29492a",
          "body": "useMountEffect cleanup now calls wsClient.disconnect(), closing the\nWebSocket connection and clearing timers when the component unmounts\n(e.g. on auth state change).",
          "is_bot": false,
          "headline": "fix: disconnect WebSocket on WsConnector unmount",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:50:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7bc875153aea8afdca7779ea2871742107d64028",
          "body": "The ternary rendered <MoreHorizontal /> in both branches regardless\nof dotsHovered/dotsOpen state. Simplified to a direct assignment.\nAlso dropped the unused state reads (now [, setDotsHovered]) since\nonly the setters are still wired to event handlers.",
          "is_bot": false,
          "headline": "fix: remove dead conditional in sidebar dotsIcon",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:49:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57c977fbc1b0667ffbdff1bedfb173e1d470d02a",
          "body": "Adds an isMountedRef that is set to false on unmount. The auto-save\nsetTimeout callback checks this ref before calling doSave, preventing\nstate updates on an unmounted component if the timer was set after\nthe cleanup already ran.",
          "is_bot": false,
          "headline": "fix: prevent auto-save timer from firing after unmount",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:44:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "98141562e87f537885c8dfe885b0b85fc990ea7a",
          "body": "…nt storms\n\nThe key included sidebarDefaultDepth, causing every sidebar node to\nunmount and remount when the config changed, losing all open/close\ntoggle state. node.path alone is unique and stable.",
          "is_bot": false,
          "headline": "fix: remove sidebarDefaultDepth from PageNodeRow key to prevent remou…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:41:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "56a3d3588de856721ec49ba9e0875bfc55bfbe75",
          "body": "The serial save queue caught but silently discarded errors from\nprior saves. Now logs them to console so they're visible during\ndebugging, while still allowing the queue to proceed.",
          "is_bot": false,
          "headline": "fix: log previous save errors in save queue instead of swallowing",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:38:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5bb1a8a1f842ff7b141ce1ab6191037830c40e80",
          "body": "…everywhere\n\nReplaces all three remaining gray-matter usages (filestore.ts, search.ts,\nbacklinks.ts) with the project's own parseFrontmatter from lib/frontmatter.ts.\nRemoves the gray-matter package from dependencies.",
          "is_bot": false,
          "headline": "refactor: remove gray-matter dependency, use custom parseFrontmatter …",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:24:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "645c4e91973f046622debd440543c6180cffcd33",
          "body": "Extracts the common title/path mapping logic into buildWikilinkLookup()\nin lib/wikilinks.ts. Both callers (buildLookupFromTree on the client,\nbuildLookup on the server) now collect page entries from their\nrespective data sources and delegate to the shared function.",
          "is_bot": false,
          "headline": "refactor: deduplicate wikilink lookup logic into shared function",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T07:02:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "60955641c8382a387bf5460a9f09f368649d6c34",
          "body": "Moves assertJsonObject from server/api-utils.ts into lib/utils.ts so both\nclient and server code can use it. Replaces 11 raw as Record<string, unknown>\ncasts across server/api.ts and lib/board.ts with runtime-validated assertions\nthat reject null, arrays, and primitives before treating the value as an object.\n\nAlso replaces as string casts in approval parsing with typeof guards plus\nempty-string fallback to prevent undefined from propagating into string fields.",
          "is_bot": false,
          "headline": "refactor: replace raw as Record casts with assertJsonObject validator",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T06:40:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "551c4306346c4fe51740d7dc8befe315da57af43",
          "body": "Three caches that could grow without bound now have size limits with\noldest-entry eviction:\n\n- ws.ts reopenCallbacks: capped at 100, drops oldest when full\n- emoji-icon.tsx dataUriCache: capped at 500, drops oldest when full\n- api-images.ts avatarCache: capped at 200, drops oldest when full",
          "is_bot": false,
          "headline": "fix: cap unbounded caches with LRU-style eviction",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T06:35:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "faadbcdf313725606bec40e2dfb46a06eee37a9c",
          "body": "Creates ErrorBoundary class component (src/components/ui/error-boundary.tsx)\nthat catches render-time errors in its subtree and shows a fallback UI\nwith a 'Try again' button instead of crashing the whole app.\n\nPlaced around <AppRoutes /> in app.tsx so all route-level pages (markdown\nviewer, board, image library, themes, etc.) are covered while providers\n(theme, user, tooltip) remain outside and survive a page crash.",
          "is_bot": false,
          "headline": "feat: add top-level error boundary to prevent white-screen crashes",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T11:14:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "36fc1a0d815ff54b7af3b45fa70937af85b63b7e",
          "body": "…n sha256Hex\n\ngit-ignore.ts: replace spawnSync/existsSync/readFileSync with async\nalternatives (execFileAsync, fs/promises access/readFile) so startup\nI/O doesn't block the event loop.\n\nruntime.ts: sha256Hex no longer creates intermediate Buffer.from()\ncopies. ArrayBuffer input uses a Uint8Array view directly, string\ninput passes encoding to hash.update(), Buffer input passes through.",
          "is_bot": false,
          "headline": "refactor: convert git-ignore to async I/O and eliminate Buffer copy i…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T10:53:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1475992c77ff45af7c702e2888105e159b4c1186",
          "body": "Previously the timestamp push was separated from the length check by an\nempty-bucket eviction branch, creating a window where two callers could\nobserve the same bucket state. Now the allow path is a single if-block\nthat checks, pushes, and returns with no intervening operations.",
          "is_bot": false,
          "headline": "refactor: make rate limiter check+record atomic in a single pass",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T09:41:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4abfcf816a0736c18c536710619d483bd298d2bb",
          "body": "The old sanitizeSvg used 8 chained .replaceAll() calls to blacklist\ndangerous elements and attributes. This is fundamentally flawed because\nXML is not a regular language -- regex cannot reliably handle CDATA\nsections, HTML entities, namespace tricks, or nested elements.\n\nNow uses linkedom's parseHTM\n[…]\n- Removes javascript:/data: URIs from href, src, action attributes\n- Restricts <use> hrefs to fragment-only references (#id)\n- Returns empty string on parse failure instead of serving un-sanitized SVG",
          "is_bot": false,
          "headline": "security: replace regex-based SVG sanitizer with DOM parser (linkedom)",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T09:32:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6d4eec89e954ab727b565916f9a9340e4b6900ca",
          "body": "…e derivation\n\n- app-shell.tsx: move activeEmails set computation from useEffect into\n  useMemo, leaving the effect only for the external-store sync side effect\n- sidebar-page-node.tsx: replace useEffect for auto-open on navigation\n  with render-time ref-based pattern, removing the useEffect dependency\n\nPer project convention: never useEffect(() => setX(f(y)), [y]);\ncompute inline during render instead.",
          "is_bot": false,
          "headline": "refactor: replace useEffect-derived state with useMemo and render-tim…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T09:11:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bddccd35e0359cf59be1cbfe27dd1650f7997c35",
          "body": null,
          "is_bot": false,
          "headline": "feat: set document title for board list page",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T08:19:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d48ee733583384f45f5206e87073acf4f7901b35",
          "body": null,
          "is_bot": false,
          "headline": "feat: extract shared BoardHeader component for board page headers",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T08:07:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ab2effef965ec62b5250f9de7d3eb147f01152a0",
          "body": null,
          "is_bot": false,
          "headline": "feat: display board icons in ticket create dialog board selector",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T11:25:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9af543f52727fcd7d0d1dfa56be2a92895f451b8",
          "body": "…dex entries",
          "is_bot": false,
          "headline": "fix: wrap discard calls in try-catch to prevent crashes on missing in…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T11:11:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0318e392ec8e8dbeae9e47f11a77e5a04976deb6",
          "body": null,
          "is_bot": false,
          "headline": "fix: ensure consistent key ordering in ticket YAML serialization",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T09:03:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "152155a085fe1cf3ea514db39a2598286fbc48a0",
          "body": null,
          "is_bot": false,
          "headline": "fix: enable sortKeys in ticketToYaml for consistent key ordering",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T06:56:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "04865acb615de45b5cd35224ff33cb03ec47a001",
          "body": null,
          "is_bot": false,
          "headline": "feat: add mode-specific favicons for board and docs views",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T04:25:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3a797a419601567599be38850b809c9c29f6fb93",
          "body": null,
          "is_bot": false,
          "headline": "refactor: use EmojiIcon for home, activity, approval, and version icons",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T14:54:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0d292bb10de7048bdf1c5fd92efa3bf6e10c1893",
          "body": "- Remove redundant value !== undefined check (Headers.get() returns string | null)\n- Move oxlint-disable comment to correct line for request.method ?? \"GET\"\n  defensive fallback (IncomingMessage.method is typed as string)",
          "is_bot": false,
          "headline": "chore: eliminate last two lint warnings in http-server.ts",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T11:33:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90f95bba80f6efe369cfd8f3e93c89a75d98e6f8",
          "body": "This rule catches real ReferenceError bugs with const/let/class access\nbefore initialization. The blanket suppress in http-server.ts was for\nhoisted function declarations (which are safe). No project-wide\nviolations exist -- only 2 inline suppressions in tree-components.tsx.",
          "is_bot": false,
          "headline": "fix: restore eslint/no-use-before-define as active rule",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T10:20:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "75e7d82142f5ed03a2c96bd0b90fc30b65996e50",
          "body": "…ted rules\n\n- Move eslint/id-length and no-use-before-define to .oxlintrc.json (project-wide)\n- Replace 17-rule file-level suppress with focused 8-rule comment for\n  Node/Bun portability patterns only\n- Add inline oxlint-disable-next-line for type assertions that cannot\n  be eliminated (Node EventEm\n[…]\ns DOM patterns, any casts from ws)\n- Remove unnecessary type assertion on route handler lookup\n- Two remaining false-positive warnings on Headers iterator and Record\n  index access (oxlint limitation)",
          "is_bot": false,
          "headline": "refactor: replace blanket oxlint-disable in http-server.ts with targe…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T10:15:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9581a71c9c0315e7bdb338b6e4eee6cd9b98bc8f",
          "body": null,
          "is_bot": false,
          "headline": "refactor: format cn() calls for readability across 11 files",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T09:46:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7ee2de41cfe14dd538f7c98b66d0d0b2548cfae1",
          "body": "…files\n\nEnsures Tailwind class conflicts are resolved by twMerge (inside cn()).\nFiles updated:\n- pages/: board-detail, board/card, file-page/header, image-library/page,\n           ticket/ticket-sidebar, ticket/timeline\n- components/dialogs/: page-action-dialogs\n- components/editor/markdown/: editor, inline-editor, csv-grid\n- components/layout/: app-shell, board-sidebar, sidebar-page-node,\n                      board-filter-bar, page-header-button",
          "is_bot": false,
          "headline": "refactor: replace raw template literal className with cn() across 16 …",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T09:44:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e2b193bbe1446deea512680be1caa2ee178cc712",
          "body": null,
          "is_bot": false,
          "headline": "chore: fix lint warnings in ticket-dialog",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T08:14:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "279789b668796b609a2328a0a0d1687b246ce914",
          "body": "- TicketDialog joins WS presence room for the ticket file on open\n- Acquires edit lock (editing_start) on Edit button click\n- Releases lock (editing_stop) on save, cancel, or dialog close\n- Blocks Edit button if another user holds the lock (shows warning toast)\n- Blocks comment submission and approval actions when locked\n- Shows amber banner when another user is editing the ticket\n- Server-side apiFilePut already enforces the lock via getEditorForPage",
          "is_bot": false,
          "headline": "fix: add write-lock to ticket editing via WebSocket presence",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T08:11:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ecfdaa24ada55e68e0d39caf5ffca99a5697891d",
          "body": null,
          "is_bot": false,
          "headline": "fix: remove dead validation guard in EmailSetupDialog",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:34:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "07c355d2c4bda78639bd2379e5bcb4461bc5e374",
          "body": null,
          "is_bot": false,
          "headline": "fix: replace try/catch flow control with MiniSearch discard()",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:33:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a9196d41a2a222e2ac4d20d5acef9fa77bea49b",
          "body": null,
          "is_bot": false,
          "headline": "fix: replace numeric session counter with randomUUID",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:33:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0257a3ecebb04ecf02daa850c910441c1bb46b86",
          "body": null,
          "is_bot": false,
          "headline": "fix: prevent double submit on Enter in NewPageDialog",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:32:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8ac37763aa5b5a02edf8f3a6d6a5d10198e89533",
          "body": null,
          "is_bot": false,
          "headline": "fix: replace non-null assertion on wsDataStore with defensive throw",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:31:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b9dc7ff1312d58df7abab4378c1a822e4da43d4c",
          "body": null,
          "is_bot": false,
          "headline": "fix: replace unsafe as string assertions with ?? fallback in search",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:31:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a310958ce7acd374c6f552e5332522914c8538d0",
          "body": null,
          "is_bot": false,
          "headline": "fix: cap inflight request dedup map to prevent unbounded growth",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:30:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "46a76075cc40167ef052036b510685fdcec4ac46",
          "body": null,
          "is_bot": false,
          "headline": "fix: destructure all values from single useUser() call",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:30:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0153c18d21da92d8ea85a0a5587b5b56b42e294",
          "body": null,
          "is_bot": false,
          "headline": "refactor: use named import for isSafePath, drop redundant default export",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:29:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c501979328afac54ee48a742497882e79463a40d",
          "body": null,
          "is_bot": false,
          "headline": "Replace fragile regex with js-yaml for ticket YAML timestamp injection",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:27:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f8e58ed4fa4fc7b6707e1d1c410060e6fb11a53a",
          "body": null,
          "is_bot": false,
          "headline": "Fix path traversal vulnerability in SPA file serving",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:57:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b303b689f0506d0bd00a1f346c7fa29dfd7f7ea0",
          "body": null,
          "is_bot": false,
          "headline": "Fix eager eviction of empty rate-limit buckets",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:55:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a01469b1124798fda4b5bfe77cddab3a8473d77f",
          "body": null,
          "is_bot": false,
          "headline": "Pin ws and @types/ws to exact versions",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:50:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59637371ab6af2df93b49e4b4eb1f89bed11a4e1",
          "body": null,
          "is_bot": false,
          "headline": "Display theme names as-is in slide properties select",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:15:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "48328fe9d760521b4d2dd3ed44cf7c5cee73d826",
          "body": null,
          "is_bot": false,
          "headline": "Refactor state ordering and fix empty string handling in top-bar link",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:12:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2286eeff231938e485f38a29fcdae4fedc65a7e6",
          "body": "…mmit link",
          "is_bot": false,
          "headline": "Add repoUrl support to user context and use it in top-bar for HEAD co…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:09:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "84594ee9dec3b3514b6c14d38f45308640da4fd3",
          "body": null,
          "is_bot": false,
          "headline": "Remove custom paragraph component from slide markdown viewer",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T16:29:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8c89fb0cde547fe808d28dc1a7933e8c47a9a8b0",
          "body": null,
          "is_bot": false,
          "headline": "Sync editor cursor position to slide preview in scroll mode",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T16:19:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99907ffba042ec1253b26d26e7afa29348bcdee5",
          "body": "…s as completed in TASKS.md",
          "is_bot": false,
          "headline": "Mark User List, Sidebar Ticket Filtering, and Cross-Board Search task…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T14:01:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7e1876ed576cae0e6688f8366ac4cea8b8dadab",
          "body": "Sidebar ticket filtering (Task 4)",
          "is_bot": false,
          "headline": "Merge pull request #7 from Foorack/feat/filter-bar",
          "author_name": "Foorack / Max Faxälv",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T13:59:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a0805f4d2b46dc41939269c8bf93f2cd3363542",
          "body": "…put component; simplify sidebar callbacks",
          "is_bot": false,
          "headline": "Refactor board filter bar with user toggle, multi-line labels, and In…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T13:54:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c0d4d424a1aab6cc393b4b6cfe2f18b1fae000f8",
          "body": null,
          "is_bot": false,
          "headline": "Add separator between Copy link and Manage in board menu",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T13:13:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e0b98bf4958d55babd571a18bd548c6370eed176",
          "body": null,
          "is_bot": false,
          "headline": "Fix list spacing in AGENTS.md and format DropdownMenuContent inline",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:27:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad09ee30e5c0c483f7b607d02f3f9359e07e0d21",
          "body": "- Extracted hamburger menu trigger (MoreHorizontal button + dropdown\n  wrapper) into shared HeaderMenu component in layout/.\n- File page header now uses HeaderMenu wrapping PageMenuItems (same\n  items as before: Export, Duplicate, Move, Delete, etc.).\n- Board page header now has its own hamburger menu with:\n  - Open in new tab\n  - Copy link\n  - Manage (navigates to /bm/:slug for board management)\n- Updated AGENTS.md with Shared UI Patterns convention to prevent\n  future single-mode assumptions.",
          "is_bot": false,
          "headline": "Add shared HeaderMenu component, use in board header with Manage item",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:27:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80669455404f35c3963feb00c4197a5ab602c96d",
          "body": "…age\"\n\nThis reverts commit c37e16e130d3c0c351a7c00a6cff88d1978a0e1d.",
          "is_bot": false,
          "headline": "Revert \"Remove Export PDF and Move/Delete from doc page menu, add Man…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:24:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c37e16e130d3c0c351a7c00a6cff88d1978a0e1d",
          "body": "- Removed onExportPdf from PageMenuItems (was passing exportPagePdf).\n- Removed onMove/onDelete from PageMenuItems (were Move/Delete items).\n- Added 'Manage' DropdownMenuItem after PageMenuItems that navigates\n  to /bm (board manager).",
          "is_bot": false,
          "headline": "Remove Export PDF and Move/Delete from doc page menu, add Manage",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:21:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b431b6dac1f98391c3f1ce444381dfe639e76987",
          "body": null,
          "is_bot": false,
          "headline": "Add me-3 to viewer avatar groups for spacing with header buttons",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:10:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ce49277eedc4259b429c36f243197b25cafaa8c9",
          "body": null,
          "is_bot": false,
          "headline": "Add grayscaleWhenInactive to Info/TOC PageHeaderButtons",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:51:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "40778b50e3b0de0d44923f0d80acbb730d7dd026",
          "body": null,
          "is_bot": false,
          "headline": "Add px-0 to commit history button entries",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:48:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7cb4bd6ba4d3621cd1bb419f42140fbaf75e5bf",
          "body": null,
          "is_bot": false,
          "headline": "Revert padding change, remove py-1.5 from commit tiles",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:47:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "94c76a1f767bb0eade600e2a26b850ab3232f7a0",
          "body": "…bold group labels",
          "is_bot": false,
          "headline": "Remove horizontal padding from commit history in PageInfo sidebar, un…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:45:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "916f1ba85ed173bc11fb1a133e118300ac85b215",
          "body": "- Renamed ArchiveButton -> PageHeaderButton (generic toggle for\n  page headers, accepts any fileType/label).\n- Moved from src/components/ui/ (general components) to\n  src/components/layout/ (app-specific layout component).\n- Replaced inline ToggleButton in file-page/header.tsx with\n  PageHeaderButton, removed dead ToggleButton function.",
          "is_bot": false,
          "headline": "Move PageHeaderButton from ui/ to layout/, remove old file",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:43:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "352971546b8909f0964eccf10ab35a47d031fb0b",
          "body": "…size=sm)",
          "is_bot": false,
          "headline": "Fix ArchiveButton height: add h-7 to match Info button (was h-8 from …",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:39:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5a0563108fa68f888133bc595e96b97bb27c0ddd",
          "body": null,
          "is_bot": false,
          "headline": "PageInfo/TOC sidebar icons 18 -> 17",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:34:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2283b4f30a0433cf063b3b2e9c87434901b6f514",
          "body": "- toc-sidebar: close X button -> Button variant=ghost size=icon-sm\n- page-info-panel: close X, commit group toggle, commit items -> Button\n- ticket-dialog: copy ID, clear assignee, assign-to-me -> Button\n- version-control-tab: commit click rows -> Button variant=ghost\n- top-bar: app logo from <button onClick={navigate}> to <a href='/'>\n  (supports middle-click, removes unused useNavigate import)",
          "is_bot": false,
          "headline": "Convert all bare button elements to use standard Button component",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:32:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "518601b0dc88b2b861b0d313e8241a4b8a7e6c6c",
          "body": "…o 18\n\n- ArchiveButton now uses <Button> component with variant='secondary'\n  (active) or 'ghost' (inactive) instead of bare <button>.\n- Board page Info button icon bumped from 16 to 18 (matches Archive).\n- File page TOC/Info toggle icons bumped from 16 to 18 (matches\n  board header).",
          "is_bot": false,
          "headline": "Standardize ArchiveButton to use Button component, unify icon sizes t…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:22:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0f1cc8f93670e8af5be4e25e289911b4cd18294",
          "body": null,
          "is_bot": false,
          "headline": "Fix line height",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:21:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "16f35d1689a4de0203082a11534f51b6f70bff1f",
          "body": null,
          "is_bot": false,
          "headline": "Bump PageInfo/TOC sidebar icon size to 18",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:21:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "636ef395afd821956b7130d72587a76a1a94a402",
          "body": null,
          "is_bot": false,
          "headline": "Remove padding on X close button in PageInfo sidebar header",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:20:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d20f68b58d05924ddc28f0cbb520d2392f54d6f6",
          "body": "…s to tracking-wider\n\n- PageInfo sidebar: py-2 -> py-2.5 (matches column header height)\n- Main sidebar: removed pt-1 from text span (was making header 44px vs 38px)\n- All uppercase headings now use tracking-wider consistently:\n  page-info-panel labels, slide-themes headings, ticket-sidebar headings",
          "is_bot": false,
          "headline": "Fix header height inconsistency and standardize all uppercase heading…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:14:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba744c1c9f7b48fcc977d9e129802f24690cb412",
          "body": null,
          "is_bot": false,
          "headline": "Match sidebar header tracking to board column headers (tracking-wider)",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:11:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c23c273747339584315e413cdd3181667b2ea0af",
          "body": null,
          "is_bot": false,
          "headline": "Fix TOC icon name: AppListDetail -> AppsListDetail",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:10:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b250622a114da15830b67067afdc5d9e6c57d3a6",
          "body": null,
          "is_bot": false,
          "headline": "Swap File/List icons in PageInfoPanel and TocSidebar for EmojiIcon",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:09:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d4baed783976757ef17b6a5951ed9245939c53ea",
          "body": null,
          "is_bot": false,
          "headline": "Swap lucide Info/List icons for EmojiIcon pageinfo/toc",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:05:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "01acf5e9eed84137d7debbf409cc9fc71bd75866",
          "body": "…n types",
          "is_bot": false,
          "headline": "Add pageinfo (DocumentText24Color) and toc (AppListDetail24Color) ico…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T09:01:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6066f14a6eab12e7386a66d96e3e0938b8d10f0d",
          "body": null,
          "is_bot": false,
          "headline": "Remove mr-2 from ArchiveButton",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:58:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "18b79f4f0c67b7bea67837b3c8a701db5e0e423f",
          "body": null,
          "is_bot": false,
          "headline": "Bump board header py-1 to py-2",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:56:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cd027a30f3378aea4cb887ceeaf1d422ed8cf333",
          "body": null,
          "is_bot": false,
          "headline": "Use colon instead of comma in sort labels",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:42:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cca039ec8cb946fcbca6012c5d0643b6cf0b0071",
          "body": null,
          "is_bot": false,
          "headline": "Bump gap from space-y-0.5 to space-y-1",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:38:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "282134885f84da0e166ca7956a9ea1d9a56a0657",
          "body": null,
          "is_bot": false,
          "headline": "Add pb-2 back to filter bar for space above divider",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:36:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90f303cd294b1f56e4f2735185afe7a6f3fbdbf3",
          "body": null,
          "is_bot": false,
          "headline": "Unify spacing: all gaps come from parent space-y-0.5 only",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:33:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 0,
      "commits_last_year": 836,
      "latest_release_at": null,
      "latest_release_tag": null,
      "releases_from_tags": false,
      "days_since_last_push": 6,
      "active_weeks_last_year": 14,
      "days_since_latest_release": null,
      "mean_days_between_releases": null
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": false,
      "has_contributing": false,
      "health_percentage": 28,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "kumidocs",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "wiki",
            "docs",
            "markdown",
            "git",
            "bun",
            "self-hosted"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/kumidocs",
          "is_deprecated": false,
          "latest_version": "0.20260720.156",
          "repository_url": "https://github.com/Foorack/kumidocs",
          "versions_count": 139,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 8997,
          "first_published_at": "2026-03-13T09:54:29.418000Z",
          "latest_published_at": "2026-07-20T11:23:22.843000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 6
        }
      ]
    },
    "popularity": {
      "forks": 2,
      "stars": 3,
      "watchers": 1,
      "fork_history": {
        "days": [
          {
            "date": "2026-06-28",
            "count": 1
          },
          {
            "date": "2026-06-30",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 2,
        "total_forks": 2
      },
      "star_history": null,
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 419910,
      "source_files_sampled": 150,
      "oversized_source_files": 1,
      "agent_instruction_files": [
        "AGENTS.md"
      ],
      "agent_instruction_max_bytes": 10645
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [
          {
            "name": "js-yaml",
            "direct": true,
            "version": "5.2.1",
            "severity": "high",
            "ecosystem": "npm",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-pm4m-ph32-ghv5"
            ],
            "fixed_version": "5.2.2",
            "advisory_count": 1,
            "oldest_advisory_days": 1
          },
          {
            "name": "react-router",
            "direct": false,
            "version": "7.18.0",
            "severity": "high",
            "ecosystem": "npm",
            "cvss_score": null,
            "advisory_ids": [
              "GHSA-qwww-vcr4-c8h2"
            ],
            "fixed_version": "8.3.0",
            "advisory_count": 1,
            "oldest_advisory_days": 1
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "high": 2
        },
        "advisory_count": 2,
        "affected_count": 2,
        "assessed_count": 443,
        "malicious_count": 0,
        "assessed_package": "npm:kumidocs@0.20260720.156",
        "unassessed_count": 0,
        "direct_affected_count": 1
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@dnd-kit/core",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "6.3.1"
        },
        {
          "name": "@dnd-kit/sortable",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "10.0.0"
        },
        {
          "name": "@dnd-kit/utilities",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "3.2.2"
        },
        {
          "name": "@iconify-json/devicon",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.62"
        },
        {
          "name": "@iconify-json/flag",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.12"
        },
        {
          "name": "@iconify-json/fluent-color",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.21"
        },
        {
          "name": "@iconify-json/glyphs-poly",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.0"
        },
        {
          "name": "@iconify-json/logos",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.11"
        },
        {
          "name": "@noble/hashes",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.2.0"
        },
        {
          "name": "@radix-ui/react-label",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.1.10"
        },
        {
          "name": "@radix-ui/react-select",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.3.1"
        },
        {
          "name": "@radix-ui/react-slider",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.4.2"
        },
        {
          "name": "@radix-ui/react-slot",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.3.0"
        },
        {
          "name": "@streamdown/cjk",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.0.3"
        },
        {
          "name": "@streamdown/code",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.1.1"
        },
        {
          "name": "@streamdown/math",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.0.2"
        },
        {
          "name": "@streamdown/mermaid",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.0.2"
        },
        {
          "name": "class-variance-authority",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "0.7.1"
        },
        {
          "name": "clsx",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.1.1"
        },
        {
          "name": "cmdk",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.1.1"
        },
        {
          "name": "color",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "5.0.3"
        },
        {
          "name": "diff",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "9.0.0"
        },
        {
          "name": "html2canvas-pro",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.2.0"
        },
        {
          "name": "ignore",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "7.0.5"
        },
        {
          "name": "js-yaml",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "5.2.1"
        },
        {
          "name": "jspdf",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "4.2.1"
        },
        {
          "name": "khroma",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.1.0"
        },
        {
          "name": "linkedom",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.18.13"
        },
        {
          "name": "lucide-react",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.21.0"
        },
        {
          "name": "minisearch",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "7.2.0"
        },
        {
          "name": "next-themes",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "0.4.6"
        },
        {
          "name": "radix-ui",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.6.0"
        },
        {
          "name": "react",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "19.2.7"
        },
        {
          "name": "react-diff-view",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "3.3.3"
        },
        {
          "name": "react-dom",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "19.2.7"
        },
        {
          "name": "react-router-dom",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "7.18.0"
        },
        {
          "name": "rehype-harden",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.1.8"
        },
        {
          "name": "sonner",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.0.7"
        },
        {
          "name": "streamdown",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.5.0"
        },
        {
          "name": "tailwind-merge",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "3.6.0"
        },
        {
          "name": "ws",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "8.21.0"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "@dnd-kit/core",
            "direct": true,
            "version": "6.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "@dnd-kit/sortable",
            "direct": true,
            "version": "10.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "@dnd-kit/utilities",
            "direct": true,
            "version": "3.2.2",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/devicon",
            "direct": true,
            "version": "1.2.62",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/flag",
            "direct": true,
            "version": "1.2.12",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/fluent-color",
            "direct": true,
            "version": "1.2.21",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/glyphs-poly",
            "direct": true,
            "version": "1.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/logos",
            "direct": true,
            "version": "1.2.11",
            "ecosystem": "npm"
          },
          {
            "name": "@noble/hashes",
            "direct": true,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "@radix-ui/react-label",
            "direct": true,
            "version": "2.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "@radix-ui/react-select",
            "direct": true,
            "version": "2.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "@radix-ui/react-slider",
            "direct": true,
            "version": "1.4.2",
            "ecosystem": "npm"
          },
          {
            "name": "@radix-ui/react-slot",
            "direct": true,
            "version": "1.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "@streamdown/cjk",
            "direct": true,
            "version": "1.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "@streamdown/code",
            "direct": true,
            "version": "1.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "@streamdown/math",
            "direct": true,
            "version": "1.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@streamdown/mermaid",
            "direct": true,
            "version": "1.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "class-variance-authority",
            "direct": true,
            "version": "0.7.1",
            "ecosystem": "npm"
          },
          {
            "name": "clsx",
            "direct": true,
            "version": "2.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "cmdk",
            "direct": true,
            "version": "1.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "color",
            "direct": true,
            "version": "5.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "diff",
            "direct": true,
            "version": "9.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "html2canvas-pro",
            "direct": true,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "ignore",
            "direct": true,
            "version": "7.0.5",
            "ecosystem": "npm"
          },
          {
            "name": "js-yaml",
            "direct": true,
            "version": "5.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "jspdf",
            "direct": true,
            "version": "4.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "khroma",
            "direct": true,
            "version": "2.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "linkedom",
            "direct": true,
            "version": "^0.18.13",
            "ecosystem": "npm"
          },
          {
            "name": "lucide-react",
            "direct": true,
            "version": "1.21.0",
            "ecosystem": "npm"
          },
          {
            "name": "minisearch",
            "direct": true,
            "version": "7.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "next-themes",
            "direct": true,
            "version": "0.4.6",
            "ecosystem": "npm"
          },
          {
            "name": "radix-ui",
            "direct": true,
            "version": "1.6.0",
            "ecosystem": "npm"
          },
          {
            "name": "react",
            "direct": true,
            "version": "19.2.7",
            "ecosystem": "npm"
          },
          {
            "name": "react-diff-view",
            "direct": true,
            "version": "3.3.3",
            "ecosystem": "npm"
          },
          {
            "name": "react-dom",
            "direct": true,
            "version": "19.2.7",
            "ecosystem": "npm"
          },
          {
            "name": "react-router-dom",
            "direct": true,
            "version": "7.18.0",
            "ecosystem": "npm"
          },
          {
            "name": "rehype-harden",
            "direct": true,
            "version": "1.1.8",
            "ecosystem": "npm"
          },
          {
            "name": "sonner",
            "direct": true,
            "version": "2.0.7",
            "ecosystem": "npm"
          },
          {
            "name": "streamdown",
            "direct": true,
            "version": "2.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "tailwind-merge",
            "direct": true,
            "version": "3.6.0",
            "ecosystem": "npm"
          },
          {
            "name": "ws",
            "direct": true,
            "version": "8.21.0",
            "ecosystem": "npm"
          },
          {
            "name": "@tailwindcss/typography",
            "direct": false,
            "version": "0.5.20",
            "ecosystem": "npm"
          },
          {
            "name": "@types/bun",
            "direct": false,
            "version": "1.3.14",
            "ecosystem": "npm"
          },
          {
            "name": "@types/color",
            "direct": false,
            "version": "4.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "@types/node",
            "direct": false,
            "version": "26.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "@types/react",
            "direct": false,
            "version": "19.2.17",
            "ecosystem": "npm"
          },
          {
            "name": "@types/react-dom",
            "direct": false,
            "version": "19.2.3",
            "ecosystem": "npm"
          },
          {
            "name": "@types/ws",
            "direct": false,
            "version": "8.18.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/native-preview",
            "direct": false,
            "version": "7.0.0-dev.20260626.1",
            "ecosystem": "npm"
          },
          {
            "name": "bun-plugin-tailwind",
            "direct": false,
            "version": "0.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "country-flag-icons",
            "direct": false,
            "version": "1.6.19",
            "ecosystem": "npm"
          },
          {
            "name": "oxfmt",
            "direct": false,
            "version": "0.56.0",
            "ecosystem": "npm"
          },
          {
            "name": "oxlint",
            "direct": false,
            "version": "1.71.0",
            "ecosystem": "npm"
          },
          {
            "name": "oxlint-tsgolint",
            "direct": false,
            "version": "0.23.0",
            "ecosystem": "npm"
          },
          {
            "name": "tailwindcss",
            "direct": false,
            "version": "4.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "tw-animate-css",
            "direct": false,
            "version": "1.4.0",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "6.0.3",
            "ecosystem": "npm"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 57,
        "direct_count": 41,
        "indirect_count": 16
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 6,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 1,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "Foorack",
          "commits": 833,
          "avatar_url": "https://avatars.githubusercontent.com/u/5008081?v=4"
        },
        {
          "type": "User",
          "login": "systeemgod",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/36364329?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.999
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "publish.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "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": null,
            "reason": "no pull request found",
            "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 0/30 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 1 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": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "1c3db31da59b81addde1b3cf900396002e649c18",
        "ran_at": "2026-07-26T16:35:21Z",
        "aggregate_score": 5.8,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-20T11:23:26Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-12T13:59:38Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/Foorack/kumidocs",
    "host": "github.com",
    "name": "kumidocs",
    "owner": "Foorack"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 53,
      "inputs": {
        "security": 59,
        "vitality": 45,
        "community": 36,
        "governance": 63,
        "engineering": 58
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "at_risk",
        "name": "Vitality",
        "value": 45,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 74,
            "inputs": {
              "commits_last_year": 836,
              "human_commit_share": 1,
              "days_since_last_push": 6,
              "active_weeks_last_year": 14
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 6 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "14/52 weeks with commits",
                "points": 9.7,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 14
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "836 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 836
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "critical",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "releases_count": 0
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "no releases published",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases_published",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "no releases",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases",
                    "params": {}
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "no releases",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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": 36,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 5,
            "inputs": {
              "forks": 2,
              "stars": 3,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "3 stars",
                "points": 4.9,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "2 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "1 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 66,
            "inputs": {
              "packages": [
                "kumidocs"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 8997
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "8,997 downloads/month across npm",
                "points": 52.7,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 8997,
                      "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": 63,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 22,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.999
            },
            "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 100% of commits",
                "points": 0,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "2 contributors",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "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": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "merged_prs": 6,
              "open_issues": 0,
              "closed_issues": 1,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "6/6 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 6,
                      "decided": 6
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "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": 60,
            "inputs": {
              "followers": 58,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "Foorack",
              "public_repos": 80,
              "account_age_days": 4759
            },
            "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": "58 followers of Foorack",
                "points": 12.7,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 58,
                      "login": "Foorack"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "80 public repos, account ~13 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 80
                    }
                  },
                  {
                    "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": [
                "kumidocs"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 6
            },
            "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 6 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "139 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 139
                    }
                  }
                ],
                "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": "moderate",
        "name": "Engineering Quality",
        "value": 58,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": null,
              "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": null,
                "points": 0,
                "status": "missed",
                "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 59,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 58,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 5.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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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 0/30 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 1 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": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "3 existing vulnerabilities detected",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "moderate",
            "name": "Dependency advisories",
            "note": "Matched the npm:kumidocs@0.20260720.156 runtime dependency closure — what installing the published package pulls in — 443 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:kumidocs@0.20260720.156",
                  "assessed": 443
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 65,
            "inputs": {
              "source": "osv",
              "advisories": 2,
              "affected_packages": 2,
              "assessed_packages": 443,
              "unassessed_packages": 0,
              "affected_by_severity": "high 2",
              "direct_affected_packages": 1
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "1 affected: js-yaml 5.2.1 (high 7.5)",
                "points": 14,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "js-yaml 5.2.1 (high 7.5)"
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "1 affected: react-router 7.18.0 (high)",
                "points": 11,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "react-router 7.18.0 (high)"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory has been public longer than 90 days",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "advisories_none_stale",
                    "params": {
                      "days": 90
                    }
                  }
                ],
                "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": 443,
              "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": 4
            },
            "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": "moderate",
        "name": "AI Readiness",
        "value": 66,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "good",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.65,
              "agent_instruction_files": [
                "AGENTS.md"
              ],
              "agent_instruction_max_bytes": 10645
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "65 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 34.7,
                "status": "partial",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 65,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 43,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "tsconfig.json"
              ],
              "agent_commit_share": 0,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "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": 419910,
              "source_files_sampled": 150,
              "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/150 source files over 60KB",
                "points": 54.6,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 150,
                      "oversized": 1
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "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": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-26T16:35:31.137602Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/f/Foorack/kumidocs.svg",
  "full_name": "Foorack/kumidocs",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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