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

dereuromark / cakephp-queue-scheduler

CakePHP Addon for Queue plugin to schedule commands and queue tasks as crontab like DB solution

PHPMIT★ 7 зірок⑂ 0 форківз жовт. 2023 р.Переглянути на GitHub ↗

dereuromark/cakephp-queue-scheduler має індекс здоров’я 65 зі 100, що відповідає смузі «Помірний». Найвищий показник — Vitality (86/100), найнижчий — Community & Adoption (42/100). Останнє оновлення було 30 днів тому. Більшість нещодавньої роботи виконує один учасник.

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

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

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

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

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

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

Власність

Mark SchererОсобистий обліковий запис
750 підписників123 публічні репозиторіїз груд. 2008 р.Available as (Cake)PHP expert

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

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

РеєстрПакетВерсіяЗавантажень / місВерсіїОстання публікаціяТеги
Packagistdereuromark/cakephp-queue-scheduler0.3.64 6142660 днів томуqueueplugincroncakephpautomationadmin-panelrecurringschedulerstandalone-ui

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

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

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

86Відмінний · 22% загального індексу
Як обчислюється оцінка
28.8/36Свіжість push — останній push 30 дн. тому
20.1/36Ритм комітів — 29/52 тижнів із комітами
18/18Обсяг комітів — 110 комітів за останній рік
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
Використані вхідні дані
commits_last_year110
human_commit_share1
days_since_last_push30
active_weeks_last_year29
Як обчислюється оцінка
27/27Випускає релізи — опубліковано 26 релізів
36/36Свіжість релізів — останній реліз 60 дн. тому
27/27Ритм релізів — реліз кожні ~13,7 дн.
0/10OpenSSF Scorecard: Signed-Releases — немає даних
Використані вхідні дані
releases_count26
latest_release_tag0.3.6
releases_from_tagsні
days_since_latest_release60
mean_days_between_releases13,7
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: Signed-Releases. Залишкові ваги перенормовано.

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

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

42У зоні ризику · 18% загального індексу
Як обчислюється оцінка
12.6/60Зірки — 7 зірок
0/25Форки — 0 форків
0/15Спостерігачі — 1 спостерігачів
Використані вхідні дані
forks0
stars7
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Як обчислюється оцінка
22.5/22.5README
22.5/22.5Ліцензія — визнана ліцензія (MIT)
18/18Настанови CONTRIBUTING
0/13.5Кодекс поведінки
0/7.2Шаблон issue
0/6.3Шаблон PR
Використані вхідні дані
has_readmeтак
has_licenseтак
has_contributingтак
has_issue_templateні
has_code_of_conductні
has_pull_request_templateні
Як обчислюється оцінка
48.9/80Щомісячні завантаження — 4 614 завантажень/місяць у packagist
2/20Залежні пакети в реєстрі — залежних пакетів: 1
Використані вхідні дані
packagesdereuromark/cakephp-queue-scheduler
dependents1
ecosystemspackagist
total_downloads22 287
monthly_downloads4 614

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

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

62Помірний · 24% загального індексу
Як обчислюється оцінка
9/54Бас-фактор — на 1 контриб’ютор(ів) припадає половина всіх комітів
0/22.5Розподіл комітів — головний контриб’ютор — автор 100% комітів
1.4/13.5Широта контриб’юторів — 1 контриб’юторів
10/10OpenSSF Scorecard: Contributors — project has 3 contributing companies or organizations -- score normalized to 10
Використані вхідні дані
bus_factor1
contributors_sampled1
top_contributor_share1
Як обчислюється оцінка
40.1/46.8Вирішення issue — закрито 86% issue
34.6/38.3Прийняття PR — злито 38/42 вирішених PR
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Використані вхідні дані
merged_prs38
open_issues1
closed_issues6
issue_closed_ratio0,857
closed_unmerged_prs4
Як обчислюється оцінка
10/30Підтримка власника — особистий (користувацький) обліковий запис
0/20Верифікований домен — не застосовно до користувацьких облікових записів
20.7/25Охоплення власника — 750 підписників у dereuromark
25/25Послужний список — 123 публічних репозиторіїв, вік облікового запису ~17 р.
Використані вхідні дані
followers750
owner_typeUser
is_verified
owner_logindereuromark
public_repos123
account_age_days6 437
Виключено з оцінювання (немає даних або не застосовно): Верифікований домен. Залишкові ваги перенормовано.

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

100Відмінний
Як обчислюється оцінка
25/25Опубліковано й доступно — 1 пакет(ів) у packagist
35/35Свіжість публікацій — остання публікація 60 дн. тому
20/20Історія версій — 26 опублікованих версій
20/20Не застарілий — активний, не deprecated і не yanked
Використані вхідні дані
packagesdereuromark/cakephp-queue-scheduler
ecosystemspackagist
any_deprecatedні
min_days_since_publish60

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

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

84Добрий · 20% загального індексу
Як обчислюється оцінка
24/24Процеси CI — 1 процес(ів) CI
24/24Наявні тести
16/16Конфігурація лінтера — phpcs.xml, phpstan.neon
0/9.6Pre-commit-хуки
6.4/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 15 out of 15 merged PRs checked by a CI test -- score normalized to 10
Використані вхідні дані
has_ciтак
has_testsтак
has_editorconfigтак
has_linter_configтак
has_precommit_configні
Як обчислюється оцінка
30/30README
25/25Каталог документації
0/15Сайт документації / домашня сторінка
10/10Опис репозиторію
0/10Теми
10/10Wiki
Використані вхідні дані
topics
has_wikiтак
homepage
has_readmeтак
has_docs_dirтак
has_descriptionтак

Безпека

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

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

Стан безпеки

44У зоні ризику
Як обчислюється оцінка
7.5/7.5Binary-Artifacts — no binaries found in the repo
0.8/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 15 out of 15 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 3 contributing companies or organizations -- score normalized to 10
0/10Dangerous-Workflow — немає даних
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Ліцензія — license file detected
7.5/7.5Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — немає даних
0/5Pinned-Dependencies — немає даних
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — немає даних
0/7.5Token-Permissions — немає даних
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Використані вхідні дані
sourceopenssf_scorecard
checks_evaluated13
scorecard_versionv5.5.0
checks_inconclusive5
scorecard_aggregate4,4
Виключено з оцінювання (немає даних або не застосовно): dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions. Залишкові ваги перенормовано.

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

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

43У зоні ризику · 0% загального індексу
Як обчислюється оцінка
0/45Інструкції для агентів — немає CLAUDE.md / AGENTS.md / правил редактора
0/15Машиночитана документація (llms.txt)
37.3/40Читабельна історія комітів — намір зазначено у 70 з 100 людських комітів (структурований заголовок або пояснювальний текст)
Використані вхідні дані
has_llms_txtні
legible_history_share0,7
agent_instruction_files
agent_instruction_max_bytes
Як обчислюється оцінка
0/18Розгортання однією командою
22/22Автоматизовані тести
11/11Конфігурація лінтера / форматера — phpcs.xml, phpstan.neon
0/11Статична перевірка типів
0/10Відтворюване середовище
6/10Підтверджена практика роботи з агентами — 3 з останніх 100 комітів створено агентом або з його зазначенням
0/8Автоматизоване супроводження — автоматичних оновлень залежностей не виявлено
0/10OpenSSF Scorecard: Pinned-Dependencies — немає даних
Використані вхідні дані
has_nixні
has_testsтак
lockfiles
has_dockerfileні
typed_languageні
bootstrap_files
has_devcontainerні
has_linter_configтак
typecheck_configs
agent_commit_share0,03
toolchain_manifests
dependency_bot_commit_share0
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: Pinned-Dependencies. Залишкові ваги перенормовано.
Як обчислюється оцінка
0/45Типізований код — PHP без конфігурації перевірки типів
55/55Керовані розміри файлів — 0/66 файлів вихідного коду понад 60 КБ
Використані вхідні дані
primary_languagePHP
largest_source_bytes34 351
source_files_sampled66
oversized_source_files0

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

