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

nemanjan00 / qrp

A data-first, declarative, low-overhead framework for dashboards. Zero RUNTIME dependencies, zero build step — the devDependencies below are only for tests, lint, and git hooks.

JavaScript · HTMLMIT★ 0 зірок⑂ 0 форківз лип. 2026 р.Переглянути на GitHub ↗

nemanjan00/qrp має індекс здоров’я 55 зі 100, що відповідає смузі «Помірний». Найвищий показник — Engineering Quality (93/100), найнижчий — Security (32/100). Останнє оновлення було 4 дні тому. Більшість нещодавньої роботи виконує один учасник.

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

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

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

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

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

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

Власність

Nemanja NedeljkovićОсобистий обліковий запис
117 підписників233 публічні репозиторіїз жовт. 2010 р.FlockSocial

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

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

РеєстрПакетВерсіяЗавантажень / місВерсіїОстання публікаціяТеги
npm@nemanjan00/qrp0.7.02 683184 дні томуdashboardreactiveproxydeclarativeframeworkfrontendno-buildzero-dependencydomformstable

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

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

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

68Помірний · 22% загального індексу
Як обчислюється оцінка
36/36Свіжість push — останній push 4 дн. тому
0.7/36Ритм комітів — 1/52 тижнів із комітами
18/18Обсяг комітів — 118 комітів за останній рік
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Використані вхідні дані
commits_last_year118
human_commit_share1
days_since_last_push4
active_weeks_last_year1
Як обчислюється оцінка
16.2/27Випускає релізи — 21 тегів версій (без релізів GitHub)
36/36Свіжість релізів — останній реліз 4 дн. тому
27/27Ритм релізів — реліз кожні ~0,2 дн.
0/10OpenSSF Scorecard: Signed-Releases — немає даних
Використані вхідні дані
releases_count21
latest_release_tagv0.7.0
releases_from_tagsтак
days_since_latest_release4
mean_days_between_releases0,2
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: Signed-Releases. Залишкові ваги перенормовано.

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

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

32У зоні ризику · 18% загального індексу
Як обчислюється оцінка
0/60Зірки — 0 зірок
0/25Форки — 0 форків
0/15Спостерігачі — 0 спостерігачів
Використані вхідні дані
forks0
stars0
watchers0
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ні
Як обчислюється оцінка
45.7/80Щомісячні завантаження — 2 683 завантажень/місяць у npm
0/20Залежні пакети в реєстрі — ця екосистема цього не повідомляє
Використані вхідні дані
packages@nemanjan00/qrp
dependents
ecosystemsnpm
total_downloads
monthly_downloads2 683
Виключено з оцінювання (немає даних або не застосовно): Залежні пакети в реєстрі. Залишкові ваги перенормовано.

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

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

42У зоні ризику · 24% загального індексу
Як обчислюється оцінка
9/54Бас-фактор — на 1 контриб’ютор(ів) припадає половина всіх комітів
0/22.5Розподіл комітів — головний контриб’ютор — автор 100% комітів
1.4/13.5Широта контриб’юторів — 1 контриб’юторів
10/10OpenSSF Scorecard: Contributors — project has 6 contributing companies or organizations
Використані вхідні дані
bus_factor1
contributors_sampled1
top_contributor_share1
Як обчислюється оцінка
0/46.8Вирішення issue — немає issue або даних
0/38.3Прийняття PR — немає вирішених pull request-ів або даних
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Використані вхідні дані
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
Виключено з оцінювання (немає даних або не застосовно): Вирішення issue, Прийняття PR. Залишкові ваги перенормовано.
Як обчислюється оцінка
10/30Підтримка власника — особистий (користувацький) обліковий запис
0/20Верифікований домен — не застосовно до користувацьких облікових записів
14.9/25Охоплення власника — 117 підписників у nemanjan00
25/25Послужний список — 233 публічних репозиторіїв, вік облікового запису ~15 р.
Використані вхідні дані
followers117
owner_typeUser
is_verified
owner_loginnemanjan00
public_repos233
account_age_days5 752
Виключено з оцінювання (немає даних або не застосовно): Верифікований домен. Залишкові ваги перенормовано.

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

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

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

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

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

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

100Відмінний
Як обчислюється оцінка
30/30README
25/25Каталог документації
15/15Сайт документації / домашня сторінка — https://qrp.nemanja.top/
10/10Опис репозиторію
10/10Теми — 11 тем
10/10Wiki
Використані вхідні дані
topicsdashboard, declarative, dom, forms, framework, frontend, no-build, proxy, reactive, table, zero-dependency
has_wikiтак
homepagehttps://qrp.nemanja.top/
has_readmeтак
has_docs_dirтак
has_descriptionтак

Безпека

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

32У зоні ризику · 16% загального індексу

Стан безпеки

32У зоні ризику
Як обчислюється оцінка
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 6 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Ліцензія — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — немає даних
1.5/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 3
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — немає даних
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
Використані вхідні дані
sourceopenssf_scorecard
checks_evaluated15
scorecard_versionv5.5.0
checks_inconclusive3
scorecard_aggregate3,2
Виключено з оцінювання (немає даних або не застосовно): ci_tests, packaging, signed_releases. Залишкові ваги перенормовано.

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

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

67Помірний · 0% загального індексу
Як обчислюється оцінка
45/45Інструкції для агентів — CLAUDE.md
0/15Машиночитана документація (llms.txt)
40/40Читабельна історія комітів — намір зазначено у 86 з 100 людських комітів (структурований заголовок або пояснювальний текст)
Використані вхідні дані
has_llms_txtні
legible_history_share0,86
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes15 489
Як обчислюється оцінка
0/18Розгортання однією командою
22/22Автоматизовані тести
11/11Конфігурація лінтера / форматера — .eslintrc.json
11/11Статична перевірка типів — tsconfig.json
10/10Відтворюване середовище — lockfile
0/10Підтверджена практика роботи з агентами — серед останніх 100 комітів немає створених агентом
0/8Автоматизоване супроводження — автоматичних оновлень залежностей не виявлено
3/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 3
Використані вхідні дані
has_nixні
has_testsтак
lockfilespackage-lock.json
has_dockerfileні
typed_languageні
bootstrap_files
has_devcontainerні
has_linter_configтак
typecheck_configstsconfig.json
agent_commit_share0
toolchain_manifests
dependency_bot_commit_share0
Як обчислюється оцінка
27/45Типізований код — JavaScript з конфігурацією перевірки типів (tsconfig.json)
55/55Керовані розміри файлів — 0/84 файлів вихідного коду понад 60 КБ
Використані вхідні дані
primary_languageJavaScript
largest_source_bytes46 054
source_files_sampled84
oversized_source_files0
Як обчислюється оцінка
0/40Схема API (OpenAPI/GraphQL/proto)
0/20Сервер MCP
40/40Придатні до запуску приклади — examples
Використані вхідні дані
example_dirsexamples
has_mcp_signalні
api_schema_files

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

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

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

  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository
  • deps.dev does not index npm:@nemanjan00/qrp@0.7.0; advisories assessed against the repository dependency graph instead

Докладніше

OpenSSF Scorecard 3.2 / 10
3.2сукупно

Незалежна, не прив'язана до інструментів оцінка безпеки від відкритого проєкту OpenSSF Scorecard. Кожна перевірка винагороджує практику безпеки, а не інструмент конкретного постачальника. Перевірки, які Scorecard не зміг визначити, позначено н/д і виключено з оцінки безпеки (вони ніколи не зараховуються як нуль).Scorecard v5.5.0 · 2026-07-21 16:52 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 6 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
н/дPackagingpackaging workflow not detected
3Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 3
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
н/дSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
7Vulnerabilities3 existing vulnerabilities detected
Усі залежності не зібрано

