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

itdove / ai-guardian

AI IDE security hook: blocks directories, scans secrets, and protects AI interactions

PythonВласна ліцензія★ 10 зірок⑂ 5 форківз бер. 2026 р.Переглянути на GitHub ↗

itdove/ai-guardian має індекс здоров’я 64 зі 100, що відповідає смузі «Помірний». Найвищий показник — Vitality (82/100), найнижчий — Community & Adoption (41/100). Останнє оновлення — сьогодні. Більшість нещодавньої роботи виконує один учасник.

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

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

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

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

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

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

Власність

Dominique VernierОсобистий обліковий запис
6 підписників77 публічних репозиторіївз трав. 2017 р.Red Hat

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

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

РеєстрПакетВерсіяЗавантажень / місВерсіїОстання публікаціяТеги
PyPIai-guardian1.15.0-330 днів томуaiclaudecursorgitleakshookssecretssecurity

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

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

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

82Добрий · 22% загального індексу
Як обчислюється оцінка
36/36Свіжість push — останній push 0 дн. тому
11.8/36Ритм комітів — 17/52 тижнів із комітами
18/18Обсяг комітів — 1 722 комітів за останній рік
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
Використані вхідні дані
commits_last_year1 722
human_commit_share1
days_since_last_push0
active_weeks_last_year17
Як обчислюється оцінка
27/27Випускає релізи — опубліковано 100 релізів
36/36Свіжість релізів — останній реліз 0 дн. тому
27/27Ритм релізів — реліз кожні ~0,1 дн.
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Використані вхідні дані
releases_count100
latest_release_tagrc-1.16.0-dev-main.2f11f5e
releases_from_tagsні
days_since_latest_release0
mean_days_between_releases0,1

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

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

41У зоні ризику · 18% загального індексу
Як обчислюється оцінка
15.5/60Зірки — 10 зірок
5/25Форки — 5 форків
0/15Спостерігачі — 0 спостерігачів
Використані вхідні дані
forks5
stars10
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Як обчислюється оцінка
22.5/22.5README
16.9/22.5Ліцензія — файл ліцензії наявний, не є визнаною ліцензією
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ні

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

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

59Помірний · 24% загального індексу
Як обчислюється оцінка
9/54Бас-фактор — на 1 контриб’ютор(ів) припадає половина всіх комітів
0/22.5Розподіл комітів — головний контриб’ютор — автор 100% комітів
2.7/13.5Широта контриб’юторів — 2 контриб’юторів
6/10OpenSSF Scorecard: Contributors — project has 2 contributing companies or organizations -- score normalized to 6
Використані вхідні дані
bus_factor1
contributors_sampled2
top_contributor_share0,998
Як обчислюється оцінка
45/46.8Вирішення issue — закрито 96% issue
38.2/38.3Прийняття PR — злито 811/813 вирішених PR
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Використані вхідні дані
merged_prs811
open_issues33
closed_issues865
issue_closed_ratio0,963
closed_unmerged_prs2
Як обчислюється оцінка
10/30Підтримка власника — особистий (користувацький) обліковий запис
0/20Верифікований домен — не застосовно до користувацьких облікових записів
6.1/25Охоплення власника — 6 підписників у itdove
25/25Послужний список — 77 публічних репозиторіїв, вік облікового запису ~9 р.
Використані вхідні дані
followers6
owner_typeUser
is_verified
owner_loginitdove
public_repos77
account_age_days3 359
Виключено з оцінювання (немає даних або не застосовно): Верифікований домен. Залишкові ваги перенормовано.

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

100Відмінний
Як обчислюється оцінка
25/25Опубліковано й доступно — 1 пакет(ів) у pypi
35/35Свіжість публікацій — остання публікація 0 дн. тому
20/20Історія версій — 33 опублікованих версій
20/20Не застарілий — активний, не deprecated і не yanked
Використані вхідні дані
packagesai-guardian
ecosystemspypi
any_deprecatedні
min_days_since_publish0

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

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

82Добрий · 20% загального індексу
Як обчислюється оцінка
24/24Процеси CI — 12 процес(ів) CI
24/24Наявні тести
16/16Конфігурація лінтера
9.6/9.6Pre-commit-хуки
0/6.4.editorconfig
20/20OpenSSF Scorecard: CI-Tests — 26 out of 26 merged PRs checked by a CI test -- score normalized to 10
Використані вхідні дані
has_ciтак
has_testsтак
has_editorconfigні
has_linter_configтак
has_precommit_configтак

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

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

Безпека

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

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

Стан безпеки

53Помірний
Як обчислюється оцінка
7.5/7.5Binary-Artifacts — no binaries found in the repo
4.5/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 26 out of 26 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
1.5/2.5Contributors — project has 2 contributing companies or organizations -- score normalized to 6
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.2/2.5Ліцензія — license file detected
7.5/7.5Maintained — 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Використані вхідні дані
sourceopenssf_scorecard
checks_evaluated18
scorecard_versionv5.5.0
checks_inconclusive0
scorecard_aggregate5,3

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

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

73Добрий · 0% загального індексу
Як обчислюється оцінка
45/45Інструкції для агентів — AGENTS.md, CLAUDE.md, examples/aider/.aider.conf.yml
0/15Машиночитана документація (llms.txt)
40/40Читабельна історія комітів — намір зазначено у 99 з 100 людських комітів (структурований заголовок або пояснювальний текст)
Використані вхідні дані
has_llms_txtні
legible_history_share0,99
agent_instruction_filesAGENTS.md, CLAUDE.md, examples/aider/.aider.conf.yml
agent_instruction_max_bytes70 167
Як обчислюється оцінка
18/18Розгортання однією командою — Makefile
22/22Автоматизовані тести
11/11Конфігурація лінтера / форматера
0/11Статична перевірка типів
10/10Відтворюване середовище — Dockerfile
10/10Підтверджена практика роботи з агентами — 99 з останніх 100 комітів створено агентом або з його зазначенням
5/8Автоматизоване супроводження — автоматизацію залежностей налаштовано, але у вибірці комітів її не видно
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Використані вхідні дані
has_nixні
has_testsтак
lockfiles
has_dockerfileтак
typed_languageні
bootstrap_filesMakefile
has_devcontainerні
has_linter_configтак
typecheck_configs
agent_commit_share0,99
toolchain_manifests
dependency_bot_commit_share0
Як обчислюється оцінка
0/45Типізований код — Python без конфігурації перевірки типів
53.3/55Керовані розміри файлів — 17/558 файлів вихідного коду понад 60 КБ
Використані вхідні дані
primary_languagePython
largest_source_bytes259 298
source_files_sampled558
oversized_source_files17
Як обчислюється оцінка
0/40Схема API (OpenAPI/GraphQL/proto)
20/20Сервер MCP
40/40Придатні до запуску приклади — examples
Використані вхідні дані
example_dirsexamples
has_mcp_signalтак
api_schema_files

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

10зірок GitHub
2контриб'юторів
1 722комітів за останні 12 місяців
0днів від останнього пушу
100релізів
1бас-фактор
33відкритих issue
PyPIпакетних екосистем

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

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • deps.dev does not index pypi:ai-guardian@1.15.0; advisories assessed against the repository dependency graph instead
  • No resolved dependencies carried a version and a supported ecosystem

Докладніше

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

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

12345512026-042026-052026-06
OpenSSF Scorecard 5.3 / 10
5.3сукупно

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

10Binary-Artifactsno binaries found in the repo
6Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests26 out of 26 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
6Contributorsproject has 2 contributing companies or organizations -- score normalized to 6
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
9Licenselicense file detected
10Maintained30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
Прямі залежності 28
РеєстрПакетОбмеження версіїМаніфест
PyPItextual>=0.47.0pyproject.toml
PyPIjsonschema>=4.0.0pyproject.toml
PyPIrequests>=2.28.0pyproject.toml
PyPItomli>=2.0.0pyproject.toml
PyPItomli-w>=1.0.0pyproject.toml
PyPIpyyaml>=6.0.0pyproject.toml
PyPItree-sitter>=0.25.0pyproject.toml
PyPItree-sitter-json>=0.24.0pyproject.toml
PyPItree-sitter-python>=0.23pyproject.toml
PyPItree-sitter-javascript>=0.23pyproject.toml
PyPItree-sitter-typescript>=0.23pyproject.toml
PyPItree-sitter-go>=0.23pyproject.toml
PyPItree-sitter-rust>=0.23pyproject.toml
PyPItree-sitter-java>=0.23pyproject.toml
PyPItree-sitter-ruby>=0.23pyproject.toml
PyPItree-sitter-c>=0.23pyproject.toml
PyPItree-sitter-cpp>=0.23pyproject.toml
PyPItree-sitter-bash>=0.23pyproject.toml
PyPIpystray>=0.19.0pyproject.toml
PyPIPillow>=9.0.0pyproject.toml
PyPIdocker>=7.0,<9pyproject.toml
PyPImcp>=1.10.0pyproject.toml
PyPIrapidocr-onnxruntime>=1.4.0pyproject.toml
PyPIonnxruntime>=1.15.0pyproject.toml
PyPInicegui>=3.0.0pyproject.toml
PyPItokenizers>=0.15.0pyproject.toml
PyPIboto3>=1.28.0pyproject.toml
PyPIbandit>=1.7.0pyproject.toml
Усі залежності 29

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

РеєстрПакетВерсіяЗв'язок
PyPIbanditпряма
PyPIboto3пряма
PyPIdockerпряма
PyPIjsonschemaпряма
PyPImcpпряма
PyPIniceguiпряма
PyPIonnxruntimeпряма
PyPIpillowпряма
PyPIpystrayпряма
PyPIpyyamlпряма
PyPIrequestsпряма
PyPItextualпряма
PyPItokenizersпряма
PyPItomli-wпряма
PyPItree-sitterпряма
PyPItree-sitter-bashпряма
PyPItree-sitter-cпряма
PyPItree-sitter-cppпряма
PyPItree-sitter-goпряма
PyPItree-sitter-javaпряма
PyPItree-sitter-javascriptпряма
PyPItree-sitter-jsonпряма
PyPItree-sitter-pythonпряма
PyPItree-sitter-rubyпряма
PyPItree-sitter-rustпряма
PyPItree-sitter-typescriptпряма
PyPIpygobjectнепряма
PyPIpytestнепряма
PyPIpytest-asyncioнепряма
Сповіщення про залежності не оцінено

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