7зірок GitHub
1контриб'юторів
110комітів за останні 12 місяців
30днів від останнього пушу
26релізів
1бас-фактор
1відкритих issue
Packagistпакетних екосистем

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

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • No resolved dependencies carried a version and a supported ecosystem

Докладніше

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

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

10Binary-Artifactsno binaries found in the repo
1Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests15 out of 15 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
10Contributorsproject has 3 contributing companies or organizations -- score normalized to 10
н/дDangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
н/дPackagingpackaging workflow not detected
н/дPinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
н/дSigned-Releasesno releases found
н/дToken-PermissionsNo tokens found
10Vulnerabilities0 existing vulnerabilities detected
Прямі залежності 4
РеєстрПакетОбмеження версіїМаніфест
Packagistcakephp/cakephp^5.1.1composer.json
Packagistdragonmantank/cron-expression^3.3composer.json
Packagistdereuromark/cakephp-tools^3.0.0composer.json
Packagistdereuromark/cakephp-queue^8.9.0composer.json
Усі залежності 10

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

РеєстрПакетВерсіяЗв'язок
Packagistcakephp/cakephpпряма
Packagistdereuromark/cakephp-queueпряма
Packagistdereuromark/cakephp-toolsпряма
Packagistdragonmantank/cron-expressionпряма
Packagistcakephp/migrationsнепряма
Packagistdereuromark/cakephp-templatingнепряма
Packagistfig-r/psr2r-snifferнепряма
Packagistpanlatent/cron-expression-descriptorнепряма
Packagistphpнепряма
Packagistphpunit/phpunitнепряма
Сповіщення про залежності не оцінено

Звірка сповіщень не відбулася для цього звіту: No resolved dependencies carried a version and a supported ecosystem