Не вдалося зібрати розв'язаний набір залежностей для цього звіту: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Звіт у форматі JSON машиночитний
{
  "data": {
    "repo": {
      "topics": [
        "dashboard",
        "declarative",
        "dom",
        "forms",
        "framework",
        "frontend",
        "no-build",
        "proxy",
        "reactive",
        "table",
        "zero-dependency"
      ],
      "is_fork": false,
      "size_kb": 580,
      "has_wiki": true,
      "homepage": "https://qrp.nemanja.top/",
      "languages": {
        "CSS": 11179,
        "HTML": 61215,
        "JavaScript": 298103,
        "TypeScript": 5735
      },
      "pushed_at": "2026-07-17T00:27:50Z",
      "created_at": "2026-07-14T15:22:49Z",
      "owner_type": "User",
      "updated_at": "2026-07-17T00:27:54Z",
      "description": "A data-first, declarative, low-overhead framework for dashboards. Zero RUNTIME dependencies, zero build step — the devDependencies below are only for tests, lint, and git hooks.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "master",
      "license_spdx_raw": "MIT",
      "primary_language": "JavaScript",
      "significant_languages": [
        "JavaScript",
        "HTML"
      ]
    },
    "owner": {
      "blog": "https://nemanja.top/",
      "name": "Nemanja Nedeljković",
      "type": "User",
      "login": "nemanjan00",
      "company": "FlockSocial",
      "location": "Belgrade, Serbia",
      "followers": 117,
      "avatar_url": "https://avatars.githubusercontent.com/u/448151?v=4",
      "created_at": "2010-10-21T11:30:52Z",
      "is_verified": null,
      "public_repos": 233,
      "account_age_days": 5752
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-07-17T00:27:34Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2026-07-16T22:34:59Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-07-16T10:30:16Z"
        },
        {
          "tag": "v0.5.2",
          "kind": "patch",
          "published_at": "2026-07-16T09:50:20Z"
        },
        {
          "tag": "v0.5.1",
          "kind": "patch",
          "published_at": "2026-07-15T19:24:55Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-07-15T18:05:51Z"
        },
        {
          "tag": "v0.4.10",
          "kind": "patch",
          "published_at": "2026-07-15T18:02:48Z"
        },
        {
          "tag": "v0.4.9",
          "kind": "patch",
          "published_at": "2026-07-15T14:37:00Z"
        },
        {
          "tag": "v0.4.8",
          "kind": "patch",
          "published_at": "2026-07-15T10:24:47Z"
        },
        {
          "tag": "v0.4.7",
          "kind": "patch",
          "published_at": "2026-07-15T09:18:08Z"
        },
        {
          "tag": "v0.4.6",
          "kind": "patch",
          "published_at": "2026-07-15T08:41:53Z"
        },
        {
          "tag": "v0.4.5",
          "kind": "patch",
          "published_at": "2026-07-15T08:21:18Z"
        },
        {
          "tag": "v0.4.4",
          "kind": "patch",
          "published_at": "2026-07-15T08:14:59Z"
        },
        {
          "tag": "v0.4.3",
          "kind": "patch",
          "published_at": "2026-07-15T08:01:11Z"
        },
        {
          "tag": "v0.4.2",
          "kind": "patch",
          "published_at": "2026-07-15T01:12:44Z"
        },
        {
          "tag": "v0.4.1",
          "kind": "patch",
          "published_at": "2026-07-14T23:22:24Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-07-14T23:03:13Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-07-14T22:36:51Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2026-07-14T20:02:26Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-07-14T19:15:41Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-07-14T19:02:49Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "ea7183479bbd1581280f33be6d5428ffd9c323c9",
          "body": "Authoring Custom Elements is tangential to 'turn data into a dashboard' — more a\n'no class extends' flex than a dashboard need — so it's out, per do-one-thing-well.\nCore drops ~4.6 -> ~4.4 KB min+gzip. mount()/scoped() cover in-app component\nlifecycles; the ~50 self-contained lines (state+scope+clea\n[…]\n: removed the Custom elements demo section, the qrp-clock demo,\n  imports, highlighter keyword, and module-card mention. index.html render-checked.\n\nPer the tag rule, this is the version after v0.6.1.",
          "is_bot": false,
          "headline": "0.7.0: remove define() (custom-element registration) — BREAKING",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-17T00:27:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0c3e1cec0bfc0b0c1fb5c2a4e95830d5ee101014",
          "body": "v0.6.0 was tagged/published before commit 53f17ae (SHARP-EDGES callout in\nREADME + API reference, and the API.md regen documenting list()'s onDuplicateKey).\nPer 'anything after a tag is the next version', that's 0.6.1 — moved the\nSHARP-EDGES bullet out of the published 0.6.0 section into a new 0.6.1 section and\nbumped. Docs only; runtime identical to 0.6.0.",
          "is_bot": false,
          "headline": "0.6.1: SHARP-EDGES callout + onDuplicateKey docs (post-0.6.0-tag work)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-16T22:34:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "53f17ae6ec1d8da796942341b1986475dc102f60",
          "body": "…reference\n\nPoint readers (and coding agents reading the shipped docs) at the gotchas doc up\nfront. Added to bin/gen-api.js's preamble so API.md keeps it on regeneration, and\nto the README intro.\n\nAlso fixes a docs regression this surfaced: ListOptions had been inserted between\nlist()'s JSDoc and it\n[…]\nerface and\nDROPPED the entire ### list section (81 -> 80 exports). Moved ListOptions after\nthe function; list is back, onDuplicateKey documented, export set matches (81).\nFolds into unpublished 0.6.0.",
          "is_bot": false,
          "headline": "docs: 'read SHARP-EDGES before implementing' callout in README + API …",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-16T22:31:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0daa09dd9470160e6bced575ae2604a04a57715d",
          "body": "…f-host docs\n\nBuild:\n- dist/ is now a flat per-module minified mirror — dropped esbuild code-splitting,\n  so no shared chunk-*.js. Each module minifies in place (same names, no hashes);\n  cross-module imports stay relative (table.js -> ./qrp.js) so core is shared not\n  inlined, bundlers still tree-s\n[…]\nd sizes; CLAUDE.md build/release notes updated.\n\nAlso fixes CHANGELOG attribution: restored the 0.5.2 (ships-docs) and 0.5.1\n(guard rework) sections that prior version-shuffling had merged/mislabeled.",
          "is_bot": false,
          "headline": "0.6.0: flat dist (no chunks), list onDuplicateKey, build-optional/sel…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-16T10:30:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e508a5684d522c7a03c9f2a5c0add662af0d4951",
          "body": "Reviewer called it 'rare and great' — test a qrp component in a plain node --test\nscript under happy-dom, no browser. It follows from the core premise (real DOM,\nno VDOM/hydration/test-renderer) and is how qrp tests itself, but was never\nsurfaced as a selling point. Added a README section with a verified example (a\ntable going 0->3 rows on a state write via @happy-dom/global-registrator). Folds\ninto the unpublished 0.5.3 docs release.",
          "is_bot": false,
          "headline": "docs: document headless testability as a first-class plus (0.5.3)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-16T10:13:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c9ab49bfde4b0ecebfefca880a8c6a681e6768fd",
          "body": "Readers — humans and coding agents reading the shipped docs — were concluding\nfrom 'zero build / no bundler' that qrp CANNOT use a bundler. It always could;\nthe aimfox review confirmed it's a model ESM package under Vite (exports subpaths,\ntree-shaking, .d.ts). Philosophy: it's an MIT lib, use it ho\n[…]\nUDE.md: philosophy now states build-optional explicitly so future edits keep\n  the framing.\n\nDocs/metadata only, no runtime change. Ships because README + description + docs\nreach npm only on publish.",
          "is_bot": false,
          "headline": "0.5.3: reframe messaging as build-OPTIONAL (not build-forbidden)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-16T10:07:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "16f5ba4712576ba356123c19db8f921fa4860682",
          "body": "A coding agent (and humans) learn the API from what's in node_modules, so put the\nreference there: added docs/ and CHANGELOG.md to the files allowlist. The full\nAPI reference, getting-started, sharp-edges, and styling guides now travel with\nthe install — offline, no repo visit.\n\n- README doc + CHANG\n[…]\nUDE.md: package-contents note + release checklist updated (docs/ ships now;\n  *.html/docs-site.*/examples/ still don't).\n- ~30 KB added to the packed tarball (48.8 -> 78.7 kB); runtime code unchanged.",
          "is_bot": false,
          "headline": "0.5.2: ship docs/*.md + CHANGELOG in the npm package",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-16T09:50:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4f33dfb9c00a0b6e2f450c8b436e52d9e8d25348",
          "body": "…c-page dedup)\n\nThree loose ends from the review round:\n\n1. form() emitted markup (review §5): STYLING.md had the class table but not the\n   NESTING — the reviewer's labels 'sat inline until I inspected the DOM'. Added\n   the exact skeleton (bare <h3> outside .settings-section; .setting-item is\n   l\n[…]\ns. Verified all four render (headings, TOC, derived\n   aria-labels, cross-doc links resolve, live search filter) with no console\n   errors. Site-only files, not in the npm allowlist — no version bump.",
          "is_bot": false,
          "headline": "docs+site: close remaining gaps (form() markup, release checklist, do…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T19:37:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6cd00211217a587a1421ec67f7c2bfd07ce675d2",
          "body": "Patch bump: 0.5.0 (published) shipped the wall-clock runaway guard; the\nre-entrancy-depth rework (79e4179) is a runtime fix, so it needs its own version.\nMoved that CHANGELOG entry to a 0.5.1 section; 0.5.0 stays as published.",
          "is_bot": false,
          "headline": "0.5.1",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T19:24:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "264f773087e4668a0426166e6adfb32f5f3e2e87",
          "body": "Re-measured everything for 0.5.0:\n\nSizes (stale, updated): core ~3.9 -> ~4.5 KB min+gzip; whole library ~17 ->\n~20.5 KB; raw source ~12 -> ~16 KB gz. ESP32 blob rebuilt: app JS ~10.9 -> ~12.7\nKB, HTML ~15.4 -> ~17.4 KB, gzipped ~6 -> ~7 KB (react-dom ~45 KB gz is now ~6x,\nwas 7x). Test badge/count 2\n[…]\nmachine; the paint-timed suite landed on the\ndocumented table within normal jitter. Overwriting curated reference numbers with\nnoisier container/Xvfb figures would only make them worse, so they stand.",
          "is_bot": false,
          "headline": "docs: refresh sizes (benchmarks re-verified, unchanged)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T19:22:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "79e417933ba5c6e35974cf29fa84d7e81cfc8993",
          "body": "Re-running the benchmark for the size/perf refresh surfaced a false-positive in\n0.4.10's loop guard: updateOneNs fires one cell's effect ~22,000 times in a tight\nsynchronous loop, and the 1000-runs-per-second rate guard tore it down at 1001.\nA legitimately HOT reactive path (bulk writes, animation, \n[…]\n in practice.\n\n- new test: 5000 sequential updates to one effect never trip the guard\n- existing A<->B runaway + phase:'loop' report still pass\n- d.ts/SHARP-EDGES/CHANGELOG updated; API.md regenerated",
          "is_bot": false,
          "headline": "fix(core): runaway guard detects re-entrancy depth, not wall-clock rate",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T19:22:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9d8c351a780ba8fbd272cce549306d1db95e9ded",
          "body": "Bump for this round's new module + features. 0.4.10 (published) keeps only what\nshipped in it — the runaway-effect guard and the two createHttp fixes. The new\ndatagrid module (a new public subpath) makes this a minor bump; datagrid,\ncollection.filtered(), behaviors scope auto-teardown, query({arrays}), and the\nmarker console.error escalation move under the 0.5.0 heading.",
          "is_bot": false,
          "headline": "0.5.0",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T18:05:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ca57b95c59955c06a414c97ab4c77b6a952608ff",
          "body": "…PI, site\n\n- README + CLAUDE.md: datagrid module entry; behaviors scope auto-registration;\n  collection.filtered(); http pluggable fetch.\n- CHANGELOG 0.4.10: datagrid, collection.filtered, behavior auto-teardown,\n  query({arrays}), marker console.error.\n- docs/SHARP-EDGES: query({arrays}) note (repl\n[…]\n (13 modules, 81 exports — adds datagrid).\n- index.html: datagrid module card + import map; footer stats (259 tests, ~4.5 KB\n  core). Verified index.html + api.html render datagrid, no console errors.",
          "is_bot": false,
          "headline": "docs: datagrid + round-four fixes across README, CLAUDE, CHANGELOG, A…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T18:02:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4f9b6af7207f756f15da80c75bfae34cff48d067",
          "body": "…ogs error\n\nThree review edges (§7, §11, §2):\n\n- §7: portal/dismissable/trapFocus/anchored now onDispose-register their undo, so\n  building them inside scoped()/mount() means dispose() alone tears down effects\n  AND behaviors — no hand-tracking. Undos stay returned and are now idempotent.\n- §11: que\n[…]\ned (unchanged).\n- §2: a bare parent.append(when()/list()) now logs at console.error (was warn) so\n  headless/CI catches it (most harnesses fail on console.error); the in-DOM\n  breadcrumb is unchanged.",
          "is_bot": false,
          "headline": "fix: behaviors auto-register teardown; query() array params; marker l…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T18:02:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "61195b6e751a0669a9a4767e02195e04cceb6e31",
          "body": "…aging)\n\nReview §11 called a headless dataGrid 'the single highest-leverage addition' for\nqrp's audience — the batteries every admin table rebuilds: row selection\n(select-all + indeterminate, keyed so it survives sort/filter/page churn and\nrow-object replacement on refetch), column visibility, page-\n[…]\nthe\n  .d.ts), gen-api MODULES, and test/types.ts\n- tests: selection + keyed-survives-refetch + filtered select-all, column\n  visibility, page-size reset, windowed pager clamping, explicit-page honored",
          "is_bot": false,
          "headline": "feat(datagrid): headless data-grid state machine (selection/columns/p…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T18:02:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "87e6f0618eeedaa895e9512ac2a13f66b036887a",
          "body": "…ll links)\n\n- §0: README linked docs/*.md, CHANGELOG, examples/ — none ship in the npm\n  tarball, so an npm reader hit dead links. Converted to absolute GitHub URLs\n  (work on both npmjs.com and GitHub).\n- §1: SHARP-EDGES 'Routing & URL' — navigate with a real <a href>, not\n  onclick+navigate() (pre\n[…]\nve loader is now safe inside effects (the untracked fix).\n\nVerified sharp.html renders: new Routing section, 6 TOC entries, 11 cross-doc\nlinks resolve to api.html, no raw .md links, no console errors.",
          "is_bot": false,
          "headline": "docs: address review's doc findings (SHARP-EDGES callouts + npm-tarba…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T17:46:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "224a1d9b97f18561821c67e3d1fe28d8d6794f4b",
          "body": "…h is never partial)\n\nReview §5 flagged validate().value 'dropping keys not in the schema' (v0.4.8),\nranked the highest-value fix. It does not reproduce: walk() has built `out` from\n{ ...data } since before v0.4.8, so undeclared keys already pass through (declared\nones coerced) — verified against th\n[…]\n test mirroring the exact scenario (a no-rule\nfield surviving alongside coercion), plus explicit 'carries ALL keys' wording in\nthe module doc + .d.ts (pass { strict: true } to reject undeclared keys).",
          "is_bot": false,
          "headline": "validate: lock in + document that value carries undeclared keys (patc…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T17:46:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1686c1c1af82840f310e0a9be9c00a3e3559b358",
          "body": "… fetch seam\n\nTwo fixes surfaced by a real Vite/TS rewrite driving qrp as an npm dep.\n\n1. CRITICAL: the reactive in-flight counter's `loading.pending += 1` reads\n   pending. Issuing a request synchronously inside an effect() (the normal\n   refetch-on-filter-change pattern) subscribed that effect to \n[…]\nests or wrapped (retry/dedupe) without patching\n   globalThis.fetch.\n\nTests: a request inside an effect no longer re-runs it via pending; a custom\nfetch overrides the global. d.ts + CHANGELOG updated.",
          "is_bot": false,
          "headline": "http: stop createHttp leaking the loader dep into caller effects; add…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T17:35:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fde5b7d75c5ef18d8f1791043e2d802919899dd2",
          "body": "An effect that (transitively) writes state it reads looped forever: the classic\nfootgun is a loader called from an effect that sets state the same effect\ndepends on. Synchronously it recursed until the stack overflowed; with an async\nloader it spun an unbounded fetch loop ending in net::ERR_INSUFFIC\n[…]\nt option + phase 'loop'; API.md regenerated.\n- tests: runaway is stopped+reported; 50 legit re-runs never trip the guard.\n- docs/SHARP-EDGES.md + CLAUDE.md + CHANGELOG: document the guard and the fix.",
          "is_bot": false,
          "headline": "core: runaway-effect guard (loop detection) — 0.4.10",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T16:45:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f667721cea84904d30e07be28efc0fac84c517bd",
          "body": "…ss-links\n\n- styling.html renders docs/STYLING.md live (same dogfooded md renderer as\n  api/start); sharp.html does the same for docs/SHARP-EDGES.md (which the guide\n  already linked but had no rendered target).\n- generalize resolveHref across all doc pages: cross-doc .md links now map to\n  their re\n[…]\ning at the site root.\n- unified doc-page nav (Home · Guide · API · Styling · Demos · GitHub); added\n  Styling to the main site nav. Verified: all 4 pages render, no raw .md links,\n  no console errors.",
          "is_bot": false,
          "headline": "site: render STYLING (and SHARP-EDGES) on the website + unify doc cro…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T15:07:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5e0e7f8214803fedc44706ad0f5eb094f7adf35e",
          "body": "Documents the styling seam the 'helpers, not styled components' stance implies:\nthe three approaches (own CSS, the qrp.css token baseline + light/dark theming,\nor a CSS framework via class passthrough), the --qrp-* design tokens, and a\nreference of every semantic class the batteries emit (grounded in the source,\nincl. the forms classes' un-prefixed quirk). Linked from README + guide + CLAUDE.",
          "is_bot": false,
          "headline": "docs: add STYLING.md (bring-your-own CSS / qrp.css tokens / frameworks)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T14:59:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a32624ad7baa57e5bc4f77f2e61bb96c151d5c56",
          "body": null,
          "is_bot": false,
          "headline": "docs: CHANGELOG 0.4.9 (sideEffects)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T14:37:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b62594b4f0edc0a64b3926bf509364a70de8685f",
          "body": null,
          "is_bot": false,
          "headline": "0.4.9",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T14:37:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5b66dda31c30ced238ce5c173bc9596c44b62f42",
          "body": "Marks all JS side-effect-free so a consumer's bundler (webpack especially, which\nrequires the flag) drops unused re-exports — importing one util from the barrel\nno longer drags the rest in (verified: memoize-only import = 843 B, no\nvalidate/loadScript/limit/debounce). CSS kept side-effectful (**/*.css) since a\nCSS import injects styles.",
          "is_bot": false,
          "headline": "build: add sideEffects for reliable consumer tree-shaking",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T14:36:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "429f87b6cd649d7ef98708870c5f534e25de9353",
          "body": "Nav lagged the reorder: now Guide · ESP32 · Composition · Performance · Reactivity\n· Table · Data · Modules · API · GitHub — in section order, differentiators first.\nAdded the missing Composition link; every in-page anchor resolves.",
          "is_bot": false,
          "headline": "site: nav order matches new section flow (+ add Composition, drop stale)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T14:16:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3e8f417f566249c4eb65bd15f65d0ae5e1a740ca",
          "body": "Marketing order: reactivity is table stakes (assumed), so the differentiators go\nfirst — esp32 (tiny) → composition (simple) → performance (categorically fast:\n'change one field, touch one node') → reactivity (the how). Moved the perf\nsection's scattered helpers (perfData/perfSection/vsRow/perfHeadline) together\nwith its append so they define before use. Verified render + order, no errors.",
          "is_bot": false,
          "headline": "site: lead with differentiators — Performance now sits above Reactivity",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T13:06:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "da95b909c8c8fb0ff67d47d7b38adcf9a0e1efcd",
          "body": "esp32 (the 'wow' hook) → composition (how you actually build) reads as a stronger\none-two before the primitives deep-dive. Section unchanged, just reordered.",
          "is_bot": false,
          "headline": "site: move Composition section directly below the ESP32 demo",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T12:54:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b3688d3be96817d14fb2f5d0e9ca1c0ce113a433",
          "body": "…nctions\n\nShows the 'components are just functions' payoff concretely: a Card() wrapping\nField()s (each wrapping an input) plus a Toggle() factory, composed into a live\nAccount settings card with two-way bind + a save + a live state readout. Verified\nin Chromium (edit name, flip toggle, save), zero console errors.",
          "is_bot": false,
          "headline": "site: add live Composition section — a real card+form from factory fu…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T12:43:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de231f84e82ff3f59e66b91c0abc8a8a846c2949",
          "body": "Teaches the 'helpers, not components' payoff the guide was missing: a component\nis just a function returning DOM; a factory takes props (values or thunks/state)\nand returns an el() tree. Covers composition, the one-node-one-place reuse\ngotcha (why factories/thunks exist), free scope-owned cleanup + onDispose, and\nwhen to reach for scoped()/define(). Renumbered 'Where to go next' to §9.",
          "is_bot": false,
          "headline": "docs(guide): add 'Reusable components (the factory pattern)' section",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T12:41:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f502ee63a6eef29abae291145cd3eaba70abd290",
          "body": null,
          "is_bot": false,
          "headline": "chore: gitignore profiles/ (local profiler captures, never commit)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T12:35:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0157332325f398bf8eefd6ef9785e6fe910ae40d",
          "body": "…ustom domain)",
          "is_bot": false,
          "headline": "docs: point live-demo links + homepage to https://qrp.nemanja.top/ (c…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T12:34:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b15ea0c1342a224c235b571ec1a1084722adb9b9",
          "body": null,
          "is_bot": false,
          "headline": "0.4.8",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T10:24:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "52188b7b36c20e65761a6cb54033de62ee527219",
          "body": null,
          "is_bot": false,
          "headline": "docs: CHANGELOG 0.4.8 + test badges (243)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T10:24:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a1f8c262c851ed89b24b405825cbbb64f29976a5",
          "body": "The one unsupported marker position — parent.append(marker) — failed as a silent\n[object Object] text node (shipped exactly this: a whole tab pane rendering as\n[object Object], invisible to navigation-only smoke tests). Markers now carry a\ntoString() that console.warns and returns a '[qrp when() — r\n[…]\ndiagnoses at the call site.\nCan't fire in normal use (qrp routes markers via the renderable symbol before any\nString coercion). +test (happy path silent; misuse warns+breadcrumb). SHARP-EDGES\nupdated.",
          "is_bot": false,
          "headline": "feat(core): markers self-diagnose a bare DOM append (P2)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T10:24:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2c4fb6bb922ef284bf227b79939219cf33d1387e",
          "body": null,
          "is_bot": false,
          "headline": "0.4.7",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T09:18:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "700229f87b9c4c22ba75e10cedd8ae76bd9d899c",
          "body": null,
          "is_bot": false,
          "headline": "docs: CHANGELOG 0.4.7 + test badges (242)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T09:18:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e2bcd1e6d1cb316043ffb0d3f52bcc0f219b9603",
          "body": "…plementations\n\nCloses the one seam where when/list were privileged: the normalizer special-cased\ntheir brands, so a userland switchOn/virtualList needed a host element. Now child\nposition dispatches on Symbol.for('qrp.renderable') — any object with\n[renderable](parent) renders like when/list, with \n[…]\nts it without importing. +test: a userland switchOn nested inside a\nfirst-party when, no wrapper, no stranding. Docs: exported symbol +\nQrpRenderable type, CLAUDE 'small core, everything else a peer'.",
          "is_bot": false,
          "headline": "feat(core): expose the renderable protocol — when/list become peer im…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T09:17:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0a9b621b1988395869933d17cbf2a65289671f11",
          "body": null,
          "is_bot": false,
          "headline": "0.4.6",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:41:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2866a067479cd1545cc00e27eb27692b44d0f400",
          "body": null,
          "is_bot": false,
          "headline": "docs: CHANGELOG 0.4.6 + test badges (241)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:41:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6bad92c479b4a3ae898c97b9524d03f4cd958ab1",
          "body": "…M on dispose (P0)\n\nFound adopting 0.4.x: a when()/list() nested in a parent marker's branch stranded\nits DOM when the parent switched (both tabs' content stacking). Cause: the parent\nonly tracks the nodes present when IT mounted the branch; a nested marker that\nre-rendered since inserted nodes the \n[…]\n unaffected (clear() already wipes; the removes are no-ops there).\n\nWrapper divs are no longer needed as the safe idiom for nested markers. +2 tests\n(nested when->when, when->list grow/switch/return).",
          "is_bot": false,
          "headline": "fix(core)!: nested-marker teardown leak — a marker removes its own DO…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:41:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b17b8732e5e114f699297749d9e5f58a267ee112",
          "body": null,
          "is_bot": false,
          "headline": "0.4.5",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:21:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b604b5cb4bf2c470218f86ab963fb3b2be182f59",
          "body": null,
          "is_bot": false,
          "headline": "docs: CHANGELOG 0.4.5 + test badges (239)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:21:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1a495ca7d752ab053965e5cb1d60f349ce7b56df",
          "body": "The two must-have table batteries, done without regressing the static fast path:\n- fields may be a THUNK () => Column[] — a reactive column set (visibility\n  toggle, role-gated). Header + each row's cells become reactive regions that\n  re-render on change; row ELEMENTS are reused. Static arrays keep\n[…]\n Row click toggles it (interactive cells excluded); also\n  node.toggleRow(key) + reactive node.expanded. + qrp.css .qrp-expand.\n+5 tests (incl. row-reuse across column change, interactive-cell guard).",
          "is_bot": false,
          "headline": "feat(table): dynamic (reactive) columns + expandable rows (§9.6)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:20:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b6c500d50518a99c1ea61d43b79d95279d98dfa5",
          "body": null,
          "is_bot": false,
          "headline": "0.4.4",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:14:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "663d2505fc8a5ee341821e3880a376231acd23a6",
          "body": null,
          "is_bot": false,
          "headline": "docs: CHANGELOG 0.4.4 + test-count badges (236)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:14:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2807623d89d13922c7b9bd4018644fea1cb90404",
          "body": "Full control of a th's content (select-all box, filter icon…); its own clicks\nstopPropagation so they don't trigger the column sort. Overrides label. +test.",
          "is_bot": false,
          "headline": "feat(table): custom header content via field.header(column) (§9.6)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:14:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "906cd4735e936cb4ec5e99b63999aee9a93d6e50",
          "body": "The ~70-lines-per-page pager (prev/windowed-pages/next, clamp, hide at ≤1 page)\nand 'Showing X–Y of Z' summary the port rewrote every time — now stock helpers\nover a table().view (or any collection), reactive. + qrp.css baseline styles\n(.qrp-pager/.qrp-summary). +4 tests.",
          "is_bot": false,
          "headline": "feat(table): tablePager + tableSummary batteries (§9.6)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:13:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "967b94d28dd4773c306479e8f74aec8a09d188cc",
          "body": "Persist table filters/sort/page to the URL without a page rebuild: setQuery\nmerges/replaces query params (nullish removes, array repeats), defaults to\nreplace+merge, and rides the same-pattern keep-alive so currentRoute.query\nupdates reactively with no remount. +test.",
          "is_bot": false,
          "headline": "feat(router): setQuery() — query-only URL updates without remount (§4.3)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:11:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2d51c674a4a605bb84afa97f5ecbf875744aa05c",
          "body": "…name})\n\nThe 2nd handler arg was the opaque internal runner. Now it's a stable context:\n{ phase } — 'create' (first run) vs 'update' (a reactive re-run) — plus 'name'\nfrom effect(fn, { name }), for crash-report attribution/triage. +test asserts.",
          "is_bot": false,
          "headline": "feat(onEffectError): documented context { phase, name } + effect(fn,{…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:10:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6ef425ce88074f8e544a96ecf3e7813b07205d92",
          "body": "…ount appends return (§2.2)\n\n- toNodes() now materializes when()/list() markers via a fragment, so a marker\n  RETURNED from a when branch, a list render, a mount component, or a reactive\n  hole renders instead of stringifying to [object Object]. Only a bare non-qrp\n  parent.appendChild(marker) is un\n[…]\nso the\n  append-to-view style doesn't double. Done inside the mount scope so a returned\n  marker's effects are owned.\n- docs: when()/mount d.ts + SHARP-EDGES updated (no longer limitations). +6 tests.",
          "is_bot": false,
          "headline": "fix(core): markers render when returned (not just as el children) + m…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:08:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0e40aba47040adf2626d68b9a7c9e46cf632ca03",
          "body": null,
          "is_bot": false,
          "headline": "0.4.3",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:01:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "20966d4e25a40a0e0ace1ac36783706e09964a8a",
          "body": "…empty (round-three findings)\n\nFrom the production port adopting 0.4.2 (deleted both hand-rolled validators):\n- validate(schema, data, { strict }) — opt-in reject keys not in the schema,\n  recursively (default permissive, so pass-through patches keep working).\n- present-but-empty '' is now validated\n[…]\n — now deletable.\n\nAlso: add CHANGELOG.md (breaking/behavioral changes marked, newest first) — the\nport flagged three consecutive silent semantic fixes; this closes that. Linked\nfrom README. +2 tests.",
          "is_bot": false,
          "headline": "feat(validate)!: strict unknown-key rejection + validate present-but-…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T08:01:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6538f6376d2f97f2bd0c6360d52dfba8c532897f",
          "body": null,
          "is_bot": false,
          "headline": "0.4.2",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T01:12:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fc8702046b7859c52894a4c1698965348f5562cf",
          "body": "…inding)\n\nThe production port could NOT adopt validate() because its real validation sites\ncoerce ('5'→5, 'true'→true) and send the coerced patch to the server; check-only\nwould have changed the wire format. Now validate() coerces form strings toward\neach rule's declared type and returns { errors, v\n[…]\nend as the patch. Nested fields coerce too.\n\nBREAKING: validate() returns { errors, value } instead of an errors array\n(validate is one release old; pre-1.0). Docs/site/types updated. +coercion tests.",
          "is_bot": false,
          "headline": "feat(validate)!: coerce + return { errors, value } (round-two field f…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-15T01:12:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "22586768445c75575d51770074b50b59c793861a",
          "body": null,
          "is_bot": false,
          "headline": "0.4.1",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T23:22:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "63cfe8c028e1d1d4dc3aa3d717b5831e7da95123",
          "body": "0.4.0 shipped dist/utils/ WITHOUT debounce/limit/validate/load-script: build.js's\nENTRIES was a hand-maintained list and the new util files were never added, so\nthe exports './utils/*' deep subpaths pointed at files not in the tarball (the\numbrella '@nemanjan00/qrp/utils' worked; '.../utils/debounce\n[…]\n\n- build guard: assert every package.json exports subpath resolves to a built\n  dist file; fail the build (→ prepack → publish) otherwise.\n\ndist/utils now has all 8 files; verifyExportsResolve passes.",
          "is_bot": false,
          "headline": "fix(build)!: derive dist entries from filesystem + guard exports resolve",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T23:22:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1b3d0e892130cd6a9c03d5c23452ecb84c7df982",
          "body": "The utils overview prose was stale — it listed only the original helpers, not\nlimit/debounce/throttle/validate/loadScript or memoize's ttl/invalidate (the\nper-export entries were present; only the intro undersold them). Note the barrel\nimport for both modules and the scoped() modal caveat for behaviors. Regenerated.",
          "is_bot": false,
          "headline": "docs: refresh utils/behaviors module overviews in API.md",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T23:18:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "050e4d1dfd12134c0a54998bc7eef3cb13f5ea99",
          "body": "…utils/routing snippets)\n\n- site: live 'Dashboard utilities' section — a debounced search (keystrokes fire\n  every time; the search waits for a pause), verified in Chromium. Highlighter +\n  importmap updated for the new utils.\n- README: value-keyed when() tab example; new snippets for debounce/limit/\n  validate, responseType, currentRoute/scoped/onEffectError; keep-alive note.",
          "is_bot": false,
          "headline": "site,readme: showcase 0.4 features (debounce demo, value-keyed when, …",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T23:11:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c472d135db61d1ad195620aea0765075672c7e89",
          "body": "… KB library)\n\nNew exports (currentRoute, onEffectError, scoped; validate, loadScript,\nlimit/debounce, memoize ttl) grew the core to ~3.9 KB min+gzip and the whole\nlibrary to ~16.8 KB. README badge/copy, index.html meta/hero/footer updated.\nBenchmarks re-verified: single-cell still ~0.8 us / 1 node of 40,002; suite\nratios unchanged within noise — no table change needed.",
          "is_bot": false,
          "headline": "docs: update size claims to measured 0.4.0 figures (~3.9 KB core, ~17…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T23:07:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b02926a12717ad695fdf0e07ac78d7e372c884f7",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump test-count badges to 225",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T23:03:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1a4cbe83a4abd494d67079b7b5b4516ec925a7cc",
          "body": null,
          "is_bot": false,
          "headline": "0.4.0",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T23:03:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae030cc73c4f16814fbb4cb0bcb6c7943da25109",
          "body": "- docs/SHARP-EDGES.md: the handful of behaviors worth knowing once (raw-array\n  mutation, node-lives-once, marker-as-child, value-keyed when, unique list keys,\n  scoped() for handler-built UI, http reject shape, SPA serving) — reflecting the\n  CURRENT post-fix state, not the report's pre-fix list. Linked from README +\n  Getting Started.\n- README/CLAUDE.md/site utils listings updated (validate, loadScript, memoize\n  ttl). API.md regenerated.",
          "is_bot": false,
          "headline": "docs: add SHARP-EDGES.md + sync README/CLAUDE/site for new utils (§8.2)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T23:02:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ada320501607f98c17241fc105a7358c9e860e4",
          "body": "… §6.2)\n\n- utils/validate.js: tiny declarative schema validator (required/type/min/max/\n  enum/pattern/custom check/nested fields) → [{path,message}]. Pairs with forms;\n  the zero-build answer to joi/zod for PATCH payloads.\n- utils/load-script.js: inject a UMD/global <script> once (deduped), reactiv\n[…]\n — the honest hatch for Chart.js et al. under an\n  import-map app.\n- behaviors/anchored: { matchWidth } sizes the floating element to its trigger\n  (dropdown-spans-input).\n+4 tests, API.md 76 exports.",
          "is_bot": false,
          "headline": "feat(utils,behaviors): validate, loadScript, anchored matchWidth (§7,…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T23:01:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "895d7cb62ba893d2da7064df6396c827e9b9a668",
          "body": "The generator listed supporting types by NAME only — the gap that shipped the\ndisclosure() bug (readers assumed d.open was a boolean, not a method). Now it\ncaptures each exported interface/type's FULL definition (brace-matched), incl.\nundocumented ones (second pass), and emits them as code blocks under a\n'Supporting types' heading. Bumped the api.html/start.html markdown renderers to\nh4 + styled it. Disclosure's { state:{open}, toggle(), open(), close() } shape\nnow visible.",
          "is_bot": false,
          "headline": "docs(gen)!: inline supporting-type definitions in API.md (§8.1)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:59:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80eeca1ac7e1eac8353d5d7057f6172d150c531e",
          "body": "- memoize: options.ttl expires entries (post-resolve for promises); the returned\n  fn gains .invalidate(...args) (one key) / .invalidate() (all). Covers the\n  refetch-with-TTL + bus-driven-invalidation pattern hand-rolled in the port.\n- lru: add clear().\n- scoped(fn) -> { value, dispose }: build UI \n[…]\nutside a render (a modal from an\n  onclick) with owned effects instead of ownerless leaks (§6.1). ESP32 demo's\n  scan modal now uses it — its when()/list() effects tear down with the modal.\n\n+4 tests.",
          "is_bot": false,
          "headline": "feat: memoize ttl+invalidate, lru.clear, scoped() sugar (§7, §6.1)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:56:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0b509670698f32883b497e664d08ca2a6db27058",
          "body": "BREAKING (behavioral): when a navigation matches the SAME route pattern (a\nparam/query change — e.g. switching :tab on /users/:pk/:tab), the router no\nlonger tears down and remounts the page. In-pane state (form edits, scroll,\nexpanded rows) survives and the handler reacts through the reactive currentRoute;\nno refetch churn. A different pattern still fully remounts. Pass\nrouter(..., { remount: true }) to restore always-remount.\n\n+2 tests.",
          "is_bot": false,
          "headline": "feat(router)!: keep-alive on same-pattern navigation (§4.2)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:52:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9869aafe3f93b263ca075d4d90728510e4827d85",
          "body": "…c, §5.1b)\n\n- table: custom render() cells are now reactive — re-run when the row's item is\n  replaced (refetch), so action cells reflect fresh state instead of the item\n  they were built with. (Was: built once per key.)\n- forms: form() renders the FIELDS spec, not Object.keys(settings) — a field\n  \n[…]\njects created, bound two-way) and seeds defaults\n  along the path. With no fields, keeps the reactive-key-set fallback.\n\nBREAKING: form() structure is now fields-driven when fields is given. +6 tests.",
          "is_bot": false,
          "headline": "feat(table,forms)!: reactive render cells + fields-driven forms (§2.3…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:51:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "604513728342351e59c0b79fdb342d3a3e4dfca9",
          "body": null,
          "is_bot": false,
          "headline": "test(list): cyclic-object rebind terminates (loop safety regression)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:47:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cba5465b9f2b15b57e0dace84ed85005a17c0005",
          "body": "… §2.4)\n\nBREAKING (behavioral): a row whose key survives a refetch now reflects the fresh\nobject instead of the one captured when the row was built. The merge is a\nDEPTH-LIMITED recursion (REBIND_DEPTH=8): it recurses into nested plain objects\nso their proxy identity is preserved (a captured `const \n[…]\nic subtrees fall back to reference assignment. Same-identity rows still\nupdate in place through their own bindings.\n\nAnswers the reviewer's §2.3 staleness trap and the nested-object concern. +3 tests.",
          "is_bot": false,
          "headline": "feat(list)!: rebind surviving rows via bounded recursive merge (§2.3,…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:46:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "05d5b1afc56b8a91f1c3bc276bf635f2871191a8",
          "body": "… (§2.1)\n\nBREAKING: when() now re-renders the branch when the condition's VALUE changes\n(Object.is), not only when truthiness flips. This makes value-switches work\ndirectly — when(() => state.tab, tab => TABS[tab]()) re-renders on every tab,\nthe pattern that previously shipped a bug (stuck on the fi\n[…]\nue change rebuilds.\n\nMigration: code relying on when() NOT rebuilding across distinct truthy values\nshould key on a boolean instead (when(() => !!x, ...)). Boolean conditions are\nunaffected. +2 tests.",
          "is_bot": false,
          "headline": "feat(when)!: value-keyed rendering — re-render when the value changes…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:42:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a72052769746f32ed8434f9a00534bfc51d6cfe7",
          "body": "…1/§2.2)\n\nCompletes the 'skip the behavior change, document the gotcha' half for the two\nthat shipped bugs in the field report: when() swaps on truthiness not value\n(so it won't switch between truthy tabs — branch per value), and markers are\nonly valid as el()/html children. Regenerated API.md.",
          "is_bot": false,
          "headline": "docs: loudly document when() truthiness trap + marker-child rule (§2.…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:38:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "95a8fb084395cc71c9ac9eeac31fd91aed2bba69",
          "body": null,
          "is_bot": false,
          "headline": "0.3.0",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:36:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "202831e5223bb69e9bce3c52068f1b294b4e4bbe",
          "body": "…pe, utils limit/debounce/throttle, forms style passthrough\n\nAdditive changes from a production port's punch list (no breaking semantics):\n\n- core: onEffectError(handler) — central hook fired before a throwing effect's\n  error propagates (wire Sentry etc.); today a throwing binding is only visible\n \n[…]\nal), types-suite usage, API.md regenerated (73 exports),\nREADME/site/CLAUDE.md synced. Skipped (need design, would break behavior):\nwhen() value-keying, list()/table render-cell rebind, nested routes.",
          "is_bot": false,
          "headline": "feat: field-report P0s — onEffectError, currentRoute, http responseTy…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:36:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d8153a6c58ace5273d19ff17ca22a0eeaf7317a5",
          "body": null,
          "is_bot": false,
          "headline": "chore: gitignore local field notes (never commit/publish)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T22:23:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bb2078b973ceb1a30a706233b2f0ab5a3b1efb11",
          "body": "…ast)\n\nThe old toasts demo sent a static html snippet — it didn't show the actual\ntrick. Now 'Delete last' emits a toast whose content is a live el() node with\na working Undo button; the node travels over the bus (bus.emit('warning', node))\nand the toast layer renders it, handler and all. Undo restores the item and\nfires a success toast. Builds a fresh node per emit (a DOM node lives in one\nplace). Reframes the section as 'Renderables over the bus'.",
          "is_bot": false,
          "headline": "site: demo sending a live DOM node over the event bus (Undo action to…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T20:32:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ee3caee84528c85ee6514d832436d41c61286c33",
          "body": "…orners\n\n- sparkline: derive() the history min/max ONCE per tick instead of every one\n  of the 40 bars re-scanning the whole array twice (was 80 scans to move 40\n  bars — the opposite of the fine-grained pitch). Now one scan feeds 40 bindings.\n- modal: make close/pick local to each openScan() so they close over that\n  invocation, not a module-scoped reassigned handle — the pattern stays correct\n  if copied for a second modal. Compose the three behaviors' teardowns into one.",
          "is_bot": false,
          "headline": "examples(esp32): tighten the two spots exemplary code shouldn't cut c…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T20:24:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ec42b8f86d1c954f14376402ee3dadd53ac86003",
          "body": "- docs/GETTING-STARTED.md: a ten-minute, zero-to-dashboard tutorial covering\n  the five core ideas (state/effect, el, derive, when, list) then a full small\n  dashboard, with a 'where to go next' map into the module docs.\n- start.html: renders the guide live with the same qrp markdown renderer as\n  a\n[…]\n in api.html/start.html (link-in-text-block).\n- wire links: README header + Install note, index.html nav + hero 'Get\n  started' CTA, api.html nav.\n- CLAUDE.md: document the guide + start.html pattern.",
          "is_bot": false,
          "headline": "docs: add Getting Started guide + rendered start.html page",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T20:17:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a1a679b73d550a95e3fb35999c8ddf79771a4fe7",
          "body": null,
          "is_bot": false,
          "headline": "0.2.1",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T20:02:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57334a7be17992f75f106dfd4e0282f8c2100924",
          "body": "Leftover from the original form-only demo; the reworked live dashboard is\n~6 KB gzipped, as the panel next to it already states.",
          "is_bot": false,
          "headline": "site: fix stale ESP32 flash size in code comment (~4 KB -> ~6 KB)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T20:01:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5622b43d40f7e85dfd3b7f1b036e636d6cf9ccf2",
          "body": "Audited all three pages (site, api.html, esp32 dashboard) with Lighthouse.\n\nAccessibility -> 100:\n- forms: field() now associates its <label> with the control via for/id\n  (only for labelable INPUT/SELECT/TEXTAREA, not the radio-group wrapper) —\n  fixes the Lighthouse select-name/label failures at t\n[…]\nO -> 100: meta description on the esp32 dashboard.\n\nFinal: site 98/100/100/100 (2 perf pts are the intentional raw-source load),\napi 100/100/100/100, esp32 100/100/100/100 — for a client-rendered SPA.",
          "is_bot": false,
          "headline": "a11y + perf: Lighthouse 100 on api & esp32, 98/100/100/100 on site",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T19:57:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8dac45759bd807b914764116211e8c40e0507443",
          "body": "A static settings form is the weakest pitch for a reactive framework, so make\nthe demo show what only reactivity can do:\n- live telemetry (temp/humidity/rssi/heap) streaming into bindings + sparkline\n- LED toggle + brightness slider that write to the device\n- config form that rewrites itself via whe\n[…]\nKB gzipped blob\n- reframe README + site section (live dashboard, not a form); iframe gets a title\n\nFixes the qrp gotcha of mixing native append() with when()/list() markers\n(build the tree with el()).",
          "is_bot": false,
          "headline": "examples(esp32): rework into a live reactive dashboard + WiFi-scan modal",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T19:38:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "032c8a0146d289e246b600f849f78ec9afd0469c",
          "body": "… & site\n\n- examples/esp32/: form() as a full device config UI, bundled + minified +\n  gzipped into a ~4 KB PROGMEM blob served from flash. PlatformIO project\n  (platformio.ini + src/main.cpp), build.js (bundle->minify->inline->gzip->\n  PROGMEM header), self-contained dashboard.html doubles as the l\n[…]\n extreme case' section after the hero — main.cpp serve snippet\n  beside a live iframe of the actual dashboard; nav link added.\n- fix README keyed-list sample: () => view.items() (items() is a method).",
          "is_bot": false,
          "headline": "examples: add ESP32 self-hosted settings dashboard + wire into README…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T19:24:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f5c5c80c6499e0fcba83e11a0fad899992e5f13f",
          "body": null,
          "is_bot": false,
          "headline": "0.2.0",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T19:15:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80672759ab7ce63666b50cda1e983d63d46cf998",
          "body": "- bin/build.js: esbuild bundle+splitting per subpath -> dist/ (shared core\n  chunk), minified. npm run build; also prepack so pack/publish rebuild it.\n- package.json: exports.default -> dist/*.js, exports.types -> hand-written\n  .d.ts; files ships dist + .d.ts + css, NOT raw source; esbuild devDep.\n\n[…]\n correct all size claims to measured figures: core ~3.7 KB min+gzip\n  (was quoting ~12 KB raw-gzip), whole library ~15 KB; honest raw-source\n  clause in README. Update CLAUDE.md (docs+build pipeline).",
          "is_bot": false,
          "headline": "build: ship minified, code-split dist/ on npm (~3.7 KB min+gzip core)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T19:13:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e32e6f7653001a4c895b6ea7c36ae75b4aba1da3",
          "body": null,
          "is_bot": false,
          "headline": "0.1.1",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T19:02:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3970b677ebc87be173531a11c516a54c434c6131",
          "body": "- npm version + license badges, npm link in quick-links\n- LICENSE (MIT) + license field in package.json + License section",
          "is_bot": false,
          "headline": "readme: npm badge + link; add MIT license",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T19:02:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b8f140c42beaa094eaddd88936edc26e585942a2",
          "body": "- package.json: scoped name, exports map (clean subpaths + types), files\n  allowlist, publishConfig.access=public, repo/homepage/keywords/author\n- README + generated API.md + site + examples: import from @nemanjan00/qrp[/sub]\n- demo HTML pages gain a <script type=\"importmap\"> so the bare specifiers\n\n[…]\noped specifiers so docs stay single-sourced\n\nqrp was taken on npm; scoped keeps the brand. Verified: all demo pages boot\nunder the import maps, typecheck + lint clean, npm pack ships 47 runtime files.",
          "is_bot": false,
          "headline": "publish: rename package to @nemanjan00/qrp, wire clean subpath imports",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T19:00:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "910bdc1b7fea47d9bd02254f72f778c5af5784b5",
          "body": "Runs on push to master/main and every PR, matrix over Node 22 & 24\n(node --test glob needs Node >= 21). Adds a CI status badge to the README.",
          "is_bot": false,
          "headline": "ci: add GitHub Actions workflow (lint + typecheck + test)",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T18:47:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8683e88d410f4ba9a315e6beead59ded20627df6",
          "body": "- assets/qrp-logo.svg: wordmark (r in accent) + QRP radio-wave mark,\n  matched to the site palette (#0a0d12 / #ffb23e / #34d399)\n- centered header: shields.io badges (deps/build/size/tests/types),\n  live-demo + API + quick-jump links\n- emoji icons on every section heading; proto row lists onceOnly",
          "is_bot": false,
          "headline": "readme: add logo, badges, section icons, live-demo links",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T18:46:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "64f419bcde72272ec6dbd0531fe3b8aa7647fcf5",
          "body": "The proto module (wrapMethod/delegate/onceOnly) shipped and tested but never\nappeared on the marketing site — not even as a module card. Add a live\nwrapMethod demo (idempotent prototype patch, the userscript trick) and the\nmissing grid card.",
          "is_bot": false,
          "headline": "site: add Prototypes section + module card for the proto module",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T18:40:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b74088c4f3ddd318cf02578a0713721c53801b5f",
          "body": "- add bin/gen-api.js: parse .d.ts doc-comments -> docs/API.md\n- backfill @module overviews across satellite .d.ts so curated prose\n  (html escaping guarantee, forms FieldSpec/types, http error shape) lives\n  in one place and flows through the generator\n- enrich qrp/index.d.ts: list() thunk source contract, effect/derive edge\n  cases, el() prop-rule subsection, scope-vs-mount guidance\n- wire npm run docs",
          "is_bot": false,
          "headline": "docs: generate API.md from .d.ts single source",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T18:37:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "10b26d4d927cd0b393e0967f64467b8c86580934",
          "body": "- api.html: a browsable API reference — sticky sidebar TOC, filterable search,\n  styled tables/code — rendered at runtime from docs/API.md by a compact\n  Markdown→DOM renderer built with qrp itself (el/list/state, no md library).\n  The site DERIVES from the markdown: one place to update, no duplicat\n[…]\number + the minified\n  context, not the flattering stale figure.\n\n- CLAUDE.md: documented the types/docs setup and the JSDoc-as-single-source\n  north star (generate .d.ts + md from JSDoc — next step).",
          "is_bot": false,
          "headline": "API reference page (renders docs/API.md live) + accurate size numbers",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T18:22:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1658fe32a56140934bba630cc1f2e2a0abc26160",
          "body": "Ship types for the whole surface, hand-written next to each ESM module so\nimporting \"./qrp/index.js\" resolves ./qrp/index.d.ts — no @types package, no\nbuild step, no change to how qrp is loaded.\n\n- .d.ts for qrp, html, forms, collection, table, http, events, toasts, browser,\n  each behaviors/* and u\n[…]\nerence — every export, signature, and a usage snippet\n  per module, plus the escaping guarantee and a TypeScript section.\n\ntypecheck passes; lint clean; 192 tests. .eslintignore excludes the .ts test.",
          "is_bot": false,
          "headline": "Add TypeScript declarations (.d.ts) for every module + API reference",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T18:14:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c82c909757c0ae9dfde824f5b839032a3f347a5b",
          "body": "Same class as the markup-demo fix, in the section whose lede promises \"disposes\nthe previous route's scope on navigation.\" It did the opposite: it hand-rolled\noutlet.replaceChildren() + mount() inside an effect and never kept the disposable\nmount() returns — so every tab click stranded the previous \n[…]\ne outlet) — which is exactly\nwhat the real router() does on navigation. Verified in Chromium: switching\nthrough all routes leaves exactly one view in the outlet (no accumulation), zero\nconsole errors.",
          "is_bot": false,
          "headline": "Router demo: dispose the mount handle instead of hand-rolling + leaking",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T18:02:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb894b9a65eb07eb1a0989f5a98315609b7fcb54",
          "body": "1. Removed the duplicate storable-templates section — #templates (Grace Hopper)\n   and #storable (card list) demoed the same feature. Kept the richer #storable\n   (list() + add-row).\n\n2. Markup demo now uses when() for the tab switch instead of a hand-rolled\n   IIFE + effect + replaceChildren — dogf\n[…]\nno longer contradicts the numbers below it.\n\nVerified in Chromium: one templates section, one viewport meta, badges/footer at\n192, markup when()-switch works, theme swatch reacts, zero console errors.",
          "is_bot": false,
          "headline": "Fix the remaining five site issues from review",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T18:00:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0961cca28a9772165110e4805f0296668eab0833",
          "body": "1. Perf chart no longer drops the two worst numbers. It now shows all EIGHT ops\n   the README shows — including create 10k (1.3×) and clear 10k (1.8×), the one\n   I explicitly called the honest weak spot. Omitting it after naming it was the\n   kind of thing that taints the numbers you did show. 1.8×\n[…]\nse to GitHub on narrow screens, the\n   table scrolls horizontally in its own box, and section/bar/code spacing scales\n   down. Verified at 390px: zero horizontal page overflow.\n\n192 tests still green.",
          "is_bot": false,
          "headline": "Site perf/table/responsive fixes from review",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T17:51:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e774392bb07fc764c98154eab0c8be8a3a68506a",
          "body": "A 1000× claim invites a fight; answer the top-comment objections before they're\nraised, in both places people look:\n\n- flushSync: answered in react-compare.html AND the README. flushSync doesn't\n  add work — it stops batching from smearing the reconcile across a later frame\n  so it can be timed. Con\n[…]\ned. That walk is the ~800µs. The number\n  defends itself.\n\n\"You wrote slow React\" (per-row stores narrow it) folded in as the second\nanswered objection. No code changes; docs/comments only. 192 tests.",
          "is_bot": false,
          "headline": "Preempt the two objections to the 1000× number",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T17:28:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5a20fbd89c3f35fe7b77d865ef5ecabe40c2d7ed",
          "body": "…ity pass\n\nAddresses a review of the README/site — every ask was to replace an assertion\nwith evidence:\n\n- MEASURED the virtual-DOM claim. Vendored React 18 (production) and a fair\n  memoized+keyed 10k-row table (examples/react-compare.html). Same single-cell\n  update, same MutationObserver: qrp ~0.\n[…]\ns 8ms paint → ~10% reactivity).\n\n- clear() 1.8× called out as the honest weak spot.\n\nSite perf shows qrp-vs-React bars. .eslintignore excludes examples/vendor/\n(the React production build). 192 tests.",
          "is_bot": false,
          "headline": "Measure the categorical claim (React), XSS test file, README credibil…",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T17:24:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e6c8362499e46029c2f795702c22a77258143140",
          "body": "Site (index.html):\n- Performance section now LEADS with the categorical stat — \"1 DOM node touched\n  of 40,002\" when you change one field in a 10k-row table — big, with the honest\n  framing (~0.8µs, no diff, no re-render, O(1); the win is vs virtual-DOM, not\n  vs hand-written vanilla). Full suite ba\n[…]\nment\n(1 node of 40,002, ~0.8µs) and an explicit honest footnote — it's a win over\nvirtual-DOM frameworks, NOT over hand-optimized vanilla (270–460ns), and we say\nso. Full paint-timed suite kept below.",
          "is_bot": false,
          "headline": "Marketing site: single-cell headline + demo every feature; README perf",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T17:14:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "48a74050ef9b7e83d42c9de854fd825a9e832c2a",
          "body": "- Reactive text holes now update the existing text node's data IN PLACE (both\n  qrp core and html) instead of remove+insert. Changing one cell in a 10,000-row\n  table touches exactly 1 DOM node (was 3), and is faster (1.3µs → 0.8µs). The\n  effect closure already holds the node reference — no lookup,\n[…]\n it.\n\n- Removed utils/round-robin.js and utils/weighted-pool.js — load-balancer\n  helpers that don't serve dashboards. \"Do one thing well.\" utils is now\n  memoize / lru / cache / paginate.\n\n185 tests.",
          "is_bot": false,
          "headline": "In-place text updates; single-cell benchmark; cut load-balancer utils",
          "author_name": "Nemanja Nedeljkovic",
          "author_login": "nemanjan00",
          "committed_at": "2026-07-14T17:10:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        }
      ],
      "releases_count": 21,
      "commits_last_year": 118,
      "latest_release_at": "2026-07-17T00:27:34Z",
      "latest_release_tag": "v0.7.0",
      "releases_from_tags": true,
      "days_since_last_push": 4,
      "active_weeks_last_year": 1,
      "days_since_latest_release": 4,
      "mean_days_between_releases": 0.2
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@nemanjan00/qrp",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "dashboard",
            "reactive",
            "proxy",
            "declarative",
            "framework",
            "frontend",
            "no-build",
            "zero-dependency",
            "dom",
            "forms",
            "table"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@nemanjan00/qrp",
          "is_deprecated": false,
          "latest_version": "0.7.0",
          "repository_url": "https://github.com/nemanjan00/qrp",
          "versions_count": 18,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 2683,
          "first_published_at": "2026-07-14T19:00:34.180000Z",
          "latest_published_at": "2026-07-17T00:27:41.501000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 4
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 46054,
      "source_files_sampled": 84,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 15489
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 0,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "nemanjan00",
          "commits": 118,
          "avatar_url": "https://avatars.githubusercontent.com/u/448151?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        ".eslintrc.json"
      ],
      "has_editorconfig": true,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "package-lock.json"
      ],
      "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 6 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": 0,
            "reason": "no 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": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 3,
            "reason": "dependency not pinned by hash detected -- score normalized to 3",
            "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": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "ea7183479bbd1581280f33be6d5428ffd9c323c9",
        "ran_at": "2026-07-21T16:52:08Z",
        "aggregate_score": 3.2,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/nemanjan00/qrp",
    "host": "github.com",
    "name": "qrp",
    "owner": "nemanjan00"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 55,
      "inputs": {
        "security": 32,
        "vitality": 68,
        "community": 32,
        "governance": 42,
        "engineering": 93
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "moderate",
        "name": "Vitality",
        "value": 68,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "commits_last_year": 118,
              "human_commit_share": 1,
              "days_since_last_push": 4,
              "active_weeks_last_year": 1
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 4 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "1/52 weeks with commits",
                "points": 0.7,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "118 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 118
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "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": 88,
            "inputs": {
              "releases_count": 21,
              "latest_release_tag": "v0.7.0",
              "releases_from_tags": true,
              "days_since_latest_release": 4,
              "mean_days_between_releases": 0.2
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "21 version tags (no GitHub releases)",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "version_tags_no_releases",
                    "params": {
                      "count": 21
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 4 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~0.2 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0.2
                    }
                  }
                ],
                "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": 32,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "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": 57,
            "inputs": {
              "packages": [
                "@nemanjan00/qrp"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 2683
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "2,683 downloads/month across npm",
                "points": 45.7,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 2683,
                      "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": "at_risk",
        "name": "Sustainability & Governance",
        "value": 42,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "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": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 6 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution",
                    "pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "merged_prs": 0,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "no decided pull requests or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_decided_prs_or_data",
                    "params": {}
                  }
                ],
                "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": 62,
            "inputs": {
              "followers": 117,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "nemanjan00",
              "public_repos": 233,
              "account_age_days": 5752
            },
            "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": "117 followers of nemanjan00",
                "points": 14.9,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 117,
                      "login": "nemanjan00"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "233 public repos, account ~15 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 233
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 15
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@nemanjan00/qrp"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 4
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 4 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 4
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "18 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 18
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "excellent",
        "name": "Engineering Quality",
        "value": 93,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "excellent",
            "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": 88,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": true,
              "has_linter_config": true,
              "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": ".eslintrc.json",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".eslintrc.json"
                    }
                  }
                ],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 6.4,
                "status": "met",
                "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": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "topics": [
                "dashboard",
                "declarative",
                "dom",
                "forms",
                "framework",
                "frontend",
                "no-build",
                "proxy",
                "reactive",
                "table",
                "zero-dependency"
              ],
              "has_wiki": true,
              "homepage": "https://qrp.nemanja.top/",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://qrp.nemanja.top/",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "11 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 11
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 32,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 32,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 15,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 3,
              "scorecard_aggregate": 3.2
            },
            "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 6 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": "no update tool detected",
                "points": 0,
                "status": "missed",
                "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": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 3",
                "points": 1.5,
                "status": "partial",
                "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": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "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": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 3
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 67,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.86,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 15489
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "86 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 86,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 57,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "package-lock.json"
              ],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "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": ".eslintrc.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".eslintrc.json"
                    }
                  }
                ],
                "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": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "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 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "good",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "primary_language": "JavaScript",
              "largest_source_bytes": 46054,
              "source_files_sampled": 84,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "JavaScript with type-check config (tsconfig.json)",
                "points": 27,
                "status": "partial",
                "details": [
                  {
                    "code": "typecheck_config_language",
                    "params": {
                      "files": "tsconfig.json",
                      "language": "JavaScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/84 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 84,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
    "deps.dev does not index npm:@nemanjan00/qrp@0.7.0; advisories assessed against the repository dependency graph instead"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-21T16:52:13.105613Z",
  "schema_version": "0.23.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/n/nemanjan00/qrp.svg",
  "full_name": "nemanjan00/qrp",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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