Звіт у форматі JSON машиночитний
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 18540,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Shell": 65736,
        "Python": 9412247,
        "Makefile": 230,
        "Dockerfile": 6869,
        "PowerShell": 9832
      },
      "pushed_at": "2026-07-22T17:41:21Z",
      "created_at": "2026-03-23T16:55:42Z",
      "owner_type": "User",
      "updated_at": "2026-07-22T17:41:18Z",
      "description": "AI IDE security hook: blocks directories, scans secrets, and protects AI interactions",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": "NOASSERTION",
      "primary_language": "Python",
      "significant_languages": [
        "Python"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Dominique Vernier",
      "type": "User",
      "login": "itdove",
      "company": "Red Hat",
      "location": null,
      "followers": 6,
      "avatar_url": "https://avatars.githubusercontent.com/u/28610057?v=4",
      "created_at": "2017-05-10T21:35:07Z",
      "is_verified": null,
      "public_repos": 77,
      "account_age_days": 3359
    },
    "license": {
      "state": "custom",
      "spdx_id": null,
      "raw_spdx": "NOASSERTION",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "rc-1.16.0-dev-main.2f11f5e",
          "kind": "other",
          "published_at": "2026-07-22T17:41:22Z"
        },
        {
          "tag": "rc-1.16.0-dev-main.22b17fd",
          "kind": "other",
          "published_at": "2026-07-22T17:40:35Z"
        },
        {
          "tag": "v1.15.0",
          "kind": "minor",
          "published_at": "2026-07-22T17:38:15Z"
        },
        {
          "tag": "rc-1.15.0-dev-1713",
          "kind": "other",
          "published_at": "2026-07-22T16:42:05Z"
        },
        {
          "tag": "rc-1.15.0-dev-1709",
          "kind": "other",
          "published_at": "2026-07-22T13:02:07Z"
        },
        {
          "tag": "rc-1.15.0-dev-1708",
          "kind": "other",
          "published_at": "2026-07-22T11:44:47Z"
        },
        {
          "tag": "rc-1.15.0-dev-1707",
          "kind": "other",
          "published_at": "2026-07-22T11:23:10Z"
        },
        {
          "tag": "rc-1.15.0-dev-1705",
          "kind": "other",
          "published_at": "2026-07-22T10:21:04Z"
        },
        {
          "tag": "rc-1.15.0-dev-1704",
          "kind": "other",
          "published_at": "2026-07-22T01:45:37Z"
        },
        {
          "tag": "rc-1.15.0-dev-1703",
          "kind": "other",
          "published_at": "2026-07-22T01:42:20Z"
        },
        {
          "tag": "rc-1.15.0-dev-1702",
          "kind": "other",
          "published_at": "2026-07-22T01:00:19Z"
        },
        {
          "tag": "rc-1.15.0-dev-1699",
          "kind": "other",
          "published_at": "2026-07-22T00:19:01Z"
        },
        {
          "tag": "rc-1.15.0-dev-1698",
          "kind": "other",
          "published_at": "2026-07-21T23:25:57Z"
        },
        {
          "tag": "rc-1.15.0-dev-1697",
          "kind": "other",
          "published_at": "2026-07-21T23:06:39Z"
        },
        {
          "tag": "rc-1.15.0-dev-1696",
          "kind": "other",
          "published_at": "2026-07-21T20:52:13Z"
        },
        {
          "tag": "rc-1.15.0-dev-1695",
          "kind": "other",
          "published_at": "2026-07-21T20:07:53Z"
        },
        {
          "tag": "rc-1.15.0-dev-1694",
          "kind": "other",
          "published_at": "2026-07-21T19:35:52Z"
        },
        {
          "tag": "rc-1.15.0-dev-1693",
          "kind": "other",
          "published_at": "2026-07-21T18:24:46Z"
        },
        {
          "tag": "rc-1.15.0-dev-1677",
          "kind": "other",
          "published_at": "2026-07-21T17:43:00Z"
        },
        {
          "tag": "rc-1.15.0-dev-1691",
          "kind": "other",
          "published_at": "2026-07-21T17:42:44Z"
        },
        {
          "tag": "rc-1.15.0-dev-1685",
          "kind": "other",
          "published_at": "2026-07-21T16:47:54Z"
        },
        {
          "tag": "rc-1.15.0-dev-1674",
          "kind": "other",
          "published_at": "2026-07-21T16:47:31Z"
        },
        {
          "tag": "rc-1.15.0-dev-1679",
          "kind": "other",
          "published_at": "2026-07-21T14:05:00Z"
        },
        {
          "tag": "rc-1.15.0-dev-1665",
          "kind": "other",
          "published_at": "2026-07-21T12:35:06Z"
        },
        {
          "tag": "rc-1.15.0-dev-1675",
          "kind": "other",
          "published_at": "2026-07-20T20:57:13Z"
        },
        {
          "tag": "rc-1.15.0-dev-1673",
          "kind": "other",
          "published_at": "2026-07-20T20:52:45Z"
        },
        {
          "tag": "rc-1.15.0-dev-1671",
          "kind": "other",
          "published_at": "2026-07-20T20:07:43Z"
        },
        {
          "tag": "rc-1.15.0-dev-1653",
          "kind": "other",
          "published_at": "2026-07-20T20:07:35Z"
        },
        {
          "tag": "rc-1.15.0-dev-1666",
          "kind": "other",
          "published_at": "2026-07-20T19:11:24Z"
        },
        {
          "tag": "rc-1.15.0-dev-1585",
          "kind": "other",
          "published_at": "2026-07-20T17:25:40Z"
        },
        {
          "tag": "rc-1.15.0-dev-1661",
          "kind": "other",
          "published_at": "2026-07-20T16:29:48Z"
        },
        {
          "tag": "rc-1.15.0-dev-1659",
          "kind": "other",
          "published_at": "2026-07-20T16:01:01Z"
        },
        {
          "tag": "rc-1.15.0-dev-1658",
          "kind": "other",
          "published_at": "2026-07-20T15:40:16Z"
        },
        {
          "tag": "rc-1.15.0-dev-1656",
          "kind": "other",
          "published_at": "2026-07-20T15:15:53Z"
        },
        {
          "tag": "rc-1.15.0-dev-1654",
          "kind": "other",
          "published_at": "2026-07-20T14:07:30Z"
        },
        {
          "tag": "rc-1.15.0-dev-1652",
          "kind": "other",
          "published_at": "2026-07-20T13:19:19Z"
        },
        {
          "tag": "rc-1.15.0-dev-1651",
          "kind": "other",
          "published_at": "2026-07-17T22:29:39Z"
        },
        {
          "tag": "rc-1.15.0-dev-1650",
          "kind": "other",
          "published_at": "2026-07-17T20:58:46Z"
        },
        {
          "tag": "rc-1.15.0-dev-1649",
          "kind": "other",
          "published_at": "2026-07-17T20:24:34Z"
        },
        {
          "tag": "rc-1.15.0-dev-1642",
          "kind": "other",
          "published_at": "2026-07-17T19:42:06Z"
        },
        {
          "tag": "rc-1.15.0-dev-1648",
          "kind": "other",
          "published_at": "2026-07-17T19:39:50Z"
        },
        {
          "tag": "rc-1.15.0-dev-1646",
          "kind": "other",
          "published_at": "2026-07-17T19:11:54Z"
        },
        {
          "tag": "rc-1.15.0-dev-1645",
          "kind": "other",
          "published_at": "2026-07-17T19:05:07Z"
        },
        {
          "tag": "rc-1.15.0-dev-1640",
          "kind": "other",
          "published_at": "2026-07-17T18:37:49Z"
        },
        {
          "tag": "rc-1.15.0-dev-1638",
          "kind": "other",
          "published_at": "2026-07-17T17:14:12Z"
        },
        {
          "tag": "rc-1.15.0-dev-1637",
          "kind": "other",
          "published_at": "2026-07-17T16:27:58Z"
        },
        {
          "tag": "rc-1.15.0-dev-1635",
          "kind": "other",
          "published_at": "2026-07-17T15:56:23Z"
        },
        {
          "tag": "rc-1.15.0-dev-1630",
          "kind": "other",
          "published_at": "2026-07-17T15:42:52Z"
        },
        {
          "tag": "rc-1.15.0-dev-1632",
          "kind": "other",
          "published_at": "2026-07-17T14:42:53Z"
        },
        {
          "tag": "rc-1.15.0-dev-1631",
          "kind": "other",
          "published_at": "2026-07-17T12:38:42Z"
        },
        {
          "tag": "rc-1.15.0-dev-1629",
          "kind": "other",
          "published_at": "2026-07-17T11:47:58Z"
        },
        {
          "tag": "rc-1.15.0-dev-1624",
          "kind": "other",
          "published_at": "2026-07-17T11:33:18Z"
        },
        {
          "tag": "rc-1.15.0-dev-1623",
          "kind": "other",
          "published_at": "2026-07-17T10:13:44Z"
        },
        {
          "tag": "rc-1.15.0-dev-1606",
          "kind": "other",
          "published_at": "2026-07-16T18:20:14Z"
        },
        {
          "tag": "rc-1.15.0-dev-1619",
          "kind": "other",
          "published_at": "2026-07-16T17:15:02Z"
        },
        {
          "tag": "rc-1.15.0-dev-1615",
          "kind": "other",
          "published_at": "2026-07-16T15:14:49Z"
        },
        {
          "tag": "rc-1.15.0-dev-1613",
          "kind": "other",
          "published_at": "2026-07-16T14:16:51Z"
        },
        {
          "tag": "rc-1.15.0-dev-1610",
          "kind": "other",
          "published_at": "2026-07-16T13:43:45Z"
        },
        {
          "tag": "rc-1.15.0-dev-1611",
          "kind": "other",
          "published_at": "2026-07-16T13:09:18Z"
        },
        {
          "tag": "rc-1.15.0-dev-1604",
          "kind": "other",
          "published_at": "2026-07-16T00:16:39Z"
        },
        {
          "tag": "rc-1.15.0-dev-1605",
          "kind": "other",
          "published_at": "2026-07-15T22:26:57Z"
        },
        {
          "tag": "rc-1.15.0-dev-937",
          "kind": "other",
          "published_at": "2026-07-15T20:30:17Z"
        },
        {
          "tag": "rc-1.15.0-dev-1602",
          "kind": "other",
          "published_at": "2026-07-15T19:02:39Z"
        },
        {
          "tag": "rc-1.15.0-dev-936",
          "kind": "other",
          "published_at": "2026-07-15T10:38:36Z"
        },
        {
          "tag": "rc-1.15.0-dev-1598",
          "kind": "other",
          "published_at": "2026-07-14T20:55:40Z"
        },
        {
          "tag": "rc-1.15.0-dev-650",
          "kind": "other",
          "published_at": "2026-07-14T20:47:37Z"
        },
        {
          "tag": "rc-1.15.0-dev-1597",
          "kind": "other",
          "published_at": "2026-07-14T20:44:26Z"
        },
        {
          "tag": "rc-1.15.0-dev-1593",
          "kind": "other",
          "published_at": "2026-07-14T18:36:26Z"
        },
        {
          "tag": "rc-1.15.0-dev-1592",
          "kind": "other",
          "published_at": "2026-07-14T16:40:56Z"
        },
        {
          "tag": "rc-1.15.0-dev-main.b0ebcb5",
          "kind": "other",
          "published_at": "2026-07-13T20:00:14Z"
        },
        {
          "tag": "rc-1.15.0-dev-main.ecd036d",
          "kind": "other",
          "published_at": "2026-07-13T19:10:06Z"
        },
        {
          "tag": "v1.14.0",
          "kind": "minor",
          "published_at": "2026-07-13T17:47:12Z"
        },
        {
          "tag": "rc-1.14.0-dev-main.7f6aab6",
          "kind": "other",
          "published_at": "2026-07-13T14:25:34Z"
        },
        {
          "tag": "rc-1.14.0-dev-1567",
          "kind": "other",
          "published_at": "2026-07-12T16:43:08Z"
        },
        {
          "tag": "rc-1.14.0-dev-1534",
          "kind": "other",
          "published_at": "2026-07-09T08:31:06Z"
        },
        {
          "tag": "rc-1.14.0-dev-1533",
          "kind": "other",
          "published_at": "2026-07-09T08:31:03Z"
        },
        {
          "tag": "rc-1.14.0-dev-main.3180b07",
          "kind": "other",
          "published_at": "2026-07-09T00:44:28Z"
        },
        {
          "tag": "rc-1.14.0-dev-main.496f536",
          "kind": "other",
          "published_at": "2026-07-09T00:43:27Z"
        },
        {
          "tag": "v1.13.3",
          "kind": "patch",
          "published_at": "2026-07-09T00:41:28Z"
        },
        {
          "tag": "rc-1.14.0-dev-1528",
          "kind": "other",
          "published_at": "2026-07-08T21:50:30Z"
        },
        {
          "tag": "rc-1.14.0-dev-1525",
          "kind": "other",
          "published_at": "2026-07-08T20:33:59Z"
        },
        {
          "tag": "rc-1.14.0-dev-1524",
          "kind": "other",
          "published_at": "2026-07-08T20:14:11Z"
        },
        {
          "tag": "rc-1.14.0-dev-1523",
          "kind": "other",
          "published_at": "2026-07-08T19:41:46Z"
        },
        {
          "tag": "rc-1.14.0-dev-1517",
          "kind": "other",
          "published_at": "2026-07-08T19:04:41Z"
        },
        {
          "tag": "rc-1.14.0-dev-1519",
          "kind": "other",
          "published_at": "2026-07-08T17:24:31Z"
        },
        {
          "tag": "rc-1.14.0-dev-1518",
          "kind": "other",
          "published_at": "2026-07-08T17:19:51Z"
        },
        {
          "tag": "rc-1.14.0-dev-1516",
          "kind": "other",
          "published_at": "2026-07-08T16:54:42Z"
        },
        {
          "tag": "rc-1.14.0-dev-1515",
          "kind": "other",
          "published_at": "2026-07-08T16:37:39Z"
        },
        {
          "tag": "rc-1.14.0-dev-1514",
          "kind": "other",
          "published_at": "2026-07-08T16:26:40Z"
        },
        {
          "tag": "rc-1.14.0-dev-1511",
          "kind": "other",
          "published_at": "2026-07-08T15:48:18Z"
        },
        {
          "tag": "rc-1.14.0-dev-1509",
          "kind": "other",
          "published_at": "2026-07-08T14:10:58Z"
        },
        {
          "tag": "rc-1.14.0-dev-1506",
          "kind": "other",
          "published_at": "2026-07-08T14:10:24Z"
        },
        {
          "tag": "rc-1.14.0-dev-1499",
          "kind": "other",
          "published_at": "2026-07-08T12:44:09Z"
        },
        {
          "tag": "rc-1.14.0-dev-1502",
          "kind": "other",
          "published_at": "2026-07-08T10:44:16Z"
        },
        {
          "tag": "rc-1.14.0-dev-1498",
          "kind": "other",
          "published_at": "2026-07-07T15:45:18Z"
        },
        {
          "tag": "rc-1.14.0-dev-main.ffed89e",
          "kind": "other",
          "published_at": "2026-07-06T20:05:30Z"
        },
        {
          "tag": "v1.13.2",
          "kind": "patch",
          "published_at": "2026-07-06T19:46:27Z"
        },
        {
          "tag": "rc-1.14.0-dev-main.1ea6c76",
          "kind": "other",
          "published_at": "2026-07-06T19:41:11Z"
        },
        {
          "tag": "rc-1.14.0-dev-main.2e7febc",
          "kind": "other",
          "published_at": "2026-07-06T19:24:58Z"
        },
        {
          "tag": "v1.13.1",
          "kind": "patch",
          "published_at": "2026-07-06T19:18:14Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "2f11f5ed6f722e95a2f1618c918bff5049334bda",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: regenerate notebooklm-export.md for v1.15.0",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-22T17:41:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "22b17fde013091f1d2ce62f30a8d3b1e0232eaac",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.16.0-dev, reset README URLs to main",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-22T17:40:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f3eed84a621a633462e400f8563f17608064f119",
          "body": null,
          "is_bot": false,
          "headline": "Merge release-1.15 into main",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-22T17:39:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "36471c37308555bf59b54650cfba0bea16e32688",
          "body": "- Bump version 1.15.0-dev → 1.15.0 in pyproject.toml and __init__.py\n- Populate CHANGELOG.md with all v1.15.0 changes (Added/Changed/Fixed/Security)\n- Remove 23 duplicate \"Exfiltration behavior detection\" entries from old releases\n- Update README: integration table (5→14 IDEs), feature rows, pattern\n[…]\nility verification\n- Update docs: CONFIGURATION, COOKBOOK, TOML_PATTERNS, SECRET_SCANNING, MULTI_DAEMON_TRAY, SCANNER_INSTALLATION\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: prepare v1.15.0 release",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-22T17:28:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "79806ddd7213ca0b02e4674eae44720b1f848dad",
          "body": "…#1713)\n\n- Change missing config file status from failure to informational skip\n- Remove all_configured = False assignment for missing config paths\n- Add test for missing config file not causing FAIL status\n- Add test for mixed configured + missing config producing PASS\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: treat missing IDE config as \"not installed\" instead of failure (…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-22T16:41:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0a4766ff49e0ca454c4fe0d413c51cc00efdd4dc",
          "body": "- Add credentials-in-git-url rule to secrets.toml with regex matching\n  real passwords/tokens while skipping placeholders and env vars\n- Add detection and false-positive test cases for GitHub, GitLab,\n  Bitbucket, and Azure DevOps URL patterns\n- Exclude test_bundled_toml.py from gitleaks scanning\n- Bump secrets.toml expected rule count to 85\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: detect credentials embedded in git remote URLs (#1709)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-22T13:01:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2b1148d9f46a026ece031392dc7c3663ad0f0203",
          "body": "- Relocate MCP Security nav item from Configuration to Tools group\n  in both TUI and web navigation\n- Move corresponding help text to Tools section in TUI help docs\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: move MCP Security panel to Tools section (#1708)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-22T11:44:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4c2d3937f78db5e7c0714032aefd8ce27e72489f",
          "body": "- Add VIOLATION_FILTER_TYPES list to constants.py with display name,\n  API value, and description for all 20 violation types\n- Refactor TUI violations page to derive filters from shared constant\n  instead of hardcoded inline definitions\n- Refactor web violations page to derive filters from shared constant\n- Add slug/class mappings in TUI/web to adapt shared data to each UI\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: centralize violation filter types in constants (#1707)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-22T11:22:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d4700d6b7f8d00f478c9e0555c30e0319f85f667",
          "body": "- Move check_project_config(cwd) before global/dir pause guards so\n  _project_dir_last_seen is updated even when scanning is skipped\n- Wrap early config check in try/except to match prior error handling\n- Add parametrized test covering project dir tracking under both\n  per-directory and global pause modes\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: load project config before pause check in daemon (#1705)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-22T10:20:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f97d2a6e5a8b85ed0ac0ce3cb0c063d3f38322e5",
          "body": "…ge (#1704)\n\n- Remove badge_row UI element and its population logic\n- Remove per-category badge rendering in _update_mode_hint refresh\n- Simplify layout to content column only\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: remove unused category badge row from detection patterns pa…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-22T01:45:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "35a1f86eb67ab3541c97ce9d567cad7182c4b6c8",
          "body": "- Build RULE_ID_TO_SLUG via dict comprehension over RULE_ID_TO_CONFIG_SECTION\n  and a reverse lookup of SLUG_TO_CONFIG_SECTION, replacing hand-maintained dict\n- Add special-case for UNICODE-001 → /pi-unicode mapping\n- Add TestRuleIdToSlug test class covering validity, unicode override,\n  and spot-check of expected values\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: derive RULE_ID_TO_SLUG from existing mappings (#1703)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-22T01:41:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "55fd6a0f14b9cdc6bda975a95ab59f0791d1115a",
          "body": "- Add run_scan_pipeline() and ScanPipelineResult to scan_analyzer.py\n- Replace duplicated scan/analyze logic in TUI scan_configure with pipeline call\n- Replace duplicated scan/analyze logic in web scan_configure with pipeline call\n- Update web tests to mock centralized pipeline instead of individual components\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: extract shared scan pipeline from TUI and web (#1702)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-22T00:59:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "11e11eb8d29cb7029ba99c7eee5da0bfce170ded",
          "body": "- Move RULE_ID_LABELS, RULE_ID_TO_SCANNER, and related dicts from\n  scan_analyzer.py to constants.py\n- Add SLUG_TO_CONFIG_SECTION, RULE_ID_TO_SLUG, RULE_ID_TO_CONFIG_SECTION,\n  and RULE_ID_TO_VIOLATION_TYPE mappings\n- Replace inline slug/config lookups in TUI and web modules with\n  constant dict references\n- Update tests to match new import paths and config section routing\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: centralize rule ID mappings in constants module (#1699)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-22T00:18:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "614a1b660018de6ff35d1fe5b6de5438d184db07",
          "body": "- Extract quiet_logging() context manager to tui/utils.py and logging_utils.py\n- Replace inline _suppress/_restore_logging methods across TUI modules\n- Add safe_int() and format_count() helpers to tui/utils.py\n- Add unit tests for new utility functions\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: centralize logging suppression into shared TUI utility (#1698)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T23:25:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d4ed5867d6d7f004f96cfb83e57ca9cade42ba07",
          "body": "- Add ConfigSaveMixin to schema_defaults.py with shared config\n  load/save/path-resolution helpers used across all TUI panels\n- Replace per-panel duplicated _get_config_path, JSON read/write,\n  and _is_project_scope logic with mixin methods in 20 panel files\n- Add Skill \"release\" permission rule to ai-guardian.json\n- Update tests to match new mixin-based config plumbing\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: extract ConfigSaveMixin to deduplicate TUI config I/O (#1697)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T23:06:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7d483cf027f3d694675805262c095b777966e35a",
          "body": "- Move _load_overlaid_config to scanners module with internal loader map\n- Pre-compute overlaid configs for all overlay-enabled scanners in both\n  content_pipeline and post_tool_use hooks\n- Add _LOADER_MAP and get_loader to ScannerRegistry for loader lookup\n- Remove per-scanner loader_fn parameter in favor of registry-based dispatch\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: centralize language overlay config loading (#1696)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T20:51:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "633f614ab7356d85e42f451bb0740086fd17e17c",
          "body": "- Replace line-count incremental reads with byte-offset (seek-based)\n  positioning in _read_jsonl_incremental and all adapter callers\n- Add atomic write (tempfile + os.replace) for transcript positions file\n- Update copilot_chat, jsonl, kiro, openclaw, windsurf adapters to pass\n  and receive byte offsets instead of line counts\n- Update corresponding unit tests for new position semantics\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: switch transcript scanning to byte-offset tracking (#1695)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T20:07:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7b1b3c205b868b69f5f4f00ac8abb897f78179bb",
          "body": "- Add path traversal validation for session_files in _run_session_start_event\n- Add workspace_files param to _run_scenario_event for simulated project dirs\n- Set project_dir_override so language detection uses workspace file structure\n- Add language-overlay.yaml scenario files for minimal/moderator/standard/strict\n- Update scenario schema to include workspace_files and new test coverage\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add workspace_files support and path traversal guards (#1694)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T19:35:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e943a8cfa8c8841a4762e85010beafed3a18105d",
          "body": "- Change _get_most_recent_entry return type to Optional[Tuple[str, float]]\n- Refactor copilot_chat to use shared _get_most_recent_entry helper\n- Refactor openclaw to use shared _get_most_recent_entry helper\n- Update cline and kiro callers to destructure new tuple return\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: return mtime from _get_most_recent_entry (#1693)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T18:24:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d98c8a9c8de78f50cae681505589245a4c90ab24",
          "body": "…ole (#1690)\n\n* Feat: add init --scan UI to TUI and web console\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n* test: relax Directory Scan position assertion in TUI nav\n\n- Remove check that Directory Scan is last item in Tools group\n- Keep a\n[…]\ndocstring to match relaxed constraint\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1677: feat: add init --scan UI to TUI and web cons…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T17:42:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a5d567fe005a21e4a5d15c9c548eb48d279f556c",
          "body": "Operation blocked by ai-guardian: secret detected\n\nOriginal prompt: Based on this git diff, generate a commit message in conventional commit format.\n\nGit Status:\nM tests/unit/test_copilot_chat_transcript.py\n M tests/unit/test_kiro_transcript.py\n M tests/unit/test_openclaw_transcript.py\n M tests/unit\n[…]\nFocus on WHAT changed, not WHY\n- NO JIRA keys or ticket numbers\n\nReturn ONLY the commit message.\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "UserPromptSubmit operation blocked by hook: (#1691)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T17:42:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0793d63ee1ba9bd5c28a07499fd81b02ef2801be",
          "body": "- Remove pattern server URL/version config and test connection binding\n- Remove PatternServerSection widget and server connectivity testing\n- Replace pattern server help text with per-engine pattern server reference\n- Add privacy warning for external liveness validation API calls\n- Delete test_tui_s\n[…]\nets_pattern_server.py (dead tests)\n- Update web secrets page to match TUI pattern server removal\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: remove pattern server from secrets panel (#1685)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T16:47:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ad8b785740adc7186644a70fd66045023a6141ab",
          "body": "…jection via ScannerEntry flag (#1683)\n\n* refactor: hoist language overlay into content pipeline\n\n- Add _load_overlaid_config() helper in content_pipeline.py\n- Move apply_language_overlays call from scanners.py to callers\n- Pass pre-overlaid config to run_prompt_injection_scan\n- Add supports_languag\n[…]\n (1M context) <noreply@anthropic.com>\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1674: refactor: pipeline-level language overlay in…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T16:47:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "999f926ecfb28d785bf39b17f20ef8b5b617870c",
          "body": "- Replace **kwargs with explicit original_file_path param in run_single_engine\n- Pass original_file_path through _parse_secrets_result and _build_scan_result_from_dict\n- Use resolved original path in SecretMatch.file for python scanner and dict builder\n- Add parametrized tests verifying file path appears in scan results\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: thread original_file_path through all scan result paths (#1679)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T14:04:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cc28ad1b6d436e3d74063ae262c8da76d89e4d03",
          "body": "…ining scanner types (#1676)\n\n* refactor: extract config builders and table-driven scanner routing\n\n- Replace if/elif chains in fingerprint_finding and _scanner_for_rule_id\n  with table-driven lookups (_FINGERPRINT_DETAIL_KEY, _RULE_ID_PATTERNS)\n- Extract reusable config builder functions (_build_es\n[…]\nforward slashes regardless of host OS\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1665: feat: init --scan config generation for rema…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-21T12:34:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4cb85cb9db194d4bfc8a55f04ff76ee4432e84bb",
          "body": "- Extract apply_language_overlays() helper in scanners.py\n- Add scanner_name param to get_language_allowlist_patterns()\n- Cache all scanner patterns together per project_dir\n- Update tests for multi-scanner overlay support\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: generalize language overlay to all scanners (#1675)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T20:56:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a4d3827fa359d163deb130468d2e2bfe33e9f531",
          "body": "- Add _read_jsonl_incremental() and _scan_jsonl_incremental() to common.py\n- Refactor copilot_chat, kiro, openclaw, windsurf scanners to use shared helpers\n- Remove duplicated JSONL reading/scanning boilerplate from each adapter\n- Update tests to match simplified adapter internals\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: extract shared JSONL scan logic into common helpers (#1673)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T20:52:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e79aa97577af8852ea594724c048da840a23c069",
          "body": "- Add _get_most_recent_entry() to common.py for finding newest dir entry\n- Replace inline scandir loops in cline.py and kiro.py with shared helper\n- Update tests to cover new helper and parameterized match/mtime functions\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: extract shared _get_most_recent_entry helper (#1671)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T20:07:23Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d0f5342749d3542b9012507b260024e4b15cba07",
          "body": "…er executor — skip_file_types relies on temp filename (#1668)\n\n* feat: pass original file path through scan pipeline\n\n- Add original_file_path parameter to run_engine and run_python_scanner\n- Extract original_file_path from strategy context and forward to executors\n- Use original path instead of te\n[…]\nal parameters like original file path\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1653: fix: thread original file_path through scann…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T20:07:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "02261d2e316f66965caf6b73b600e2b299555d5d",
          "body": "- Add scan_analyzer module to cluster findings by pattern and identify high-frequency false positives\n- Add --scan and --threshold flags to init-project CLI command\n- Generate tuned config with allowlist patterns and per-scanner directory ignores\n- Add smoke tests for init-project --scan workflows\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add init-project --scan for false positive analysis (#1666)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T19:11:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3ea3ca2e7321cdbf433af65ad215268ae1ecb0cc",
          "body": "…ess known false positive patterns per language (#1663)\n\n* feat: auto-allowlist language false positives in prompt injection scan\n\n- Add false_positive_patterns dict to LanguageDefinition for per-scanner allowlists\n- Populate prompt_injection patterns for Python, JS, TS, PHP, Ruby, C/C++, Go, Java, \n[…]\ns multiple lines for PEP 8 compliance\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1585: feat: auto-detect project language and suppr…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T17:25:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "82221e683f5701cb3d0ae401de04bd1dc02c2b9c",
          "body": "- Add AiderDeskTranscriptAdapter for Markdown chat history files\n- Add OpenClawTranscriptAdapter for JSONL transcript files\n- Register both adapters in TRANSCRIPT_ADAPTERS list\n- Add unit tests for both new scanners\n- Update AGENT_SUPPORT.md with new transcript formats\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add AiderDesk and OpenClaw transcript scanners (#1661)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T16:29:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "40f55eebc0eaa2b99564b4b0c77fc8bfea22ddd8",
          "body": "- Add Copilot Chat (VS Code) JSONL delta journal to transcript adapter table\n- Document Augment Code transcript scanning infeasibility (server-side storage, no UserPromptSubmit hook)\n- Note Crush PreToolUse-only limitation already existed; new entries placed before it\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add Copilot Chat and Augment Code agent support notes (#1659)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T16:00:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7784b05dc153107a85ae41cca63a516a026ec49f",
          "body": "- Add CopilotChatTranscriptAdapter for VS Code JSONL delta journal files\n- Register adapter in TRANSCRIPT_ADAPTERS and __all__ exports\n- Document Copilot Chat session path in AGENT_SUPPORT.md\n- Add unit tests for copilot chat transcript scanning\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add Copilot Chat (VS Code) transcript scanner (#1658)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T15:39:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "12f02272f6b32c82f48f640c10b7c450a7357c47",
          "body": "- Add KiroTranscriptAdapter for ~/.kiro/sessions/cli/*.jsonl files\n- Register adapter and incremental scanner in transcript __init__.py\n- Add unit tests for Kiro transcript parsing\n- Document Kiro in AGENT_SUPPORT.md agent table\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add Kiro transcript scanning support (#1656)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T15:15:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "acbed7ab5cd55ab1d8828468f3090d177f009da2",
          "body": "- Add skip_file_types metadata field to TOML rules, converted to\n  frozenset at compile time for fast lookup\n- Thread file_ext parameter through cache.scan() and\n  TomlPatternsScanner to skip rules by extension\n- Apply skip_file_types to yaml-password rule to suppress false\n  positives in source code files\n- Add unit tests for skip_file_types parsing and scanner filtering\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add skip_file_types support to pattern rules (#1654)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T14:07:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "59a5a3af334ca2f9fb2234e46dfbaefcc407bcdb",
          "body": "- Add `ai-guardian ml setup` CLI command that checks deps, downloads\n  model, and configures prompt_injection detection in one step\n- Add `ensure_model_downloaded()` for idempotent model download with\n  verification, used by both CLI and daemon auto-download\n- Add `auto_download_model` config field \n[…]\ne templates with prompt_injection defaults and add\n  unit tests for new setup/download functions\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add one-command ML detection setup and auto-download (#1652)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-20T13:18:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "543136ab43b0d0c447e343c8b903ffe7bf0495ae",
          "body": "- Add _sanitize_warn_reason() and _build_warn_agent_context() to base\n  adapter, stripping file/line/pattern details from agent-facing output\n- Pass violation_type through warn response chain in all adapters\n  (Claude, Cline, Copilot, Cursor, Gemini, Kiro, Windsurf)\n- Keep full diagnostic details in\n[…]\nason mappings: offensive_language, canary_detected,\n  code_security, exfil_detection, bash_exfil\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: sanitize warn-mode context sent to AI agents (#1651)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T22:29:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d901771f788997044a2fd6c446715e41f670704b",
          "body": "- Add select-based read timeout (30s) to prevent hanging on\n  unresponsive leaktk subprocess; kill and raise on expiry\n- Deduplicate restart() by delegating to stop()\n- Extract _make_started_proc helper in tests to reduce mock boilerplate\n- Replace empty-response test with timeout and crash test cases\n\n\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: add timeout guard to leaktk listen mode scans (#1650)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T20:58:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "409530bb74752d62d7842a2642adc9f2cb5a8bc1",
          "body": "- Add token_prefixes config option for token_not_placeholder rules\n- Update Slack token rule to use short \"xox\" keyword with explicit prefixes\n- Update _build_token_prefix_re to prefer token_prefixes over keywords\n- Update sync test to validate token_prefixes with keywords fallback\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add token_prefixes field to secrets.toml rules (#1649)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T20:24:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "be1ffb48e8c8a665a80c2fabd53e5c26b2092528",
          "body": "…ge — reason and systemMessage contain same text (#1647)\n\n* fix: use sanitized message in block response reason field\n\n- Replace raw sys_msg with sanitized value in _block_response reason\n- Update tests to assert reason contains sanitized label components\n- Verify reason differs from raw systemMessa\n[…]\nfor warning vs error in reason string\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1642: bug: PostToolUse block shows duplicate messa…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T19:41:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "14c379505b5316abb589925b644330de8050f66a",
          "body": "- Add supports_listen_mode and version_hint fields to EngineConfig\n- Route listen mode and version hints via config flags instead of type checks\n- Make listen mode log message engine-agnostic\n- Add tests for capability flag defaults and preset values\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: replace leaktk hardcoding with capability flags (#1648)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T19:39:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b206637ed3e3334dc584a61506623ebae888d807",
          "body": "- Change header nav button label from \"Menu\" to \"Quick Links\"\n- Replace hamburger menu icon with link icon\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: rename nav menu button to Quick Links (#1646)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T19:10:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7ea9cf32e0061f6233e34ab82b9b236b79756c7f",
          "body": "- Add listen_mode.py managing a long-lived LeakTK process that accepts\n  scan requests over stdin/stdout, reducing per-scan latency ~200ms→~5ms\n- Integrate listen mode lifecycle with daemon startup/shutdown and\n  config-change restart\n- Fall back to standard subprocess execution when daemon is not running\n  or listen mode is unavailable\n- Bump LeakTK pinned version to 0.3.4\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add LeakTK listen mode for persistent process scanning (#1645)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T19:04:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "08657855cc964eac1ff91300cc9b7bcacdd5ed66",
          "body": "- Build _TOKEN_PREFIX_RE dynamically from secrets.toml rules with\n  validation=\"token_not_placeholder\" instead of hardcoding prefixes\n- Update Slack token keywords from generic \"xox\" to specific prefixes\n  (xoxb-, xoxa-, xoxp-, xoxr-, xoxs-)\n- Add tests ensuring prefix regex stays in sync with secrets.toml\n- Add fallback to never-match regex when secrets.toml missing or broken\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: derive token prefix regex from secrets.toml (#1640)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T18:37:23Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "de940fbb28f99109c27f754d7d2da89ae58ead39",
          "body": "- Add _stderr_block_response() to HookAdapter base class\n- Replace duplicated combine/print/metadata pattern in copilot, kiro, windsurf adapters\n- Move sys import from child adapters to base.py\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: extract stderr block response into base adapter (#1638)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T17:13:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b35482280e8e6c6906ae3b5fa87bab2dfd103d72",
          "body": "…#1637)\n\n- Add TOML rules for openrouter-api-key, google-gemini-auth-key,\n  hashicorp-vault-token, and confluent-cloud-api-key\n- Register new prefixes in token_not_placeholder validator\n- Add display names to SECRET_TYPE_NAMES registry\n- Add detection and false-positive test cases for all four patterns\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add secret detection for OpenRouter, Gemini, Vault, Confluent (…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T16:27:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1cff2991482750fd0169c78a2fb4f2c10ba7f6de",
          "body": "- Import threading module in stats refresh test helper\n- Replace fixed 0.3s sleep with explicit join on stats-refresh thread\n- Use 2.0s timeout on thread join for reliable synchronization\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: replace sleep with thread join in wake detection test (#1635)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T15:55:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7ca2b9a9c5f9a150e5755f83fa8b83d995ebbdd9",
          "body": "…text on PostToolUse secret block (#1634)\n\n* feat: pass redacted output via additionalContext on secret block\n\n- Add redacted_output param to format_response across all hook adapters\n- Route redacted content through additionalContext so agents can\n  continue working with sanitized output instead of \n[…]\nign with project formatting standards\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1630: feat: send redacted output via additionalCon…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T15:42:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2e5a91979f05b0cce2f5b82beaeee3fe77be6563",
          "body": "- Rename env_not_file_path validator to env_not_false_positive and add\n  ALL_CAPS_IDENTIFIER exclusion to skip programming constants\n- Add password_not_false_positive validator for password/secret fields\n  that preserves underscore-prefixed and ALL_CAPS value detection\n- Keep env_not_file_path as ba\n[…]\ncompatible alias in registry\n- Add tests for ALL_CAPS identifier and password validator behavior\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: reduce false positives in env var secret detection (#1632)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T14:42:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7a090452843f4a2261719a8bba4d793b1151167c",
          "body": "======================================================================\n🛡️ Secret Detected\n======================================================================\n\nProtection: Secret Scanning (first-match strategy)\nSecret Type: Environment Variable\nLocation: user_prompt:87:15\nScanner: toml-patterns\nPa\n[…]\nFocus on WHAT changed, not WHY\n- NO JIRA keys or ticket numbers\n\nReturn ONLY the commit message.\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "UserPromptSubmit operation blocked by hook: (#1631)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T12:38:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ca6abd37e8f6a8464e12c7201e99cb029da22f67",
          "body": "- Merge TestNewSecretPatterns and TestGitleaksGapPatterns into single TestSecretPatterns class\n- Combine detection and false-positive cases into ALL_DETECTION_CASES and ALL_FALSE_POSITIVE_CASES lists\n- Remove duplicate parametrized test methods\n\n\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: consolidate secret pattern test classes (#1629)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T11:47:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "96d0281576340ee524d86fea61b147f392ba4cb4",
          "body": "…tokens — toml patterns not wired into output scanning (#1625)\n\n* fix: block secret-containing output instead of redact-and-pass\n\n- Switch has_secrets to True so post_tool_use blocks when secrets found\n- Add fallback block when redactor produces zero redactions\n- Pass error_message and violation_typ\n[…]\no redact-and-pass / log-only behavior\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1624: bug: PostToolUse secret scan misses env var …",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T11:32:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6fd916cb941a660f2d9c2c87535106ede22aff90",
          "body": "- Replace TestNewSecretPatterns class with parametrized test cases\n- Consolidate detection and false-positive tests into data-driven lists\n- Apply same parametrize pattern to TestNewProviderSecretPatterns\n- Reduce test boilerplate while preserving identical coverage\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: refactor secret detection tests to parametrized format (#1623)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-17T10:13:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bb697e6ca51e6bc436ae1f685a6d29c6bbeb0df1",
          "body": "- Add rules for secrets management (Doppler, HashiCorp TF, Pulumi)\n- Add rules for observability (Grafana, Sentry, Datadog)\n- Add rules for cloud providers (Cloudflare, DigitalOcean, Alibaba)\n- Add rules for developer tools (Snyk, Sourcegraph, Codecov, Buildkite)\n- Add Cohere API token detection\n- Update test assertions for new bundled rule count\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add 30 secret detection patterns for new providers (#1621)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-16T23:10:30Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "85a1d7b4f09ec116f45797994089dec6ec9d539a",
          "body": "…transcript_text I/O (#1616)\n\n* refactor: extract prune helper and reduce IO in transcript scanner\n\n- Extract _prune_stale_keys() from inline dict comprehensions\n- Remove unused fcntl import block\n- Cache datetime.now() call to avoid redundant UTC lookups\n- Skip saving seen findings when no new entr\n[…]\nn hot path).\nTest updated from assertNotIn to assertIn to reflect this.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1606: Remove dead fcntl import and optimize _scan_…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-16T18:19:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "65c8f95d289d66a8efdac55b0d6d1bc7ea39efae",
          "body": "- Fix scanner file paths in research reminder workflow to match\n  current src/ai_guardian/scanners/ layout\n- Add supply chain, offensive language, canary detection, and exfil\n  detection sections to research checklist\n- Record 2026-07-16 research review findings in AGENTS.md including\n  new secret patterns (Gemini AQ., OpenRouter, Vault, Confluent)\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: update pattern research workflow and log review (#1619)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-16T17:14:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "54d4faf3531721c2b3417036e3f767b0c15de390",
          "body": "- Wrap stats-refresh loop body in try/except to log and survive errors\n- Extract shared test helper _run_stats_refresh_tick to reduce nesting\n- Flatten deeply nested context managers using parenthesized with-statement\n- Add test for stats-refresh resilience when a sub-call raises\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: guard stats-refresh tick against unhandled exceptions (#1615)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-16T15:14:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "42c71db166636a3cba7e8b87761763f5dc218939",
          "body": "- Fix prefix vs raw_prefix bug in else branch of read_cursor_transcript\n  where SQL LIKE metachar in composer_id caused wrong key stripping\n- Add test for composer_id containing underscore covering both branches\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: use raw_prefix for bubble ID extraction in cursor scanner (#1613)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-16T14:16:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ba8ebce2dd993e632e6cc36550eade157935bf26",
          "body": "…rministic startup detection (#1612)\n\n* feat: add ready event to DaemonServer for deterministic startup sync\n\n- Add _ready_event (threading.Event) to DaemonServer, set after socket bind\n- Replace poll-based _wait_server_ready with event-based wait on _ready_event\n- Remove redundant retry loops and r\n[…]\n line before _wait_server_ready calls\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1610: Add readiness event to DaemonServer for dete…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-16T13:43:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "19973508838382b6eafd4f996db5493516ee1e6c",
          "body": "- Move running_server fixture from class method to module-level\n- Extract _connect helper to module-level function\n- Add _wait_server_ready helper with proper ping-based readiness check\n- Replace poll-for-socket-file loop with connection+ping verification\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: extract shared test helpers in daemon server tests (#1611)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-16T13:08:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3c2e39fb4c65718e1aa6d97a21b55fe160c5d488",
          "body": "…ript adapters (#1608)\n\n* refactor: extract shared position-tracking logic in transcript scanners\n\n- Add _scan_with_position_tracking helper to deduplicate incremental\n  scan boilerplate across Cline, Cursor, OpenCode, Windsurf, and JSONL\n- Add _discover_path helper for common transcript path resolu\n[…]\ny shared _scan_with_position_tracking\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1604: Refactor: Extract shared helpers from transc…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-16T00:16:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6145a0655875a2fb181cb860d7ed88a0af752f60",
          "body": "- Add WindsurfTranscriptAdapter and scan_windsurf_transcript_incremental\n- Register adapter in TRANSCRIPT_ADAPTERS and __all__ exports\n- Document Windsurf Cascade transcript path in AGENT_SUPPORT.md\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add transcript scanning for Windsurf (JSONL format) (#1605)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-15T22:26:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "feddb0a5c84b902c42322524834bdf8eb5d1b6cd",
          "body": "…ON format) (#1603)\n\n* feat: add Cline/ZooCode transcript scanning adapter\n\n- Add ClineTranscriptAdapter for JSON array format conversations\n- Register adapter in TRANSCRIPT_ADAPTERS and __all__ exports\n- Add unit tests for Cline transcript scanning\n- Update AGENT_SUPPORT.md with Cline/ZooCode trans\n[…]\nth directly instead of tuple indexing\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#937: Add transcript scanning for Cline/ZooCode (JS…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-15T20:29:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2c7dfc481879dccf33a1f8853c23e50e3dd86695",
          "body": "🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Remove _hp delegation shims in hook_events/ modules (#1602)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-15T19:02:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "63079b683570b41bd03e2fc34597111e6fc6480d",
          "body": "…rmat) (#1600)\n\n* refactor: extract transcript scanning into polymorphic adapter package\n\n- Refactor monolithic transcript scanner into scanners/transcript/ package\n  with per-IDE adapters (Claude Code, OpenCode, Cursor) behind a common\n  TranscriptAdapter interface\n- Add Cursor IDE transcript scann\n[…]\nll in cursor.py across multiple lines\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#936: Add transcript scanning for Cursor (SQLite fo…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-15T10:38:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9a5583f50388fdf8352630b4af4be99cae91a33d",
          "body": "…1598)\n\n- Add CRUSH_HOOK_EVENTS tuple to constants.py for centralized config\n- Tighten CrushAdapter.can_handle() to validate event against known\n  display names and exclude Claude Code hook data\n- Replace hardcoded \"PreToolUse\" strings in hooks.py with constant\n- Add tests for CRUSH_HOOK_EVENTS and stricter detection logic\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: extract Crush hook events constant and tighten detection (#…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-14T20:55:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5664ca16c8d8c03046e3328d69c4a2b7e205b780",
          "body": "…sh notifications (#1596)\n\n* feat: add push-based event subscriptions to daemon\n\n- Add subscribe message type to protocol and server dispatcher\n- Implement container event streaming via Docker SDK in discovery\n- Add connect_subscriber() client helper for push event consumers\n- Wire tray app to recei\n[…]\ne_dir operate on existing directories\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#650: Enhancement: Event-driven tray updates via pu…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-14T20:45:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "64ca5461383dbef4d5c905d7c05803929f17611f",
          "body": "…#1597)\n\n- Import CURSOR_HOOK_EVENTS from constants in release_helper, doctor,\n  and test helpers instead of hardcoding event lists\n- Remove redundant Doctor._get_cursor_events() static method\n- Fix doctor _count_cursor_hooks falling back to full config instead\n  of empty dict when \"hooks\" key missing\n- Update test helper to dynamically build settings from EXPECTED_EVENTS\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: use CURSOR_HOOK_EVENTS constant as single source of truth (…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-14T20:44:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8a6e0fdfbac4597dd87498cd6cfe2b07e339ae70",
          "body": "- Add crush.py hook adapter with PreToolUse event handling\n- Register crush adapter in hook_adapters __init__ and setup modules\n- Add Crush to hook simulator TUI and web interfaces\n- Document Crush support in AGENT_SUPPORT.md with capability matrix\n- Add unit tests for crush adapter detection and hook generation\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add Crush (Charmbracelet) hook adapter support (#1593)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-14T18:36:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9b2d9564dd77693d0cc7c577b60bae0221d24022",
          "body": "- Add preToolUse to Cursor hook events constant and adapter\n- Update doctor checks and hook setup to handle 6 Cursor events\n- Expand release verification flow with preToolUse test steps\n- Update tests for new event count and hook configuration\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add preToolUse hook event for Cursor IDE (#1592)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-14T16:40:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b0ebcb53f180e964439109aa2655f717c16d8e65",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: regenerate notebooklm-export.md for v1.14.0",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-13T19:59:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ecd036dc8b2158b469599cc564031848b03619dd",
          "body": "Post-release v1.14.0:\n- Bump version to 1.15.0-dev in pyproject.toml and __init__.py\n- Reset install URLs in README.md from v1.14.0 back to main\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.15.0-dev, reset README URLs to main",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-13T19:09:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "27950d3642c4d7ddb0e4064aea8ab480b9e78de3",
          "body": "v1.14.0 released — architecture refactor, no new features, no breaking changes.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge release-1.14 into main",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-13T18:42:26Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fe140b66fd3438f853220da79ef52187ace183b1",
          "body": "Prepare for v1.14.0 release:\n- Update version 1.14.0-dev → 1.14.0 in pyproject.toml and __init__.py\n- Move CHANGELOG.md Unreleased section to [1.14.0] - 2026-07-13\n- Update README.md install URLs to v1.14.0\n- Add Cursor v3.10.20 verification and CI fix to CHANGELOG\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.14.0 for release",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-13T14:30:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7f6aab65958aa768fa534f6a664d10833c61bac7",
          "body": "- Update 6 stale module paths in DEVELOPER_GUIDE.md (mcp_server, prompt_injection,\n  ssrf_protector, tool_policy, violation_logger, daemon/tray → new subpackage locations)\n- Add 10 missing subpackages to project structure tree in DEVELOPER_GUIDE.md\n- Replace removed secret_scanning.action references\n[…]\nlease-readiness.yml: add secrets: inherit to scenario-tests job call\n  so QUAY_USERNAME/QUAY_PASSWORD propagate to container build\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: update stale module paths and fix CI secrets passthrough",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-13T14:25:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "feda79cb3ed52e8408b046020931c33ccf29b773",
          "body": "* itdove/ai-guardian#1527: refactor: extract shared _block_response/_warn_response/_allow_response methods in base_agent.py — eliminate duplicated format_response branches (#1535)\n\n* refactor(hook-adapters): extract shared response builders in BaseAgentAdapter\n\n- Extract _block_response, _warn_respo\n[…]\not just PRs.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release 1.14.0 — refactor, bug fixes, CI improvements (#1567)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-12T16:42:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9a376afb00353cf6289318fb80bbb9215dec0a5d",
          "body": "- Reformat release_helper.py to comply with black code style\n- Add trailing commas to dict literals and function args\n- Collapse single-expression function calls to one line\n- Update test file formatting to match\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "style(release): format release_helper with black (#1534)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-09T08:30:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9185fcb352cb2478f69a4e45a56a533c0e05f5ad",
          "body": "- Add preferred approach to reuse existing release-x.y branch for patches\n- Update hotfix workflow with decision tree (release branch vs hotfix branch)\n- Revise branch diagrams and examples to reflect cherry-pick-based flow\n- Rename \"Hotfix Workflow\" to \"Patch / Hotfix Workflow\" throughout\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(release): prefer release branch for patch fixes (#1533)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-09T08:26:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3180b07e256d754f0596a0392980145894ba092c",
          "body": "Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: regenerate notebooklm-export.md for v1.13.3",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-09T00:44:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "496f536834eeb48b5a82b9d2438b883ff3b5d9ad",
          "body": "- Fix Cursor beforeShellExecution/afterShellExecution hooks (#1531):\n  afterShellExecution misrouted to HookEvent.PROMPT instead of POST_TOOL_USE;\n  top-level command field not extracted (Bash commands not scanned);\n  can_handle() missing shell/tool events when sent via hook_event_name\n- Add [1.13.3\n[…]\ne docs: MULTI_DAEMON_TRAY.md (stale-code indicator, rebuild hint,\n  in-progress guard), CONSOLE.md (violations directory filter)\n\nCo-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cursor): shell execution hooks silent failure + v1.13.3 changelog",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-09T00:42:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "20f713fb751d865b7f9fd9cfcecba68c859337e7",
          "body": "…esponse (#1528)\n\n- Replace `reason` with `systemMessage` in SessionStart block to avoid duplicate UI display\n- Add `additionalContext` via `_sanitize_block_reason` in `hookSpecificOutput`\n- Add `TestBaseAgentAdapterSessionStartFormat` covering block format, missing reason, additionalContext, and pass-through cases\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(session-start): use systemMessage + additionalContext for block r…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T21:50:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "eaf2647f66dbd8d7d29d93fc2a73a748c90ad3b7",
          "body": "…et warnings (#1525)\n\n- Deduplicate transcript secrets by individual rule_id instead of a single\n  fingerprint, so distinct secret types each get their own seen-key\n- Warning message now shows count and type list when _last_secret_findings\n  is available; falls back to original single-finding path when not\n- Violation log includes count and types fields alongside the error reason\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(hook_processing): per-finding dedup and count in transcript secr…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T20:33:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cafa194923ca62712cb4d28399fe8d17651f33ef",
          "body": "…#1524)\n\n- Gate restart stale-vis to local runtime only; container/k8s get separate path\n- Add _stale_vis_remote/_mk_daemon_stale_vis_remote for container and kubernetes runtimes\n- Add version-aware label showing host vs daemon version mismatch with rebuild hint\n- Add disabled menu item for remote stale warning in both single- and multi-daemon menus\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tray): show rebuild-image hint for stale container/k8s daemons (…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T20:13:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c6e5aae5e44bb51a9de8017ecd61fb6e1732d376",
          "body": "…camelCase) — adapter only checks hook_event_name (snake_case) (#1523)\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bug: SessionStart not detected when Claude Code sends hookEventName (…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T19:41:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5fb3b7355fd9c6f6cfbe59fc07696e0ec250c0c2",
          "body": "…t + bootstrap scan scenario for AGENTS.md poisoning (#1520)\n\n* feat(dummy-agent): add SessionStart event support to scenario runner\n\n- Add `_run_session_start_event` helper that writes session files to a temp dir and fires the SessionStart hook\n- Thread `daemon_state` through `_run_hook`, `_run_sce\n[…]\nerlay destination path before copying\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1517: feat: add SessionStart support to dummy-agen…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T19:04:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c7211d3d1a7c5e786a6177efe1c62d4162c46d7f",
          "body": "- Entrypoint validates config file exists after setup; exits 1 if missing\n- setup_hooks returns False on config failure regardless of other flags (ide_type, remote_config_url, etc.)\n- resolve_profile accepts bare built-in names without @ prefix (e.g. \"standard\" resolves same as \"@standard\")\n- Add tests for bare-name profile resolution and setup abort behavior\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: abort setup on config failure and accept bare profile names (#1519)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T17:24:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d8eaaf1fbfb3792134b66eeff6282850c7f525d8",
          "body": "…ctions (#1518)\n\n- Block concurrent restart triggers with `_restart_in_progress` flag\n- Refresh menu immediately on restart to reflect in-progress state\n- Poll PID file for local daemons to detect process replacement (up to 10s)\n- Fall back to fixed 3s sleep for non-local runtime targets\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tray): add in-progress guard and completion polling to restart a…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T17:19:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f8538efed7ab47821c194d7d2a8ffda7db33b764",
          "body": "…(#1516)\n\n- Update `_count_claude_hooks` to check 5 hooks instead of 3\n- Add `SessionEnd` and `PostCompact` to the hook name list\n- Update display string and threshold from 3/3 to 5/5\n- Update tests to reflect new hook count and add missing hook fixtures\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(doctor): expand hook check to include SessionEnd and PostCompact …",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T16:54:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8d28619cb3f8d662089628a38f6635206c21d045",
          "body": "- Format block response with structured header, file, reason, and remediation steps\n- Add warn action branch returning warning_message instead of error_message\n- Both messages include recommended actions and false-positive escape hatch\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(bootstrap-scan): add formatted block and warn messages (#1515)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T16:37:26Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "eda6270f4d944f54da8b8daa0e6f4d7c47e7af91",
          "body": "- Add `_is_target_stale()` helper routing local targets to `_stale_code_warned` and remote targets to `_version_mismatch_notified`\n- Add `_mk_daemon_stale_vis()` closure for per-slot stale visibility check\n- Inject \"⚠️ Running old code — click to restart\" menu item per daemon when stale and not restarting\n- Add unit tests for `_is_target_stale()` and multi-daemon stale visibility logic\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add per-daemon stale-code indicator to tray menu (#1514)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T16:26:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3eeab5269077f6cbcba789874df16b3937896d6e",
          "body": "- Add `_violation_matches_dir` helper to match violations by file path prefix\n- Add directory dropdown with type-ahead and clearable support\n- Add \"Browse...\" button wired to existing directory picker dialog\n- Populate directory options from `load_web_projects` on page load\n- Apply dir filter client-side after fetching violations\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(violations): add directory filter to violations page (#1511)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T15:48:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "761ada61a467aab9c595b30c4c6eb28f15fa6a3b",
          "body": "…1509)\n\n- BanditScanner raises BanditUnavailableError instead of silently returning no findings when bandit is not importable\n- doctor.check_bandit_scanner() added to run_all() checks; reports FAIL with reinstall hint when bandit is missing\n- Scanner checklist in AGENTS.md updated to require doctor \n[…]\n for new scanners\n- Tests updated for new BanditUnavailableError behavior and doctor check count\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: surface Bandit unavailability in scan output and doctor check (#…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T14:10:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "24cf24f318dd5dd09c1e4df669501fc5cd4fe928",
          "body": "…ode — bootstrap scanning fires on first UserPromptSubmit instead of true session start (#1508)\n\n* feat: add SessionStart as distinct hook event\n\n- Add SESSION_START to HookEvent enum, separate from PROMPT/BeforeAgent\n- Handle SessionStart in base agent adapter with block-on-secrets logic\n- Update h\n[…]\nrt into parenthesized multi-line form\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1506: limitation: no SessionStart hook in Claude C…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T14:10:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2040762c70f5a6707c6cd2edc3653c28c960ab37",
          "body": "… hook call — setup should create cache dir proactively (#1507)\n\n* fix(doctor): downgrade missing default cache dir from FAIL to WARN\n\n- Detect custom cache path via config, `AI_GUARDIAN_CACHE_DIR`, or `XDG_CACHE_HOME`\n- Return WARN (not FAIL) when default cache dir missing; FAIL only for custom pat\n[…]\neflect actual strict profile behavior\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-Authored-By: Claude <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "itdove/ai-guardian#1499: bug: doctor fails on cache path before first…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T12:43:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4c6945585187d7744cf714cc702d85e5e015167b",
          "body": "* feat: add dummy-agent scenario tests to CI/CD pipeline (#1497)\n\nWire bundled dummy-agent scenarios into GitHub Actions. Scenarios are\norganized per profile (standard, strict, minimal, moderator) so each\nprofile's expected behavior is validated independently.\n\nKey decisions:\n- Dockerfile.test write\n[…]\n in minimal. Update expectations accordingly.\n\nCo-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add dummy-agent scenario tests to CI/CD pipeline (#1502)",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-08T10:43:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "268a8a6f4073d0c88ac4c68d78ab095a63c04a78",
          "body": "…498)\n\n- Document test image build and run workflow in AGENTS.md and container/README.md\n- List bundled scenarios (basic-secret, pii-detection, ask-dialog, tool-policy)\n- Specify when to run tests (hook_processing.py, scanner, dummy-agent changes)\n- Add interactive REPL and per-scenario run commands\n\n🤖 Generated with [Claude Code](https://claude.ai/code)\n\nCo-authored-by: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add hook regression testing guide for dummy-agent container (#1…",
          "author_name": "Dominique Vernier",
          "author_login": "itdove",
          "committed_at": "2026-07-07T15:45:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ffed89e3b01b469dd74b762bd9aa62f2c42b2be8",
          "body": "Brings in container docs fix (#1495 follow-up):\n- README quick-start uses curl for run.sh, pinned v1.13.2, includes auth vars\n\nCo-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge release-1.13 into main (v1.13.2)",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-06T20:05:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4332326de85473d393427ef4e2a39db84dcb4095",
          "body": "- Bump version 1.13.1 → 1.13.2 in pyproject.toml and __init__.py\n- Add [1.13.2] CHANGELOG entry: container quick-start docs fix\n- Update install URLs and container image refs to v1.13.2\n- Update CHANGELOG comparison links\n\nCo-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.13.2 for patch release",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-06T19:45:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3d6e9e234e45349f7aa106f592935faab44ca382",
          "body": "- Use curl to download run.sh (no full repo clone needed)\n- Pin image version to v1.13.1 instead of :latest\n- Add missing ANTHROPIC_API_KEY and ACCEPT_PROPRIETARY_TOS vars\n\nCo-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): fix container quick-start examples",
          "author_name": "itdove",
          "author_login": "itdove",
          "committed_at": "2026-07-06T19:44:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 100,
      "commits_last_year": 1722,
      "latest_release_at": "2026-07-22T17:41:22Z",
      "latest_release_tag": "rc-1.16.0-dev-main.2f11f5e",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 17,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 0.1
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 71,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "ai-guardian",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "ai",
            "claude",
            "cursor",
            "gitleaks",
            "hooks",
            "secrets",
            "security",
            "Development Status :: 4 - Beta",
            "Intended Audience :: Developers",
            "License :: OSI Approved :: Apache Software License",
            "Operating System :: OS Independent",
            "Programming Language :: Python :: 3",
            "Programming Language :: Python :: 3.10",
            "Programming Language :: Python :: 3.11",
            "Programming Language :: Python :: 3.12",
            "Programming Language :: Python :: 3.13",
            "Programming Language :: Python :: 3.14",
            "Programming Language :: Python :: 3.9",
            "Topic :: Security",
            "Topic :: Software Development"
          ],
          "ecosystem": "pypi",
          "matches_repo": true,
          "registry_url": "https://pypi.org/project/ai-guardian/",
          "is_deprecated": false,
          "latest_version": "1.15.0",
          "repository_url": "https://github.com/itdove/ai-guardian",
          "versions_count": 33,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": "2026-03-24T01:42:59.545984Z",
          "latest_published_at": "2026-07-22T17:37:59.953233Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 5,
      "stars": 10,
      "watchers": 0,
      "fork_history": {
        "days": [
          {
            "date": "2026-04-14",
            "count": 1
          },
          {
            "date": "2026-05-07",
            "count": 1
          },
          {
            "date": "2026-05-28",
            "count": 1
          },
          {
            "date": "2026-05-29",
            "count": 1
          },
          {
            "date": "2026-06-06",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 5,
        "total_forks": 5
      },
      "star_history": null,
      "open_issues_and_prs": 33
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": true,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 259298,
      "source_files_sampled": 558,
      "oversized_source_files": 17,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md",
        "examples/aider/.aider.conf.yml"
      ],
      "agent_instruction_max_bytes": 70167
    },
    "dependencies": {
      "manifests": [
        "pyproject.toml"
      ],
      "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": 29,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "pypi"
      ],
      "dependencies": [
        {
          "name": "textual",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.47.0"
        },
        {
          "name": "jsonschema",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=4.0.0"
        },
        {
          "name": "requests",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=2.28.0"
        },
        {
          "name": "tomli",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=2.0.0"
        },
        {
          "name": "tomli-w",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.0.0"
        },
        {
          "name": "pyyaml",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=6.0.0"
        },
        {
          "name": "tree-sitter",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.25.0"
        },
        {
          "name": "tree-sitter-json",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.24.0"
        },
        {
          "name": "tree-sitter-python",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "tree-sitter-javascript",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "tree-sitter-typescript",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "tree-sitter-go",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "tree-sitter-rust",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "tree-sitter-java",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "tree-sitter-ruby",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "tree-sitter-c",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "tree-sitter-cpp",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "tree-sitter-bash",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.23"
        },
        {
          "name": "pystray",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.19.0"
        },
        {
          "name": "Pillow",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=9.0.0"
        },
        {
          "name": "docker",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=7.0,<9"
        },
        {
          "name": "mcp",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.10.0"
        },
        {
          "name": "rapidocr-onnxruntime",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.4.0"
        },
        {
          "name": "onnxruntime",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.15.0"
        },
        {
          "name": "nicegui",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=3.0.0"
        },
        {
          "name": "tokenizers",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=0.15.0"
        },
        {
          "name": "boto3",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.28.0"
        },
        {
          "name": "bandit",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.7.0"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "bandit",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "boto3",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "docker",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "jsonschema",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "mcp",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "nicegui",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "onnxruntime",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pillow",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pystray",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pyyaml",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "requests",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "textual",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tokenizers",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tomli-w",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-bash",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-c",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-cpp",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-go",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-java",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-javascript",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-json",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-python",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-ruby",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-rust",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "tree-sitter-typescript",
            "direct": true,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pygobject",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pytest",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          },
          {
            "name": "pytest-asyncio",
            "direct": false,
            "version": null,
            "ecosystem": "pypi"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 29,
        "direct_count": 26,
        "indirect_count": 3
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 811,
        "open_issues": 33,
        "closed_ratio": 0.963,
        "closed_issues": 865,
        "closed_unmerged_prs": 2
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "itdove",
          "commits": 1723,
          "avatar_url": "https://avatars.githubusercontent.com/u/28610057?v=4"
        },
        {
          "type": "User",
          "login": "shanemcd",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/773186?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.998
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "build-container.yml",
        "build-wheel.yml",
        "integration-tests.yml",
        "lint.yml",
        "parser-compat.yml",
        "pattern-research-reminder.yml",
        "publish.yml",
        "release-readiness.yml",
        "scenario-tests.yml",
        "smoke-tests.yml",
        "tag-monitor.yml",
        "test.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": true
    },
    "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": 6,
            "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": "26 out of 26 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": 6,
            "reason": "project has 2 contributing companies or organizations -- score normalized to 6",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 9,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 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": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "2f11f5ed6f722e95a2f1618c918bff5049334bda",
        "ran_at": "2026-07-22T19:07:43Z",
        "aggregate_score": 5.3,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-22T17:51:25Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-22T16:41:45Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 77,
          "created_at": "2026-04-16T00:54:34Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 251,
          "created_at": "2026-04-25T14:03:00Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 265,
          "created_at": "2026-04-26T18:39:05Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 266,
          "created_at": "2026-04-26T18:39:57Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 267,
          "created_at": "2026-04-26T18:40:40Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 268,
          "created_at": "2026-04-26T18:41:23Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 269,
          "created_at": "2026-04-26T18:42:01Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 270,
          "created_at": "2026-04-26T18:42:50Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 331,
          "created_at": "2026-04-30T20:52:07Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 334,
          "created_at": "2026-04-30T23:59:44Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 437,
          "created_at": "2026-05-04T18:17:02Z",
          "last_comment_at": "2026-05-07T17:03:40Z",
          "last_comment_author": "itdove"
        },
        {
          "number": 438,
          "created_at": "2026-05-04T18:20:29Z",
          "last_comment_at": "2026-05-07T17:03:41Z",
          "last_comment_author": "itdove"
        },
        {
          "number": 453,
          "created_at": "2026-05-06T13:28:08Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 470,
          "created_at": "2026-05-07T13:15:37Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 472,
          "created_at": "2026-05-07T13:20:03Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 473,
          "created_at": "2026-05-07T13:20:04Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 540,
          "created_at": "2026-05-12T03:37:15Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 551,
          "created_at": "2026-05-12T20:49:24Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 609,
          "created_at": "2026-05-15T16:11:52Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 616,
          "created_at": "2026-05-15T19:08:01Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/itdove/ai-guardian",
    "host": "github.com",
    "name": "ai-guardian",
    "owner": "itdove"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 64,
      "inputs": {
        "security": 53,
        "vitality": 82,
        "community": 41,
        "governance": 59,
        "engineering": 82
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 82,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 76,
            "inputs": {
              "commits_last_year": 1722,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 17
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "17/52 weeks with commits",
                "points": 11.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 17
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "1722 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1722
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 100,
              "latest_release_tag": "rc-1.16.0-dev-main.2f11f5e",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 0.1
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "100 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~0.1 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0.1
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 41,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "forks": 5,
              "stars": 10,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "10 stars",
                "points": 15.5,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 10
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "5 forks",
                "points": 5,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 64,
            "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": "license file present, not a recognized license",
                "points": 16.9,
                "status": "partial",
                "details": [
                  {
                    "code": "license_custom",
                    "params": {}
                  }
                ],
                "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
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 59,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 18,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.998
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "2 contributors",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 2 contributing companies or organizations -- score normalized to 6",
                "points": 6,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 83,
            "inputs": {
              "merged_prs": 811,
              "open_issues": 33,
              "closed_issues": 865,
              "issue_closed_ratio": 0.963,
              "closed_unmerged_prs": 2
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "96% of issues closed",
                "points": 45,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 96
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "811/813 decided PRs merged",
                "points": 38.2,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 811,
                      "decided": 813
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 51,
            "inputs": {
              "followers": 6,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "itdove",
              "public_repos": 77,
              "account_age_days": 3359
            },
            "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": "6 followers of itdove",
                "points": 6.1,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 6,
                      "login": "itdove"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "77 public repos, account ~9 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 77
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 9
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "ai-guardian"
              ],
              "ecosystems": "pypi",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on pypi",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "pypi"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 0 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "33 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 33
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 82,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "excellent",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 94,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": true
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "12 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 12
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 16,
                "status": "met",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 9.6,
                "status": "met",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "26 out of 26 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 53,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": null,
            "notes": [],
            "value": 53,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 18,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 0,
              "scorecard_aggregate": 5.3
            },
            "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": 4.5,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "26 out of 26 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 2 contributing companies or organizations -- score normalized to 6",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "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": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 73,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.99,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md",
                "examples/aider/.aider.conf.yml"
              ],
              "agent_instruction_max_bytes": 70167
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md, examples/aider/.aider.conf.yml",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md, examples/aider/.aider.conf.yml"
                    }
                  }
                ],
                "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": "99 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 99,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 76,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": true,
              "typed_language": false,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0.99,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 11,
                "status": "met",
                "details": [],
                "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": "Dockerfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "99 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 99,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "dependency automation configured, none observed in the sampled commits",
                "points": 5,
                "status": "partial",
                "details": [
                  {
                    "code": "dependency_bot_config_only",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "moderate",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 53,
            "inputs": {
              "primary_language": "Python",
              "largest_source_bytes": 259298,
              "source_files_sampled": 558,
              "oversized_source_files": 17
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Python without a type-check config",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_typecheck_config_language",
                    "params": {
                      "language": "Python"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "17/558 source files over 60KB",
                "points": 53.3,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 558,
                      "oversized": 17
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "moderate",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "deps.dev does not index pypi:ai-guardian@1.15.0; advisories assessed against the repository dependency graph instead",
    "No resolved dependencies carried a version and a supported ecosystem"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-22T19:08:03.664262Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/i/itdove/ai-guardian.svg",
  "full_name": "itdove/ai-guardian",
  "license_state": "custom",
  "license_spdx": null
}

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

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

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