Звіт у форматі JSON машиночитний
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 401,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "PHP": 314350
      },
      "pushed_at": "2026-06-28T09:42:00Z",
      "created_at": "2023-10-18T00:48:03Z",
      "owner_type": "User",
      "updated_at": "2026-06-28T09:42:04Z",
      "description": "CakePHP Addon for Queue plugin to schedule commands and queue tasks as crontab like DB solution",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "master",
      "license_spdx_raw": "MIT",
      "primary_language": "PHP",
      "significant_languages": [
        "PHP"
      ]
    },
    "owner": {
      "blog": "https://www.dereuromark.de/",
      "name": "Mark Scherer",
      "type": "User",
      "login": "dereuromark",
      "company": "Available as (Cake)PHP expert",
      "location": "Berlin",
      "followers": 750,
      "avatar_url": "https://avatars.githubusercontent.com/u/39854?v=4",
      "created_at": "2008-12-11T16:33:44Z",
      "is_verified": null,
      "public_repos": 123,
      "account_age_days": 6437
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "0.3.6",
          "kind": "patch",
          "published_at": "2026-05-28T16:22:31Z"
        },
        {
          "tag": "0.3.5",
          "kind": "patch",
          "published_at": "2026-05-11T23:18:54Z"
        },
        {
          "tag": "0.3.4",
          "kind": "patch",
          "published_at": "2026-05-08T16:51:54Z"
        },
        {
          "tag": "0.3.3",
          "kind": "patch",
          "published_at": "2026-05-04T11:33:03Z"
        },
        {
          "tag": "0.3.2",
          "kind": "patch",
          "published_at": "2026-05-04T00:31:38Z"
        },
        {
          "tag": "0.3.1",
          "kind": "patch",
          "published_at": "2026-05-01T23:13:02Z"
        },
        {
          "tag": "0.3.0",
          "kind": "minor",
          "published_at": "2026-04-30T22:07:26Z"
        },
        {
          "tag": "0.2.15",
          "kind": "patch",
          "published_at": "2026-04-02T14:58:34Z"
        },
        {
          "tag": "0.2.14",
          "kind": "patch",
          "published_at": "2026-01-30T09:19:30Z"
        },
        {
          "tag": "0.2.13",
          "kind": "patch",
          "published_at": "2026-01-25T05:36:04Z"
        },
        {
          "tag": "0.2.12",
          "kind": "patch",
          "published_at": "2026-01-04T04:44:08Z"
        },
        {
          "tag": "0.2.11",
          "kind": "patch",
          "published_at": "2025-11-09T08:56:01Z"
        },
        {
          "tag": "0.2.10",
          "kind": "patch",
          "published_at": "2025-09-16T12:45:13Z"
        },
        {
          "tag": "0.2.9",
          "kind": "patch",
          "published_at": "2025-04-30T00:46:28Z"
        },
        {
          "tag": "0.2.8",
          "kind": "patch",
          "published_at": "2025-03-10T01:28:11Z"
        },
        {
          "tag": "0.2.7",
          "kind": "patch",
          "published_at": "2024-11-18T14:22:29Z"
        },
        {
          "tag": "0.2.6",
          "kind": "patch",
          "published_at": "2024-10-26T12:11:12Z"
        },
        {
          "tag": "0.2.5",
          "kind": "patch",
          "published_at": "2024-07-18T13:24:24Z"
        },
        {
          "tag": "0.2.4",
          "kind": "patch",
          "published_at": "2024-03-29T23:38:52Z"
        },
        {
          "tag": "0.2.3",
          "kind": "patch",
          "published_at": "2024-03-12T16:38:56Z"
        },
        {
          "tag": "0.2.2",
          "kind": "patch",
          "published_at": "2024-03-06T23:37:42Z"
        },
        {
          "tag": "0.2.1",
          "kind": "patch",
          "published_at": "2023-12-11T22:24:41Z"
        },
        {
          "tag": "0.1.2",
          "kind": "patch",
          "published_at": "2023-12-11T22:24:22Z"
        },
        {
          "tag": "0.2.0",
          "kind": "minor",
          "published_at": "2023-11-16T00:58:19Z"
        },
        {
          "tag": "0.1.1",
          "kind": "patch",
          "published_at": "2023-11-16T00:54:40Z"
        },
        {
          "tag": "0.1.0",
          "kind": "minor",
          "published_at": "2023-10-26T12:14:05Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "6caadcf36793f03190eefc112c9391f9cb4e463d",
          "body": "actions/cache@v1-v4 declare Node 20, which GitHub now deprecates and\nforce-runs on Node 24. v5 is Node 24 native and removes the warning.",
          "is_bot": false,
          "headline": "CI: bump actions/cache to v5 (Node 24)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-06-28T09:41:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "77922d55a81afa7b29a3fec0d397b72842dd8721",
          "body": "Newer phpstan (2.2.x, as installed by CI) flagged two provably-constant\ncomparisons in SchedulerRow:\n- isWithinWindow(): `$endMinutes !== null` was always true at that point\n  (both-null returns early, start-only handled above), so drop it.\n- windowIntervalsByDay(): the seconds null-guard was unreac\n[…]\nplace the exact `assertSame(300, ageSeconds)` in the stale-heartbeat\ntest with a range assertion; a second can elapse between writing\n`time() - 300` and the controller reading it, which flaked to 301.",
          "is_bot": false,
          "headline": "Fix CI: phpstan dead comparisons and flaky heartbeat age assertion",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-06-28T09:25:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "41794e01691427b89758f88a00394ac6779adbe5",
          "body": "… (#48)\n\n* Rerun terminally-failed scheduled jobs in place, with failure backoff\n\nA non-concurrent row gates its next dispatch on QueuedJobsTable::isQueued().\nOnce cakephp-queue records terminal \"aborted\" state, a dead job stops\ncounting as queued, so the schedule resumes — but it would then queue a\n[…]\nthe transaction commits, so a listener never runs mid-transaction.\n- Tidy a detached test docblock left over from the earlier insertion.\n\n* Reference cakephp-queue#505 in the reset-status shim comment",
          "is_bot": false,
          "headline": "Rerun terminally-failed scheduled jobs in place, with failure backoff…",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-28T16:13:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b79cfe41cfbf79b2c16b56b5763e316cc74acfcf",
          "body": "* AP-0000 Add QueueScheduler import/export workflow\n\n* Fix scheduler window day form submission\n\n* Fix scheduler admin template structure",
          "is_bot": false,
          "headline": "Add QueueScheduler import/export workflow (#46)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-26T21:13:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d87281c110ec6e542a4c159444fc6e845ed50215",
          "body": null,
          "is_bot": false,
          "headline": "Add sort direction indicators to admin tables",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-26T20:54:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "24b7f8196a8b2c461523aa801fe916bf321ea158",
          "body": "* Apply conservative Rector cleanup\n\n* Run PHPCS cleanup\n\n* Restore compact() for matching view vars\n\n* Simplify null guard for scheduler helper\n\n* Restore compact() for matching view vars\n\n* Restore explicit null check for cron detection",
          "is_bot": false,
          "headline": "Apply conservative Rector cleanup (#45)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-25T12:19:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "79f233f575150771a2c74042658930868c07ff3d",
          "body": "Point readers to https://toolbox.dereuromark.de/dbml so they can convert this\nDBML snapshot into the migration or raw SQL they need for their own app.",
          "is_bot": false,
          "headline": "Link the DBML converter in the schema snapshot",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-23T15:54:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7dcfd971784a43c54de68e4948f46935b2fff6a1",
          "body": "Hand-maintained DBML snapshot of the plugin's migration schema under\nresources/schema/schema.dbml — paste into dbdiagram.io to view/diagram.\nMirrors the snapshot already shipped by cakephp-workflow.",
          "is_bot": false,
          "headline": "Add DBML database schema snapshot",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-23T12:54:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "394b10bc622d0dcc9aae47a0c4e264b4dc9597b4",
          "body": null,
          "is_bot": false,
          "headline": "Add .github/CONTRIBUTING.md",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-22T18:51:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f06395f731ab8bb74df3217f3dc5577f00098e70",
          "body": "Several tests temporarily froze DateTime::setTestNow() to a past date and\n\"reset\" it afterwards with setTestNow(new DateTime()). While an override is\nactive, new DateTime() resolves to the frozen value, so the reset re-froze\nthe same past date and leaked it into later tests.\n\nRowTest::testCalculateN\n[…]\n clears the override before re-freezing at the\nreal wall clock. This avoids leaking a stale value while keeping test-now\nnon-null for tests that read getTestNow() (SchedulerRowsTableTest::testInsert).",
          "is_bot": false,
          "headline": "Fix test-now leak that made RowTest fail in CI (#44)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-21T13:52:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e94278e4418855a9d24f0e5bb3c4f082ec924f97",
          "body": null,
          "is_bot": false,
          "headline": "Document missing configuration keys in config/app.example.php",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-21T13:11:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "98a5d3341eee5f12e21a07d5cd33ac6626e60b7b",
          "body": null,
          "is_bot": false,
          "headline": "Add homepage to composer.json",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-21T12:06:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a4da3126d675b52bbb8c1a1484d6a6b9c47b9d0a",
          "body": "The page-header pattern (title + action buttons in\n`d-flex justify-content-between align-items-center`) pushed buttons\noff-viewport on phones because no wrap was allowed. Wrap on viewports\n< sm so buttons fall to a new row instead of being clipped.",
          "is_bot": false,
          "headline": "Make page-header row wrap on phones so action buttons stay on-screen",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-11T23:37:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b0f036d02abe94b897dfc63adab1eacee81d873e",
          "body": "The mobile offcanvas nav was missing the Reference -> Commands & Tasks\nlink that the desktop sidebar exposes. Mobile users had no way to reach\nthe available-commands listing without typing the URL manually.",
          "is_bot": false,
          "headline": "Sync mobile_nav with sidebar: add missing Commands & Tasks link",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-11T23:35:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a20a4e61eb65ba049d58404f1345d1ea5c774326",
          "body": "CronExpression::getNextRunDate() with the default arg resolves \"now\" via\nDateTimeImmutable('now'), which ignores Cake's Chronos::setTestNow. The\nprefer-lowest CI matrix happened to run during a real-time minute that\nsat inside the test's 23:00-23:30 window, so both the pre-patch cron\nresult and the \n[…]\ndary.\n\nUpdate testCalculateNextRunForMinutelyShortcut to compare against the\ntest-now clock rather than time(). Its previous reliance on real time()\nwas a workaround for the very bug being fixed here.",
          "is_bot": false,
          "headline": "Fix master: make calculateNextRun honor DateTime::setTestNow (#42)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-11T23:18:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1bc35f3b50693b8f60615192bb48d4ce90c5e50d",
          "body": "* Complete scheduler time-window UX and localization\n\n* Fix CI for time-window follow-up",
          "is_bot": false,
          "headline": "Complete time-window scheduler UX and localization (#41)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-11T22:58:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0994f9704057b17c24661676065465475dc58228",
          "body": "* Add time-window restrictions to SchedulerRow dispatch gating\n\nSecond of three queue-scheduler strategic items from the audit. Cron\nexpressions handle \"every Monday at 9\" but cannot express \"every 5 min,\nbut only between 09:00-18:00 on weekdays\" — those need compound\nrestrictions ANDed against the \n[…]\ny Options covering the three new columns (window_start_time,\nwindow_end_time, window_days_of_week), the overnight-wrap semantics,\nand three worked examples (business hours / overnight / weekend-only).",
          "is_bot": false,
          "headline": "Add time-window restrictions to SchedulerRow dispatch gating (#39)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-11T22:00:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7634e95f0773ee280091ffac9e8b5b92e87d2081",
          "body": "* Add ad-hoc trigger-now with per-call param and job_config overrides\n\nAdds a second \"Run Now\" path for Queue task rows in the admin UI that\nlets operators dispatch a single override job without touching the\nrow's scheduled cadence. Use case: incident-response re-runs (rerun\nyesterday's batch with a\n[…]\n enough to look like real field values, which is misleading in the\noverride JSON textareas (and elsewhere in the admin UI). Override to the\ngray-500 token so empty fields read clearly as placeholders.",
          "is_bot": false,
          "headline": "Ad-hoc trigger-now with per-call param/job_config overrides (#40)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-11T22:00:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2ae29cc9a0adc06f8e97a9cc3f23f3cc8d3ebe11",
          "body": "* Fix isDue stale-next_run loop and racy run() compare-and-swap\n\nTwo correctness bugs from the source-grounded review:\n\n1. SchedulerRow::isDue() short-circuited on next_run and ignored last_run.\n   If a dispatcher crashed between createJob() and the next_run-advancing\n   save, the row stayed in an \"\n[…]\nced the plugin registry, leaving subsequent CommandFinderTest::testAll\nunable to find Tools.Inflect. Reload all three so the registry matches what\nApplication::bootstrap() establishes in the test app.",
          "is_bot": false,
          "headline": "Fix isDue stale-next_run loop and racy run() compare-and-swap (#37)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-11T14:26:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "33574240fbb77290992f1fec15ea11311d046cf2",
          "body": null,
          "is_bot": false,
          "headline": "Fix CS.",
          "author_name": "Mark",
          "author_login": "dereuromark",
          "committed_at": "2026-05-09T18:47:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ecb435bc8467496ab4a28c859bc134b8fcf80651",
          "body": "Two ergonomics fixes for the Param field on Queue Task and Cake Command rows:\n\nAuto-normalize empty-collection literals. The validators reject `[]` and\n`{}` via `!empty($decoded)`, but the field already accepts an empty string\nto mean \"no payload / no args\". A user who explicitly types the empty\nlit\n[…]\narded straight to `Command::run($args, $io)`, so embedded\nshell-style quoting (`\"--some-option \\\"Some value\\\"\"`) does not behave as\nit would on a real shell — replaced with `--some-option=Some value`.",
          "is_bot": false,
          "headline": "Normalize empty-collection JSON params to blank; polish param docs (#36)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-08T16:26:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a0574f5fcb66936168cf3b967aed82c1f6c78441",
          "body": "… (#35)\n\n* Tokenize shell-command rows into executable and arguments on dispatch\n\nPreviously the entire scheduler `content` field was assigned to\n`Queue.Execute`'s `command` verbatim. The queue plugin matches `command`\nagainst `Queue.executeAllowedCommands` literally and `escapeshellarg`'s\neach `par\n[…]\nlready\nrejects empty content at save time, but a row inserted via raw SQL or a\nmarshalling path that bypasses validation can no longer produce a params\nlist that includes a literal empty-string entry.",
          "is_bot": false,
          "headline": "Tokenize shell-command rows into executable and arguments on dispatch…",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-08T16:13:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6b05cca12e6c414ea46464a3a6d432f9c945a1e5",
          "body": "Reads QueueScheduler.adminBackUrl + optional QueueScheduler.adminBackLabel\n(defaults to \"Back to App\"). Mirrors the same pattern in the other\ndereuromark plugins so apps can wire all of them with one consistent\nconfig shape.",
          "is_bot": false,
          "headline": "Add configurable Back-to-App link to admin header",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-04T12:30:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "26568bc33e97957749b5ec38045333307773149d",
          "body": "SchedulerRowsTable::initialize() called setColumnType('job_config', 'json')\nunconditionally, which throws DatabaseException if the column doesn't exist\nyet. On an upgrade from 0.2.x where the table is loaded via TableRegistry\nbefore migrations migrate has run, this leaves the deploy unrecoverable.\n\nGuard the cast on hasColumn() so booting against a not-yet-migrated schema\nno longer crashes; the cast attaches once the column lands.",
          "is_bot": false,
          "headline": "Guard job_config column-type cast against pre-migration schema (#34)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-04T11:32:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "909f78d62e4e46e5b6266e3185cf07754c70bea7",
          "body": "Convert __() / __n() calls in src/ and templates/ to __d('queue_scheduler', ...) /\n__dn('queue_scheduler', ...) so user-facing strings live in their own translation\ndomain instead of leaking into the host app's default domain.\n\nAdd resources/locales/queue_scheduler.pot generated via cake i18n extract so\ntranslators have a stable POT to base language files on.",
          "is_bot": false,
          "headline": "Use plugin-specific i18n domain for translations (#32)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-04T00:30:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "14a40565d641fb2a4a7466375b4f9ec8f0ef03de",
          "body": "Switched the Paginator nav titles from escapeTitle => false to\nescape => false. PaginatorHelper only honors the escape option —\nescapeTitle is silently ignored — so the FontAwesome <i> tags fell back\nto the default escaped path and rendered as literal HTML text.\n\nVerified in cakephp/cakephp PaginatorHelper: prev/next/first/last/sort\nall use only the escape option, with no narrower title-only equivalent.",
          "is_bot": false,
          "headline": "Fix pagination icons rendering as raw text (#31)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-03T15:59:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3032342b8744f4ed9d728939f19307fc1cab9b83",
          "body": "Tightens row-save validation along three axes that were previously single-\ngated or implicitly trusted:\n\n- `validateShellCommand` now requires `QueueScheduler.allowRaw=true` (or\n  `debug=true`) at row-authoring time, mirroring the dispatch-side gate in\n  `findActive()`. Rows of `TYPE_SHELL_COMMAND` \n[…]\nnow dispatches with empty params instead of crashing.\n\nAlso widens `validateContent` to `string|bool` so the new `validateShell-\nCommand` can return a translated error message instead of just `false`.",
          "is_bot": false,
          "headline": "Gate shell authoring on allowRaw and validate class types (#30)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-02T14:32:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d35a4618ea85c5b27507ffcab2eee8ce4012eee0",
          "body": "When next_run sits more than 5x the schedule interval in the past (e.g.\nan every-minute job with next_run 9 hours ago because cron was down or\nthe worker was stuck), the relative time was technically correct but\nuninformative — \"(9 hours, 35 minutes ago)\" tells the user nothing they\ncan act on. The \n[…]\nals on the next successful tick: calculateNextRun re-derives\nnext_run from CronExpression::getNextRunDate() (or last_run + interval),\nboth of which produce a future timestamp once last_run is updated.",
          "is_bot": false,
          "headline": "Show \"overdue\" instead of long ago time when next run is grossly overdue",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-01T23:01:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f801c708578b5baf277153f73c1a37170490ebf1",
          "body": "Adds a \"Run New\" button to /admin/queue-scheduler that queues all enabled\nschedules with last_run IS NULL. The button only renders when at least 2\nsuch rows exist; for a single new row, the per-row Run action is enough.\n\nUseful after bulk-adding long-interval schedules (weekly/monthly) where\nwaiting for the first cron tick is impractical.",
          "is_bot": false,
          "headline": "Add Run New action to scheduler dashboard",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-01T13:55:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "edd6a0f04295c0a01443cc12f9ca57063d71d3c3",
          "body": "Same shape of improvements that landed on the index, plus a small DRY\nrefactor: the duration formatting, ratio-based color class, and\nlast-run pass/fail icon now live as methods on SchedulerHelper so both\ntemplates render them the same way without duplicating logic inline.\n\nSchedulerHelper additions\n[…]\n threshold also go through the helper.\n\nSchedulerRowsController::view() now contains LastQueuedJob (id,\nfetched, completed, failure_message) so the new view-page bits resolve\nwithout a per-row lookup.",
          "is_bot": false,
          "headline": "Bring scheduler view page in line with the index polish",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-01T03:43:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e1f91a1c7fef7b6fa0407d55fe80bfe6d3916c81",
          "body": "- Rename the \"Log\" column header to \"Status\".\n- Surface success / failure on the last run with a check / x icon next\n  to the timestamp, driven by the linked QueuedJob's failure_message.\n- Render an explicit empty-state row when there are no schedules.\n- Lift colored spans (warning / danger duration\n[…]\ntton form submission,\nshows confirm, posts via fetch with the spinner shown in-place, and\nreloads the page once the queue layer reports success. Non-JS clients\nkeep the original flash + redirect flow.",
          "is_bot": false,
          "headline": "Polish scheduler index UI",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-01T03:22:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a6dee013c56498e9223afb567dddf8a1c282ec9b",
          "body": "Last Run row now appends the actual execution duration of the latest\nqueued job (e.g. \"(2.3s)\", \"(1m 30s)\"), pulled in via a new LastQueuedJob\nbelongsTo association on SchedulerRows. The duration is color-coded\nrelative to the schedule interval: text-warning at >= 80% of the\ninterval, text-danger at\n[…]\nw::calculateIntervalSeconds() which returns the typical\ngap between firings for both interval-style (\"+5 minutes\", \"PT5M\") and\ncron-expression frequencies, used as the yardstick for the warning bands.",
          "is_bot": false,
          "headline": "Show run duration and time-to-next-run on the scheduler index",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-05-01T03:07:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a9d7e610ed66cd60f3c24af7e5912ef11afb4993",
          "body": "Make it explicit that exactly one scheduler runner should fire against\na given database. The FileLock only guards same-host overlap, so\nmulti-host fleets either pin cron to one host (common case) or swap\nin a cross-host lock (advisory lock / Redis).\n\nReplaces the buried multi-host caveat in the sub-minute section with\na back-reference, so the rule is stated once and prominently.",
          "is_bot": false,
          "headline": "Document single-runner recommendation for scheduler",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T23:49:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d99e8c6d56e3cddc328f05fc8a031e449c9877fa",
          "body": "* Surface scheduler heartbeat on admin index\n\nRunCommand writes a unix timestamp to the cache key QueueScheduler.lastTick\nat the end of every successful (non-dry-run) pass. The admin index page\nreads it and shows a small status pill: healthy, stale, or never run.\n\nCache config defaults to 'default' \n[…]\nlthy and stale.\n\n* Untrack accidentally-committed .claude/ scratch file\n\nRemoves .claude/scheduled_tasks.lock that slipped into the previous\ncommit and adds /.claude/ to .gitignore so it cannot recur.",
          "is_bot": false,
          "headline": "Surface scheduler heartbeat on admin index (#29)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T23:11:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2c9b15ad79860ee5aa00a7bd95437a1a31f145b8",
          "body": "Using 'escape' => false also disables HTML escaping of attributes (URL, classes, title), not just the title text. The narrower 'escapeTitle' => false keeps attribute escaping on while still allowing the icon HTML in the title.",
          "is_bot": false,
          "headline": "Use escapeTitle instead of escape in pagination element (#28)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T23:09:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3cc02b8af7b093a09bfd3ff60a5762ac02e2440b",
          "body": "Cleaner than the inline FQCN now that the file already imports other\nCake classes.",
          "is_bot": false,
          "headline": "Use ServerRequest import in app.example.php",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T15:44:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f2f8e925f90dc5946d9365015a9a20a401381c49",
          "body": "These are working documents only (specs, plans, brainstorm output) and\nmust not be in the repo. The 2026-04-30-command-output-capture.md spec\nslipped in as a side-effect of an unrelated commit; untrack it and add\ndocs/superpowers/ to .gitignore so it cannot recur.\n\nThe file stays on the local working tree (just untracked), so anyone\nalready iterating on it keeps their copy.",
          "is_bot": false,
          "headline": "Stop tracking docs/superpowers/ working files",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T15:43:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "195bb487c3f354fa08fd975978e8281a222a599b",
          "body": null,
          "is_bot": false,
          "headline": "Document QueueScheduler.adminAccess in app.example.php",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T14:43:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d1acfcfd98b5f1954f4dac7c8eeff9c05b9a350",
          "body": "* Set command name in CommandExecuteTask before running\n\nMost app commands override `protected string $name` to a single bare\ntoken (e.g. `'clear_sessions'`), expecting `Cake\\Console\\CommandRunner`\nto rewrite it to `\"cake clear_sessions\"` via `setName()` before running.\n\nCommandExecuteTask invokes t\n[…]\ndy contain a space must not be rewritten by CommandExecuteTask —\nbut the example now mirrors a real-world pattern. Test method renamed\nto testRunDoesNotRewriteMultiWordCommandName for the same reason.",
          "is_bot": false,
          "headline": "Set command name in CommandExecuteTask before running (#27)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T12:52:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "27368e89a05626d72f0e83744a08250a43894dc4",
          "body": "Cover isDue(), calculateNextInterval(), and calculateNextRun() directly on\nthe entity so regressions in the core scheduling logic surface here rather\nthan only via the integration tests in SchedulerTest / RunCommandTest.\n\n26 cases across the three methods:\n\n- isDue(): next_run past/future/equal-now \n[…]\nCake's setTestNow.\ntearDown restores a fresh test-now (instead of clearing to null) so the\nexisting SchedulerRowsTableTest::testInsert keeps finding a non-null\nChronos::getTestNow() across test files.",
          "is_bot": false,
          "headline": "Add direct unit tests for SchedulerRow scheduling math",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T11:57:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c1ea4bbadadce57732cde43cfcb2be4934701bdf",
          "body": "…rontabMinimum (#26)\n\n- Bump composer.json branch-alias from 0.2.x-dev to 0.3.x-dev so Packagist\n  picks up dev-master under the right next-release banner.\n- Document QueueScheduler.adminLayout (null / false / string layout name)\n  in docs/README.md as its own Configuration subsection — previously o\n[…]\nly on but is not read\n  anywhere in src/ or templates/. Documenting a no-op key would mislead\n  users; quietly dropping it is the cleaner path. Restore via PR if it\n  is reserved for a future feature.",
          "is_bot": false,
          "headline": "Bump branch-alias to 0.3.x-dev; document admin UI config; drop dead c…",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T11:29:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c658fd5137d874e7e7d044670a634623bc9a6ff1",
          "body": null,
          "is_bot": false,
          "headline": "Update branch alias for dev-master to 0.3.x-dev",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T11:26:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "28063416e422ef21632b56c990dc4129aa8cd789",
          "body": "… (#25)\n\n* Add --duration and --interval flags for sub-minute scheduling\n\nCron's minimum granularity is one minute, but rows can already declare\nsub-minute frequencies (e.g. `+10 seconds`, `PT5S`). The previous\nRunCommand only fired once per cron tick, so those rows could never run\nat their configur\n[…]\ngumentException when the @-suppressed call\nreturns a non-DateInterval value. Now both versions reach the catch\nthrough the same path, and phpstan on 8.2 stubs sees the throw and\nkeeps the catch alive.",
          "is_bot": false,
          "headline": "Add --duration/--interval flags for sub-minute scheduling (closes #2)…",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T11:10:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f9afa4fc6b708e7b5fed52c6dc8297ff9c9fe338",
          "body": "The migration and fixture stored a comment listing keys (queue, notBefore)\nthat the validator now rejects. Reflect the real allow-list — priority\nand group only — so anyone reading the schema sees the same contract the\nvalidator enforces.\n\nCosmetic-only: no functional schema change beyond the COMMENT text.",
          "is_bot": false,
          "headline": "Tighten job_config column comment to actual allow-list",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T02:08:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a22bb02348bc5b30abe056985b927b8c2407607a",
          "body": "The scheduler admin backend can configure arbitrary scheduled command\nexecution (Cake commands, Queue tasks, and — when allowRaw is on — shell\ncommands), so accidental exposure has real blast radius. Mirror the\ncaptcha plugin's \"fail closed\" pattern: the host app MUST configure\nQueueScheduler.adminA\n[…]\nange: existing 0.2.x installs\nthat just relied on host AppController gating will 403 until they\nadd a Closure. Right tradeoff for a pre-1.0 plugin where the\nexposure cost outweighs the migration cost.",
          "is_bot": false,
          "headline": "Default-deny admin access via QueueScheduler.adminAccess Closure",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T02:07:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "96bda28103e8a20bf3b89ae6efcf6c5631a40685",
          "body": "Form display:\n* Configure FormHelper to emit Bootstrap 5 error markup\n  (errorClass=is-invalid, error template with invalid-feedback) so\n  field-level errors actually render with the red border/text instead\n  of plain unstyled \"form-error\" output.\n* Replace the misleading \"queue\" placeholder/help in\n[…]\nise\n  silently cast to 0 — accidentally the highest priority.\n\nDocs:\n* docs/README.md gains a \"Job Config\" section documenting the allow-list\n  and a \"Command flags\" section for --dry-run and --limit.",
          "is_bot": false,
          "headline": "Improve form error UX and tighten job_config validation",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T01:48:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2dab38167e1417847e2953de51499bbc9e507910",
          "body": "--dry-run lists the events that would be dispatched and exits without\nenqueueing or touching last_run/next_run. Useful for diagnosing \"why is\nthis not firing yet\" or smoke-testing a freshly added row.\n\n--limit=N caps the number of events dispatched per tick; the remainder\nstays due for the next run. Helps drain a backlog gracefully after\ndowntime instead of flooding the queue all at once.",
          "is_bot": false,
          "headline": "Add --dry-run and --limit flags to scheduler run",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T01:35:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8c8bd15e509b465d10ff246ab06a2b09110c1c5b",
          "body": "* Remove dead `=== false` / `!== false` guards on\n  DateInterval::createFromDateString — the function cannot return false on\n  PHP 8.2+, and phpstan was correctly flagging both as always-false /\n  always-true. Drops an unreachable RuntimeException and clears the last\n  two phpstan errors so the suit\n[…]\n\n  comments.\n* Drop a misused JSON_PRETTY_PRINT flag from json_decode in two\n  param-shape validators (it's an encode-only flag; integer was just\n  being ignored).\n* Add a branch-alias for dev-master.",
          "is_bot": false,
          "headline": "Clean up small code-quality issues",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T01:33:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c3597ebfccfa01e14b9c06c883c559522633f465",
          "body": null,
          "is_bot": false,
          "headline": "Queue config.",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T01:26:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9508a469670d5c633e3c4c7f6097f37203a8073a",
          "body": "The custom @minutely shortcut was being expanded to \"* * * * *\" in five\nplaces (entity, table validator, controller intervals action, view.php\ntwice, intervals.php). Promote SchedulerRow::normalizeCronExpression() to\npublic static and route every caller through it; renaming or extending\nthe shortcut list now happens in one spot.",
          "is_bot": false,
          "headline": "Centralize @minutely cron-shortcut normalization",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T01:08:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d27b94ef1c7f26cfcc5e5813e27993a13338f019",
          "body": "The admin add/edit screens call all() to populate the command picker; each\ncall walked App::classPath() and DirectoryIterator over the app and every\nloaded plugin. A static per-plugin-set cache keeps the disk walk to once\nper request lifecycle.",
          "is_bot": false,
          "headline": "Cache CommandFinder::all() per loaded plugin set",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T01:08:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "78f5e6e9a5c531d60a3254c3398dbff9e4a7a4cd",
          "body": "isDue() used strict less-than against next_run while findScheduled()\nfilters with `<=`, so a row whose next_run was exactly \"now\" was selected\nby the SQL query but rejected by the entity check, falling through into\nredundant cron/interval re-evaluation. Use `<=` in both branches so they\nagree.\n\ncalc\n[…]\nly on the next scheduler tick\nrather than at the next 11:00 occurrence. Cron rows now compute their\ntrue next occurrence even on first run; interval rows keep their existing\nfire-immediately behavior.",
          "is_bot": false,
          "headline": "Fix isDue boundary and cron first-run calculation",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T01:04:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4ed5994f52a9b78e39d77020c91210fd881a728c",
          "body": "Previously a thrown exception inside Scheduler::schedule() would bubble\nout of Collection::each and abort the rest of the batch, while RunCommand\nalways returned exit code 0 — partial failures were invisible to cron\nmonitoring.\n\nNow schedule() catches per-row throwables, logs them, counts them, and\n\n[…]\nfrom real failures.\n\ntests/bootstrap.php gains a FileLog config so the new error-path test\ndoes not blow up writing to a closed console stream after\nConsoleIntegrationTestTrait runs in the same suite.",
          "is_bot": false,
          "headline": "Make scheduler resilient to single-row failures and surface them",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T01:04:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e0ddff1d886aaf1cb675b0cc8dc951d9372f1cd7",
          "body": "The Config row used \\$row->config (which does not exist on the entity), so\nthe block never rendered. Switching to \\$row->param actually shows it. Also\nwrap the JSON output in h() — values inside <pre> still need escaping to\nprevent breakout via tags like </pre><script>.\n\nSync SchedulerRowsFixture with the schema (param, last_queued_job_id) so\ntests that exercise these columns can persist them; tests/schema.php\nderives the test DB schema from the fixture's \\$fields.",
          "is_bot": false,
          "headline": "Fix Config block on view page and escape param output",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T00:57:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ea7f63e07020cd683de663e5175a428c9087bf18",
          "body": "Cake's Validator::add() defaults the 'rule' key to the rule's name when\nabsent, so the 'role' => 'X' entries were being silently ignored — a typo\nthat did not actually break validation but kept misleading readers.",
          "is_bot": false,
          "headline": "Drop dead 'role' keys from validator rule arrays",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T00:57:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b5f09472f6d6e8ca2a08e4bcd7f7e8603d971cff",
          "body": "Reject anything that isn't a CommandInterface subclass before instantiating\nit. Previously the task did `new $class()` on whatever string the queue\npayload contained, with only a phpdoc claim that the class implemented\nCommandInterface.",
          "is_bot": false,
          "headline": "Validate command class in CommandExecuteTask",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-30T00:57:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0b2345f451bf990a54a5d9326639e56ccecca068",
          "body": null,
          "is_bot": false,
          "headline": "Adjust CS badge",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-28T16:58:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0b0c94df5661e5b8bb4278c0cd4d503c976d4e96",
          "body": "…titles (#24)\n\n10 admin template links rendering icon HTML in the title were using\n'escape' => false, which also disables escaping of url attributes (href,\nclass, title). Switching to 'escapeTitle' => false scopes the opt-out\nto the title only.\n\nThe 4 'escape' => false entries on Paginator first/prev/next/last are\nleft as-is since PaginatorHelper does not support 'escapeTitle'.",
          "is_bot": false,
          "headline": "Use 'escapeTitle' instead of 'escape' for icon-prefixed Html->link() …",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-27T10:11:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f0d85facee6b3608c853e4878a697fefd4deb352",
          "body": "The button widget honors escapeTitle (not escape) for the title text.\nPassing escape => false on these calls left the icon markup escaped, so\nbuttons rendered with literal &lt;i class=...&gt;...&lt;/i&gt; instead\nof an icon.",
          "is_bot": false,
          "headline": "Use escapeTitle => false for icon HTML in Form->postButton/button",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-27T09:43:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f15c5530299754d2242ffd400e539a32315f4114",
          "body": "* Move mobile-nav background to CSS class (strict-CSP)\n\nDrops the inline `style=\"background: linear-gradient(...)\"` attribute on the\nmobile offcanvas in favour of a `.scheduler-mobile-nav-bg` class that reuses\nthe existing `--scheduler-sidebar-bg` custom property. Removes the\n`style-src 'unsafe-inli\n[…]\nin\n`Admin/SchedulerRows/view.php` with a `.scheduler-col-w-40` class\ndefined in the layout's existing nonced `<style>` block. After this\nthe plugin's templates contain zero inline `style=` attributes.",
          "is_bot": false,
          "headline": "Move mobile-nav background to CSS class (strict-CSP) (#23)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-26T22:30:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b50eb68d0f1e98275e2f235d85b083a172935538",
          "body": "- Add nonce attribute to the three inline <script> blocks (layout\n  DOMContentLoaded / tooltip init / auto-refresh, quick-add element,\n  content-autocomplete element) so apps with a strict script-src\n  'self' 'nonce-...' CSP can run them.\n- Replace every Form->postLink with Form->postButton across t\n[…]\nnfirm messages move to a data attribute and use a\ndelegated submit handler instead.\n\nGraceful fallback: when no cspNonce request attribute is set, the\n<script> tags render without the nonce attribute.",
          "is_bot": false,
          "headline": "Make admin UI CSP-compatible (#22)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-22T23:27:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f961e2f3cc197a5734a8042004259f15f46e125b",
          "body": null,
          "is_bot": false,
          "headline": "Fix CS.",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-17T17:30:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "325a52336baf2a43b64eb5f10b6f8113bad86a3f",
          "body": null,
          "is_bot": false,
          "headline": "Fix pre element overflow in standalone layout",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-04-02T14:57:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e151be5d01de38e0286ec38ff63b05121e95998c",
          "body": "Sets explicit Bootstrap 5 templates to avoid app templates affecting\nthe standalone admin layout.",
          "is_bot": false,
          "headline": "Add standalone pagination element to prevent style leakage.",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-28T14:11:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "885bfbc265ccbdb5e9710d59285cd9bf137d93aa",
          "body": "Extract flash rendering logic into flash/flash.php element for cleaner\nlayout code and easier maintenance.",
          "is_bot": false,
          "headline": "Refactor flash rendering to use dedicated element.",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-28T13:45:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a133ce3f63a13dbd1d8d8ff00f9f207a4b29c77",
          "body": "Use inline flash rendering with consume() to avoid style leakage from\napp layouts and ensure messages are properly consumed from session.",
          "is_bot": false,
          "headline": "Fix flash message rendering in standalone layout.",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-28T13:39:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d827d343705eae34f975acc405382371548a267b",
          "body": null,
          "is_bot": false,
          "headline": "Add 'standalone-ui' to composer.json keywords",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-18T23:06:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a0b08c7fabab5dafd1e680f113ca1033bbe58951",
          "body": null,
          "is_bot": false,
          "headline": "Move Available Commands & Tasks to dedicated page in sidebar",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-18T22:52:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "70bedcc52ec3cd3c17e7098869520d383cd14cf3",
          "body": "* Add standalone admin layout with Bootstrap 5\n\nIntroduces a modern, self-contained admin dashboard similar to the\nQueue plugin. Features include:\n\n- QueueSchedulerAppController base controller with standalone mode\n- Self-contained Bootstrap 5 + Font Awesome 6 layout via CDN\n- Sidebar and mobile nav\n[…]\no have Bootstrap/Font Awesome configured.\n\n* Fix duplicate commands/tasks listing on add page\n\n* Replace quick_add with compact autocomplete search\n\n* Add type suffix to quick_add autocomplete options",
          "is_bot": false,
          "headline": "Add standalone admin layout with Bootstrap 5 (#21)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-18T21:37:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "271a6d648e63d76e6f736bb939c560a18800078e",
          "body": null,
          "is_bot": false,
          "headline": "Enable phpcs cache for faster subsequent runs",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-15T15:35:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "451f032107bc213f4f0770847e3aaa7c7097848a",
          "body": null,
          "is_bot": false,
          "headline": "Improve composer.json metadata",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-13T14:51:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4915828e034f76c0b52719be04a6c53c0ef62307",
          "body": null,
          "is_bot": false,
          "headline": "Add admin-panel keyword",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-13T14:43:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c01b3822bfbfbd0e1b5a59e58b668ba4cf098fe9",
          "body": null,
          "is_bot": false,
          "headline": "Fix Bootstrap collapse toggle for BS4/BS5 compatibility",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-03-09T23:43:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a3a4f4758b2babcd5fe6a9a6173d3ba2cd522b23",
          "body": null,
          "is_bot": false,
          "headline": "Fix PHPStan type error with entity annotation",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-02-28T00:02:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "db34570e653420ca87bab61ea51ce89e28e51127",
          "body": null,
          "is_bot": false,
          "headline": "Fix phpunit",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-02-22T17:39:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "980f0c1ee6efede181c5097c897ba934cdecf57a",
          "body": null,
          "is_bot": false,
          "headline": "Allow PHPUnit 13",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-02-06T23:54:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2fc2741c944c51eeddd5b315cb231e796b291d2e",
          "body": null,
          "is_bot": false,
          "headline": "Upgrade migrations dev dep",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-31T04:15:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3304439c11f9a305ba74f410b2cb67c8c0fbd6a8",
          "body": "* Add content field autocomplete based on task type\n\nUses HTML5 datalist to suggest available Cake commands or Queue tasks\nin the content field on add/edit forms. The datalist switches\nautomatically based on the selected type dropdown.\n\nRefs #1\n\n* Improve autocomplete.\n\n* Improve autocomplete.",
          "is_bot": false,
          "headline": "Add content field autocomplete for available commands and tasks (#20)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-30T09:15:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8768ed06c688285ab996fb001c2797114dcf5e55",
          "body": "* Add scheduler logging and fix command output capture\n\nCommandExecuteTask now captures command stdout/stderr via temp file\nstreams and forwards the output through $this->io so the Processor's\noutput capture stores it in the queued_jobs output column. Previously\na fresh ConsoleIo was used, bypassing\n[…]\n.\n\n* Raise cakephp-queue minimum to ^8.9.0 for output capture support\n\nThe output capture feature (enableOutputCapture, getOutputAsText)\nwas added in 8.9.0 and is required for this PR's functionality.",
          "is_bot": false,
          "headline": "Add scheduler logging and fix command output capture (#19)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-30T03:33:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2bdb6b431e840454f4cff2dafa3d04b01aebfee3",
          "body": "Add direct job linking from scheduler to queue jobs",
          "is_bot": false,
          "headline": "Merge pull request #18 from dereuromark/feature/job-linking",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-29T10:37:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eb4bfed93ae9836e3fa48086ccfe5a856400d768",
          "body": null,
          "is_bot": false,
          "headline": "Update cakephp-queue version to ^8.1.0",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-28T05:13:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ca98fc421097ecb8ee869388d6fb8884ea036a6d",
          "body": null,
          "is_bot": false,
          "headline": "Raise PHP Min Version",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-28T05:02:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8638315e8c16f69e64962bfda30d7dae96354f33",
          "body": "Fix search filter parameter for Queue plugin",
          "is_bot": false,
          "headline": "Merge pull request #17 from dereuromark/feature/view-job-statistics",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-14T09:38:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d4ead1ce10a36e31d0103c0cc9916b500688b33a",
          "body": null,
          "is_bot": false,
          "headline": "Fix search filter parameter for Queue plugin",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-14T09:37:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "635ebd1c57b4bc71cb6db946d01ec18f1309e5e7",
          "body": "Add job statistics and queue link to scheduler row view",
          "is_bot": false,
          "headline": "Merge pull request #16 from dereuromark/feature/view-job-statistics",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-14T09:27:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d336103c784a63d9d62299aed4a6785789ad3dd0",
          "body": "- Display average, min, and max execution duration\n- Show total runs, completed, and failed counts\n- Add recent executions table with status and duration\n- Add quick link to view jobs in Queue backend\n- Use PHP-based duration calculation for database portability",
          "is_bot": false,
          "headline": "Add job statistics and recent executions to scheduler row view",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-14T09:20:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e1e14730e97b855cb6a29b1f65f9b050b9f18d6d",
          "body": "Improve code documentation",
          "is_bot": false,
          "headline": "Merge pull request #15 from dereuromark/improve-docs",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-04T04:50:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a93bdcd9b9dd481aa50bca1e53edbdc5226deafa",
          "body": null,
          "is_bot": false,
          "headline": "Add PHPDoc to Scheduler class and methods",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-04T04:48:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "15220b8c1468354b2689f0ddbaf8b85c654170a7",
          "body": "Fix PHP version badge in README",
          "is_bot": false,
          "headline": "Merge pull request #14 from dereuromark/fix-readme-badge",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-04T04:40:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9e30d7e942623412231d54269f86554d11c329b6",
          "body": null,
          "is_bot": false,
          "headline": "Fix PHP version badge in README",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-04T04:37:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "37ccfc60f4e21fd4a546b6866bf81c8ddfab70ee",
          "body": "Add missing command description for scheduler run",
          "is_bot": false,
          "headline": "Merge pull request #13 from dereuromark/add-command-descriptions",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-04T01:38:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e561789d0e743206538265368912c87598dd4764",
          "body": null,
          "is_bot": false,
          "headline": "Add missing command description for scheduler run",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-04T01:33:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c417a2a016887786c48dd7d2ac34250f16fb5c1e",
          "body": "Make Icon configuration optional with text fallback",
          "is_bot": false,
          "headline": "Merge pull request #12 from dereuromark/feature/optional-icon-config",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-01T18:21:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8b48627c268356751233e505507ce822d743a4a6",
          "body": "- Add Icon config to app.example.php\n- Document icon configuration in docs/README.md\n- Conditionally load Icon helper only when Icon.sets is configured\n- Add icon element with text fallback for when icons are not configured\n\nFixes #11",
          "is_bot": false,
          "headline": "Make Icon configuration optional with text fallback",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2026-01-01T16:35:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "edcf9c04d02184b7966c1c2705f7da527e4f3aab",
          "body": null,
          "is_bot": false,
          "headline": "Auto-fix CS - CS master branch",
          "author_name": "Mark",
          "author_login": "dereuromark",
          "committed_at": "2025-12-01T17:32:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8a6b85de4fd3987e8575c66b41e3709f74e50f02",
          "body": "- Add parameter and return type hints to Command classes\n- Add type hints to Controller action methods\n- Add type hints to Entity and Table validation methods\n- Add declare(strict_types=1) to files missing it\n- Add use statement for Response class\n- Update PHPDoc blocks to match type signatures\n- Ad\n[…]\nlicit return statements where needed\n\nAll tests, PHPStan Level 8, and PHPCS checks pass.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add comprehensive type hints throughout codebase (#10)",
          "author_name": "Mark Scherer",
          "author_login": "dereuromark",
          "committed_at": "2025-11-19T15:36:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8eef9989d752ced68090ac3d95e4cf289dd01321",
          "body": "- Add parameter and return type hints to Command classes\n- Add type hints to Controller action methods\n- Add type hints to Entity and Table validation methods\n- Add declare(strict_types=1) to files missing it\n- Add use statement for Response class\n- Update PHPDoc blocks to match type signatures\n- Ad\n[…]\nlicit return statements where needed\n\nAll tests, PHPStan Level 8, and PHPCS checks pass.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add comprehensive type hints throughout codebase",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2025-11-19T13:59:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "555485c7ab73c04db100ec4e6a7be82e3501c7a3",
          "body": null,
          "is_bot": false,
          "headline": "Adjust phpcs config",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2025-11-17T09:52:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ac36d8eb56b2ee5237c9dc82866b0c7a4bd4ea8a",
          "body": null,
          "is_bot": false,
          "headline": "Fix docs",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2025-11-12T14:00:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5d23bdfb80d119d2ae6f6cbb9ee6ea9955ded948",
          "body": "Normalize @minutely to standard cron expression (* * * * *) before passing to CronExpression constructor to avoid InvalidArgumentException.\n\nThe @minutely shortcut is supported in the entity but not recognized by the dragonmantank/cron-expression library.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix @minutely cron expression handling in view template.",
          "author_name": "mscherer",
          "author_login": "dereuromark",
          "committed_at": "2025-11-08T11:40:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 26,
      "commits_last_year": 110,
      "latest_release_at": "2026-05-28T16:22:31Z",
      "latest_release_tag": "0.3.6",
      "releases_from_tags": false,
      "days_since_last_push": 30,
      "active_weeks_last_year": 29,
      "days_since_latest_release": 60,
      "mean_days_between_releases": 13.7
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 57,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "dereuromark/cakephp-queue-scheduler",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "queue",
            "plugin",
            "cron",
            "cakephp",
            "automation",
            "admin-panel",
            "recurring",
            "scheduler",
            "standalone-ui"
          ],
          "ecosystem": "packagist",
          "matches_repo": true,
          "registry_url": "https://packagist.org/packages/dereuromark/cakephp-queue-scheduler",
          "is_deprecated": false,
          "latest_version": "0.3.6",
          "repository_url": "https://github.com/dereuromark/cakephp-queue-scheduler",
          "versions_count": 26,
          "total_downloads": 22287,
          "dependents_count": 1,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 4614,
          "first_published_at": null,
          "latest_published_at": "2026-05-28T16:13:03Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 60
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 7,
      "watchers": 1,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 1
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 34351,
      "source_files_sampled": 66,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "composer.json"
      ],
      "advisories": {
        "error": "No resolved dependencies carried a version and a supported ecosystem",
        "scope": "repository_graph",
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 10,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "packagist"
      ],
      "dependencies": [
        {
          "name": "cakephp/cakephp",
          "manifest": "composer.json",
          "ecosystem": "packagist",
          "version_constraint": "^5.1.1"
        },
        {
          "name": "dragonmantank/cron-expression",
          "manifest": "composer.json",
          "ecosystem": "packagist",
          "version_constraint": "^3.3"
        },
        {
          "name": "dereuromark/cakephp-tools",
          "manifest": "composer.json",
          "ecosystem": "packagist",
          "version_constraint": "^3.0.0"
        },
        {
          "name": "dereuromark/cakephp-queue",
          "manifest": "composer.json",
          "ecosystem": "packagist",
          "version_constraint": "^8.9.0"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "cakephp/cakephp",
            "direct": true,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "dereuromark/cakephp-queue",
            "direct": true,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "dereuromark/cakephp-tools",
            "direct": true,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "dragonmantank/cron-expression",
            "direct": true,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "cakephp/migrations",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "dereuromark/cakephp-templating",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "fig-r/psr2r-sniffer",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "panlatent/cron-expression-descriptor",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "php",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          },
          {
            "name": "phpunit/phpunit",
            "direct": false,
            "version": null,
            "ecosystem": "packagist"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 10,
        "direct_count": 4,
        "indirect_count": 6
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 38,
        "open_issues": 1,
        "closed_ratio": 0.857,
        "closed_issues": 6,
        "closed_unmerged_prs": 4
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "dereuromark",
          "commits": 186,
          "avatar_url": "https://avatars.githubusercontent.com/u/39854?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": [
        "phpcs.xml",
        "phpstan.neon"
      ],
      "has_editorconfig": true,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 1,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "15 out of 15 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 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 3 contributing companies or organizations -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "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": 10,
            "reason": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": null,
            "reason": "no dependencies found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 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": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "6caadcf36793f03190eefc112c9391f9cb4e463d",
        "ran_at": "2026-07-28T09:47:28Z",
        "aggregate_score": 4.4,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-28T02:10:10Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-05-28T16:13:03Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 49,
          "created_at": "2026-07-16T11:25:12Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/dereuromark/cakephp-queue-scheduler",
    "host": "github.com",
    "name": "cakephp-queue-scheduler",
    "owner": "dereuromark"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 65,
      "inputs": {
        "security": 44,
        "vitality": 86,
        "community": 42,
        "governance": 62,
        "engineering": 84
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 86,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 77,
            "inputs": {
              "commits_last_year": 110,
              "human_commit_share": 1,
              "days_since_last_push": 30,
              "active_weeks_last_year": 29
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 30 days ago",
                "points": 28.8,
                "status": "partial",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "29/52 weeks with commits",
                "points": 20.1,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 29
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "110 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 110
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "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": 100,
            "inputs": {
              "releases_count": 26,
              "latest_release_tag": "0.3.6",
              "releases_from_tags": false,
              "days_since_latest_release": 60,
              "mean_days_between_releases": 13.7
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "26 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 26
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 60 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 60
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~13.7 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 13.7
                    }
                  }
                ],
                "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": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 30,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 30 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "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": 42,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 13,
            "inputs": {
              "forks": 0,
              "stars": 7,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "7 stars",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "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": "1 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": null,
            "notes": [],
            "value": 51,
            "inputs": {
              "packages": [
                "dereuromark/cakephp-queue-scheduler"
              ],
              "dependents": 1,
              "ecosystems": "packagist",
              "total_downloads": 22287,
              "monthly_downloads": 4614
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "4,614 downloads/month across packagist",
                "points": 48.9,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 4614,
                      "ecosystems": "packagist"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "1 packages depend on it",
                "points": 2,
                "status": "partial",
                "details": [
                  {
                    "code": "registry_dependents",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 62,
        "weight": 0.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 3 contributing companies or organizations -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "merged_prs": 38,
              "open_issues": 1,
              "closed_issues": 6,
              "issue_closed_ratio": 0.857,
              "closed_unmerged_prs": 4
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "86% of issues closed",
                "points": 40.1,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 86
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "38/42 decided PRs merged",
                "points": 34.6,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 38,
                      "decided": 42
                    }
                  }
                ],
                "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": "good",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 70,
            "inputs": {
              "followers": 750,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "dereuromark",
              "public_repos": 123,
              "account_age_days": 6437
            },
            "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": "750 followers of dereuromark",
                "points": 20.7,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 750,
                      "login": "dereuromark"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "123 public repos, account ~17 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 123
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 17
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "dereuromark/cakephp-queue-scheduler"
              ],
              "ecosystems": "packagist",
              "any_deprecated": false,
              "min_days_since_publish": 60
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on packagist",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "packagist"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 60 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 60
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "26 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 26
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 84,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "excellent",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 90,
            "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": "phpcs.xml, phpstan.neon",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "phpcs.xml, phpstan.neon"
                    }
                  }
                ],
                "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": "15 out of 15 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 44,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "pinned_dependencies",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 44,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 13,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 5,
              "scorecard_aggregate": 4.4
            },
            "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 is not maximal on development and all release branches",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "15 out of 15 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file 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": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "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": "at_risk",
        "name": "AI Readiness",
        "value": 43,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 37,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.7,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "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": "70 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 37.3,
                "status": "partial",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 70,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_pinned_dependencies"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 43,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0.03,
              "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": "phpcs.xml, phpstan.neon",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "phpcs.xml, phpstan.neon"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "3 of the last 100 commits agent-authored or agent-credited",
                "points": 6,
                "status": "partial",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 3,
                      "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": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "moderate",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "primary_language": "PHP",
              "largest_source_bytes": 34351,
              "source_files_sampled": 66,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "PHP without a type-check config",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_typecheck_config_language",
                    "params": {
                      "language": "PHP"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/66 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 66,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "No resolved dependencies carried a version and a supported ecosystem"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-28T09:47:39.444648Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/d/dereuromark/cakephp-queue-scheduler.svg",
  "full_name": "dereuromark/cakephp-queue-scheduler",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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