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

Curviate / curviate-cli

Official CLI for the Curviate API

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

Curviate/curviate-cli має індекс здоров’я 42 зі 100, що відповідає смузі «У зоні ризику». Найвищий показник — Vitality (75/100), найнижчий — Security (22/100). Останнє оновлення було 5 днів тому. Більшість нещодавньої роботи виконує один учасник.

42
загалом / 100
У зоні ризику

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

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

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

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

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

Власність

CurviateОрганізація
0 підписників3 публічні репозиторіїз черв. 2026 р.

За цим репозиторієм стоїть організація — спільна, підзвітна опіка, здатна пережити будь-якого окремого мейнтейнера.

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

РеєстрПакетВерсіяЗавантажень / місВерсіїОстання публікація
npm@curviate/cliвказує на інший репозиторій — не оцінюється0.18.13 853255 днів тому

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

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

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

75Добрий · 22% загального індексу
Як обчислюється оцінка
36/36Свіжість push — останній push 5 дн. тому
3.5/36Ритм комітів — 5/52 тижнів із комітами
18/18Обсяг комітів — 171 комітів за останній рік
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Використані вхідні дані
commits_last_year171
human_commit_share1
days_since_last_push5
active_weeks_last_year5
Як обчислюється оцінка
27/27Випускає релізи — опубліковано 13 релізів
36/36Свіжість релізів — останній реліз 6 дн. тому
27/27Ритм релізів — реліз кожні ~1,5 дн.
0/10OpenSSF Scorecard: Signed-Releases — немає даних
Використані вхідні дані
releases_count13
latest_release_tagcli-v0.17.0
releases_from_tagsні
days_since_latest_release6
mean_days_between_releases1,5
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: Signed-Releases. Залишкові ваги перенормовано.

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

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

24Критичний · 18% загального індексу
Як обчислюється оцінка
0/60Зірки — 0 зірок
0/25Форки — 0 форків
0/15Спостерігачі — 0 спостерігачів
Використані вхідні дані
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Як обчислюється оцінка
22.5/22.5README
22.5/22.5Ліцензія — визнана ліцензія (MIT)
0/18Настанови CONTRIBUTING
0/13.5Кодекс поведінки
0/7.2Шаблон issue
0/6.3Шаблон PR
Використані вхідні дані
has_readmeтак
has_licenseтак
has_contributingні
has_issue_templateні
has_code_of_conductні
has_pull_request_templateні

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

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

38У зоні ризику · 24% загального індексу
Як обчислюється оцінка
9/54Бас-фактор — на 1 контриб’ютор(ів) припадає половина всіх комітів
1.6/22.5Розподіл комітів — головний контриб’ютор — автор 93% комітів
2.7/13.5Широта контриб’юторів — 2 контриб’юторів
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Використані вхідні дані
bus_factor1
contributors_sampled2
top_contributor_share0,93
Як обчислюється оцінка
0/46.8Вирішення issue — немає issue або даних
38.2/38.3Прийняття PR — злито 13/13 вирішених PR
0/15OpenSSF Scorecard: Code-Review — Found 0/11 approved changesets -- score normalized to 0
Використані вхідні дані
merged_prs13
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
Виключено з оцінювання (немає даних або не застосовно): Вирішення issue. Залишкові ваги перенормовано.

Власність та опіка

35У зоні ризику
Як обчислюється оцінка
30/30Підтримка власника — у власності організації
0/20Верифікований домен
0/25Охоплення власника — 0 підписників у Curviate
4.6/25Послужний список — 3 публічних репозиторіїв, вік облікового запису ~0 р.
Використані вхідні дані
followers0
owner_typeOrganization
is_verified
owner_loginCurviate
public_repos3
account_age_days32

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

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

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

Інженерні практики

40У зоні ризику
Як обчислюється оцінка
0/24Процеси CI
24/24Наявні тести
16/16Конфігурація лінтера — eslint.config.mjs
0/9.6Pre-commit-хуки
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — 0 out of 5 merged PRs checked by a CI test -- score normalized to 0
Використані вхідні дані
has_ciні
has_testsтак
has_editorconfigні
has_linter_configтак
has_precommit_configні

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

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

Безпека

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

22Критичний · 16% загального індексу

Стан безпеки

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

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

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

60Помірний · 0% загального індексу
Як обчислюється оцінка
0/45Інструкції для агентів — немає CLAUDE.md / AGENTS.md / правил редактора
0/15Машиночитана документація (llms.txt)
40/40Читабельна історія комітів — намір зазначено у 100 з 100 людських комітів (структурований заголовок або пояснювальний текст)
Використані вхідні дані
has_llms_txtні
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
Як обчислюється оцінка
0/18Розгортання однією командою
22/22Автоматизовані тести
11/11Конфігурація лінтера / форматера — eslint.config.mjs
11/11Статична перевірка типів — tsconfig.json
10/10Відтворюване середовище — lockfile
0/10Підтверджена практика роботи з агентами — серед останніх 100 комітів немає створених агентом
0/8Автоматизоване супроводження — автоматичних оновлень залежностей не виявлено
0/10OpenSSF Scorecard: Pinned-Dependencies — немає даних
Використані вхідні дані
has_nixні
has_testsтак
lockfilespnpm-lock.yaml
has_dockerfileні
typed_languageтак
bootstrap_files
has_devcontainerні
has_linter_configтак
typecheck_configstsconfig.json
agent_commit_share0
toolchain_manifests
dependency_bot_commit_share0
Виключено з оцінювання (немає даних або не застосовно): OpenSSF Scorecard: Pinned-Dependencies. Залишкові ваги перенормовано.
Як обчислюється оцінка
45/45Типізований код — TypeScript (статично типізована)
53.1/55Керовані розміри файлів — 4/117 файлів вихідного коду понад 60 КБ
Використані вхідні дані
primary_languageTypeScript
largest_source_bytes90 875
source_files_sampled117
oversized_source_files4

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

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

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

  • npm package '@curviate/cli' points at a different repository (https://github.com/curviate/cli); excluded from ecosystem scoring
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository
  • deps.dev does not index npm:@curviate/cli@0.18.1; advisories assessed against the repository dependency graph instead

Докладніше

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

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
0CI-Tests0 out of 5 merged PRs checked by a CI test -- score normalized to 0
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/11 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
н/дDangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
н/дPackagingpackaging workflow not detected
н/дPinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
н/дSigned-Releasesno releases found
н/дToken-PermissionsNo tokens found
7Vulnerabilities3 existing vulnerabilities detected
Прямі залежності 3
РеєстрПакетОбмеження версіїМаніфест
npm@curviate/sdk^0.18.1package.json
npmcitty^0.1.6package.json
npmopen^10.1.0package.json
Усі залежності не зібрано

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

Звіт у форматі JSON машиночитний
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 1087,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "JavaScript": 17234,
        "TypeScript": 1662610
      },
      "pushed_at": "2026-07-18T15:13:57Z",
      "created_at": "2026-06-21T16:13:30Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-18T15:14:07Z",
      "description": "Official CLI for the Curviate API",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript"
      ]
    },
    "owner": {
      "blog": null,
      "name": null,
      "type": "Organization",
      "login": "Curviate",
      "company": null,
      "location": null,
      "followers": 0,
      "avatar_url": "https://avatars.githubusercontent.com/u/295625820?v=4",
      "created_at": "2026-06-21T16:02:17Z",
      "is_verified": null,
      "public_repos": 3,
      "account_age_days": 32
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "cli-v0.17.0",
          "kind": "other",
          "published_at": "2026-07-17T16:49:17Z"
        },
        {
          "tag": "cli-v0.16.0",
          "kind": "other",
          "published_at": "2026-07-17T09:16:29Z"
        },
        {
          "tag": "cli-v0.15.2",
          "kind": "other",
          "published_at": "2026-07-12T08:29:26Z"
        },
        {
          "tag": "v0.15.1",
          "kind": "patch",
          "published_at": "2026-07-11T19:52:37Z"
        },
        {
          "tag": "v0.15.0",
          "kind": "minor",
          "published_at": "2026-07-11T11:03:42Z"
        },
        {
          "tag": "v0.14.0",
          "kind": "minor",
          "published_at": "2026-07-07T02:58:12Z"
        },
        {
          "tag": "v0.13.0",
          "kind": "minor",
          "published_at": "2026-07-06T15:02:09Z"
        },
        {
          "tag": "cli-v0.12.0",
          "kind": "other",
          "published_at": "2026-07-05T06:10:23Z"
        },
        {
          "tag": "cli-v0.11.0",
          "kind": "other",
          "published_at": "2026-07-04T18:53:51Z"
        },
        {
          "tag": "cli-v0.10.0",
          "kind": "other",
          "published_at": "2026-07-03T20:09:37Z"
        },
        {
          "tag": "cli-v0.4.1",
          "kind": "other",
          "published_at": "2026-06-29T12:34:25Z"
        },
        {
          "tag": "cli-v0.3.0",
          "kind": "other",
          "published_at": "2026-06-28T17:28:48Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-06-22T18:40:08Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "761ea169b86234d3ee9103dc548e7235263fd127",
          "body": null,
          "is_bot": false,
          "headline": "chore: update repo URLs after rename",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-18T15:13:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7704aeabd0398e9f0642a558433046c644abbb04",
          "body": "…rom registry)",
          "is_bot": false,
          "headline": "chore(release): @curviate/cli 0.18.1 (resolve @curviate/sdk ^0.18.1 f…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-18T10:11:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e6c8e0118f0c399e3a086df132476d4efa59c716",
          "body": "… identifier (#13)\n\nCascade the company-reply hard cutover: the endpoint now accepts the normal\n2-… chat id from `company chats` and resolves the page mailbox internally\nfrom the company identifier, so the COMPANY_ chat-id requirement is gone.\n\n- reply header/JSDoc/subcommand-description + <chat_id>\n[…]\nd is accepted; the stale guiding-COMPANY_-400 assertion is\n  replaced by a plain malformed-id 400 (verbatim passthrough, no client\n  pre-check).\n\nCo-authored-by: Raphael Redmer <ra.redmer@outlook.com>",
          "is_bot": false,
          "headline": "fix(company): reply takes the normal 2-… chat id, preview notice from…",
          "author_name": "Raphael",
          "author_login": "rapha-red",
          "committed_at": "2026-07-18T09:57:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ceeda40df228b0e7f5e2de2a6d9bebf33f528b70",
          "body": "…rom registry)",
          "is_bot": false,
          "headline": "chore(release): @curviate/cli 0.18.0 (resolve @curviate/sdk ^0.18.0 f…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-17T21:21:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2ea51a21641943603c85828fdb7be6786cc1ecc1",
          "body": "curviate company reply <id> <chat_id> \"<text>\" [--attach <file>...] [--preview]\ncalls companies.sendMessage(identifier, chatId, body). <id> resolves via the\nexisting company sub-resource resolver (URL/slug/numeric); <chat_id> passes\nthrough verbatim (it must be a COMPANY_ id, the API returns the gui\n[…]\n_SDK_METHOD_COUNT 144 -> 145).\n\nDev-only link:../sdk dependency (mirrors the prior follow-invite work) so\ntypecheck/tests resolve companies.sendMessage, which is not on the last\npublished npm version.",
          "is_bot": false,
          "headline": "feat(companies): add reply command (reply as the company page)",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-17T19:18:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "62680a8351de21f0592da066ebf62c093a405e88",
          "body": "company follow-invite + invitable-followers, release 0.17.0",
          "is_bot": false,
          "headline": "Merge pull request #12 from Curviate/feat/company-follow-invite",
          "author_name": "Raphael",
          "author_login": "rapha-red",
          "committed_at": "2026-07-17T16:48:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7c3df9cfd0fe771f7557973004d665234d4c88bc",
          "body": "…7.0 publish",
          "is_bot": false,
          "headline": "chore(release): resolve @curviate/sdk from registry (^0.17.0) for 0.1…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-17T16:47:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a24c2906d76bee7d4599435fbd133a0f8d16dc89",
          "body": "…econciled SDK/API contract)",
          "is_bot": false,
          "headline": "fix(company): describe follow-invite as all-or-nothing (matches the r…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-17T16:47:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4c0403031fd22fedd6331234b263f89ca147ec78",
          "body": "…ec api/028 FR-004)\n\nExtend the `company` command with two subcommands:\n\n- `company follow-invite <id> --invitee <AC…> [--invitee <AC…> ...]`\n  (write, admin-gated, --preview accepted). Invites the connected\n  account's 1st-degree connections to follow an administered company\n  page via companies.fo\n[…]\novering both\ncommands (repeatable --invitee, preview-resolves-id-first, base64\ninvite_token safety in every output mode, slug/numeric id resolution,\n403 admin-gate mapping, min-1-invitee usage error).",
          "is_bot": false,
          "headline": "feat(companies): add follow-invite + invitable-followers commands (sp…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-17T12:57:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d3225388dd88dac736a2e8b28dbb101c07101546",
          "body": "…6.0 publish",
          "is_bot": false,
          "headline": "chore(release): resolve @curviate/sdk from registry (^0.16.0) for 0.1…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-17T09:15:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a3b37f1f15d53032864f4b79377d5fcdc0df549b",
          "body": "feat: inboxes command group; SDK 0.16 alignment (0.16.0)",
          "is_bot": false,
          "headline": "Merge pull request #11 from Curviate/feat/company-scope-surface",
          "author_name": "Raphael",
          "author_login": "rapha-red",
          "committed_at": "2026-07-17T09:09:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a9e5a771a973a401b8a290ddcd591ad15f293d3a",
          "body": "Founder follow-up: the company-behalf send must be first-class on the SEND\ncommand's own --help, not only on the inboxes command that discovers a\nCOMPANY_ chat id.\n\n- `message send`'s description now states plainly: a COMPANY_ chat id (from\n  `inboxes chats`) sends as that company page, no separate \n[…]\nmessage`'s own top-level description gained the same one-line pointer.\n\nNo behavior change, --help text only. Verified against the built binary.\n\ntypecheck/lint/test(1381)/build/check:clean all green.",
          "is_bot": false,
          "headline": "docs: document company-behalf send on message send --help itself",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-17T08:30:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8af99faebe9f48c13bb477efaf4e190a2d7c702b",
          "body": "…imit range)\n\nThree AX findings from qa dogfooding the 0.16 inboxes/reply-as-page surface,\naddressed without any breaking change:\n\n- message send now names the acting identity in its default output, not\n  only --verbose --json. When the response's sent_as.kind is \"company\", a\n  stderr notice prints \n[…]\nho x2),\ninbox.test.ts (limit range x3 across list/messages), inboxes.test.ts\n(limit range x2). Verified end-to-end against the built binary too.\n\ntypecheck/lint/test(1381)/build/check:clean all green.",
          "is_bot": false,
          "headline": "feat(ax): P1 polish on reply-as-page (sent_as notice, preview echo, l…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-17T07:58:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e4132dace8fb7e840b1a2455a0637d993d202c0a",
          "body": "…EQUIRED exit codes (0.16.0)\n\nNew `inboxes` command group (Beta), wrapping the SDK's new account-scoped\n`inboxes` namespace:\n  - `inboxes list [--kind personal|company] [--company-id <id>]` — discovers\n    the account's personal inbox plus, when the company product is attached,\n    one entry per com\n[…]\nctly fails either way — widened the regex to\n    accept both codes rather than assert a specific compiler internal.\n\ntypecheck/lint/test(1369)/build/check:clean/check:clean:dist/verify:dist\nall green.",
          "is_bot": false,
          "headline": "feat(inboxes): add `inboxes` command group; PREMIUM_CONFLICT/REAUTH_R…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-16T23:19:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e5d78a60d261e335e2ec1933f21bb049d085873c",
          "body": "check:clean previously scanned files by extension only, which silently\nskipped extensionless dotfiles like .gitignore. Extend the scanner to\nalso match a fixed dotfile allowlist so a leaked internal reference in\none of these files gets caught going forward. This repo's .gitignore\nwas already clean; this is preventive hardening matching the SDK's fix.",
          "is_bot": false,
          "headline": "chore(hygiene): scan dotfiles in check-clean",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-13T11:08:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "031f61d7abe7d6cacfd601aa261676113f8e4645",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): CHANGELOG + version bump to 0.15.2",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-12T08:20:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7be66c8ba9022e777dcfdb084d35365bb30c8595",
          "body": "The tier-1b interactive-TTY stdin cue printed twice on a real\nterminal: credential-resolve.ts writes STDIN_TTY_CUE to out.stderr\nbefore invoking the reader, but both production defaults (this\nmodule's own defaultReadSingleLine, and account.ts's\nresolveCredentialIO default) passed the cue text straig\n[…]\nt — which readlineSync itself writes to\nstderr, rendering it a second time.\n\nBoth defaults now pass an empty prompt to readlineSync instead; the\ninjected out.stderr write stays the single visible cue.",
          "is_bot": false,
          "headline": "fix(readline): single cue on the tier-1b TTY stdin read",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-12T08:20:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "139972dbeb4604ef32a63203ce6b8dc1e2761c94",
          "body": "--auth-method credentials --password-stdin on a TTY with no --email\nsilently suppressed the read: the credentials password call reused\nits email-inclusive allowInteractive for BOTH the tier-1b stdin read\nand the tier-3/4 masked-prompt/fail-fast gate, so no-email skipped the\nstdin read too even thoug\n[…]\nreader fires whenever the run isn't a preview,\n--email or not. An email-less resulting body still fails downstream\nvalidation as expected — this only stops the read itself from being\nsilently dropped.",
          "is_bot": false,
          "headline": "fix(account): tier-1b TTY stdin read gated by preview only",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-12T08:20:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1eef17f024723b7ee4d94ce5b55d2f74583acf28",
          "body": "The raw-mode onData handler equality-checked the WHOLE incoming chunk\nagainst \"\\r\"/\"\\n\" — one character per data event was assumed, but a\nlive terminal (paste with a trailing newline, or an Enter coalesced\ninto the paste over SSH) can deliver the terminator inside a\nmulti-byte chunk, which the whole\n[…]\neal stdin can't be scripted to emit arbitrary chunk boundaries\nin-process — the regression-anchor suite drives a fake TTY stream\nthrough it, RED against the unmodified handler and GREEN after the\nfix.",
          "is_bot": false,
          "headline": "fix(readline): chunk-safe terminator scan in raw-mode onData",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-12T08:20:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3db418755a08948531c58a3d9d168c51096e6881",
          "body": "…ution\n\nDrives the fix through account link end-to-end: typed-value resolution\nfor both credential secrets, the stderr cue with the secret never\nappearing in it, the piped/env paths staying untouched, the empty-line\nfallthrough obeying the full precedence order (env before prompt/\nfail-fast, not a shortcut), and --preview suppressing the read entirely\n(no cue, no block, no reader call) while leaving the piped --preview\ncase unaffected.\n\nPart of #392",
          "is_bot": false,
          "headline": "test(account): command-level coverage for interactive-TTY stdin resol…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-12T08:20:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7c1f57d7d03090feeb15712150ee2d66e4e61aca",
          "body": "--password-stdin/--li-at-stdin used to always await stdin to EOF, which\nnever arrives on a live terminal (only Ctrl-D sends it) — pasting a\nsecret and pressing Enter hung forever and, worse, could echo. Add a\ntop-level isTTY signal plus a dedicated single-line-reader seam on the\ncredential resolver:\n[…]\nt test races the resolver against a short timer\nwith the identical stub pair against both old and new behavior — RED\n(times out) against the prior implementation, GREEN against this one.\n\nPart of #392",
          "is_bot": false,
          "headline": "fix(account): route interactive-TTY --*-stdin reads off the EOF reader",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-12T08:20:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "752a58f478ef1adb3350aeac5a13b161046828fa",
          "body": "Documents the AX/DX batch: successor hints, --all NDJSON notice + --page-delay\npacing, job list --state ALL, --fields unknown-field warning, reaction-signature\nunification (back-compatible), constraint + list-lag help notes, and the\nprofile endorse handle-resolution fix. Patch release, no breaking changes.",
          "is_bot": false,
          "headline": "chore(release): CHANGELOG + version bump to 0.15.1",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T19:09:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "38f85da6a31bf03ff23a585a9e268d0dc23e2eaf",
          "body": "post user-posts, comment list, inbox messages, and connect sent/received help\nnow note that a very recent create/delete may take a few minutes to appear or\nclear (LinkedIn-side indexing), and that a direct get reflects a change\nimmediately. Prevents an agent re-deleting or misreporting on the propagation\nwindow. Help-text only.",
          "is_bot": false,
          "headline": "docs(cli): note list-lag on mutation-adjacent list reads",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T19:08:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bd2a8edbd5fc931a945a809e1691993319165e9d",
          "body": "Item 8 — `job list --state ALL`: a best-effort client-side union over every\nenum state. Each state is queried, re-filtered against its own state (LinkedIn's\nfilter is best-effort), then merged and de-duplicated by id. A modest pause\nseparates the per-state fetches; --all streams the union as NDJSON,\n[…]\nhe server-enforced 200-character minimum explicitly, and --budget-amount notes\nit must be a non-negative number. (The served OpenAPI snapshot carries no other\nminLength/maxLength on CLI-wired bodies.)",
          "is_bot": false,
          "headline": "feat(job): --state ALL client-side union + constraint discoverability",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T19:06:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0e3c812181a1b3d5f5ebc35292674573f6df80a1",
          "body": "The endorse write path accepts only the member provider id — a public slug or\nURL 404s upstream (the same class already handled for follow/unfollow, D6). The\nCLI was passing the raw handle straight through, so `profile endorse <slug>\n--endorsement-id N` 404'd while the identical call with the provid\n[…]\n identifier via the shared\nmember-id resolver (a contact-safe users.get READ that runs even under\n--preview and passes a provider-id input straight through). Help + docstring\nnote the auto-resolution.",
          "is_bot": false,
          "headline": "fix(profile): resolve slug/URL to provider id on `profile endorse`",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T18:57:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1a00652c7a176d89d5a79a26465a1dffcbe10f31",
          "body": "Projecting a field that does not exist on the first item (observed live:\n--fields id,full_name on relations, whose keys are member_id/first_name)\nyielded {} with no hint. renderSuccess now emits one stderr warning naming the\nunmatched fields and listing the available keys. The data channel is unchan\n[…]\nck runs against the slim output the\nprojection actually sees. Only the unknown subset is reported; a dot-path whose\ntop-level key exists is not flagged; empty lists and no-projection cases are\nsilent.",
          "is_bot": false,
          "headline": "feat(output): warn when --fields matches nothing on the response",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T18:54:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c9323bcf01407e219e87a3e9ec20e665bf3a7ef3",
          "body": null,
          "is_bot": false,
          "headline": "chore(test): drop unused Mock import in reaction-unification test",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T18:52:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "27cbc2edb6b0346ef2e74d6bc39a35b95cf15ab3",
          "body": "post react <post_id> <reaction> and message react <chat_id> <message_id> <emoji>\nnow take the reaction/emoji as a positional (matching comment react/unreact and\npost unreact). The old --reaction / --emoji flags are kept as documented-\ndeprecated aliases (no breaking removal in a patch): a distinct a\n[…]\na fallback behind the positional.\nA missing value is now a usage error (exit 2) rather than a silent empty body.\n\nProven end-to-end through the built bin: both forms render the identical\npreview body.",
          "is_bot": false,
          "headline": "feat(react): unify reaction commands on the positional form",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T18:52:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "07ccff33d8c27ce9a7f5b5732eb295f62605c51b",
          "body": "Item 2 — NDJSON discoverability: when --all streaming engages, streamAll writes\na one-line stderr notice (\"--all streams NDJSON: one object per line; the\n{items,cursor} envelope is not used\") once per invocation, before any item.\nAgents that pattern-match the plain-mode envelope were mis-parsing the\n[…]\nms>\noverrides it (0 disables). Threaded into all 47 --all call sites via\npageDelayFromFlags; a source-scan gate test keeps every call site honest.\nInjectable sleep keeps the pacing unit tests instant.",
          "is_bot": false,
          "headline": "feat(paginate): --all NDJSON-mode notice + default inter-page pacing",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T18:48:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6fa8daf5cc17e85fcf1c6539118885456a23ac96",
          "body": "Removed/renamed commands (post list, connect respond, profile connections,\naccount reconnect*, inbox sync*, recruiter add-candidate/sync, sales-nav sync,\nwebhook state-diff, company followers, …) now emit a one-line \"did you mean\"\nsuccessor hint at the dispatcher's unknown-command path instead of a \n[…]\nallowed as a bare id, for connect/profile/company). Exit stays 2.\n\nKeyed by a small <group> -> <token> -> hint map; a current subcommand always\nwins first, so the map only ever fires on a stale token.",
          "is_bot": false,
          "headline": "feat(dispatch): successor hints for removed/renamed 0.15.0 commands",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T18:37:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42fed070c2ef384df3a3e163f2afc0c400062541",
          "body": null,
          "is_bot": false,
          "headline": "chore(deps): resolve @curviate/sdk from the published 0.15.0",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T11:01:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b20a213b5b2add1fa8c6788770356aa5213d1018",
          "body": "The hint pointed to 'profile me' organizations as the org-id source, but\nthat field was removed from profile me's output (D14) — the real user\nprofile has no administered-organizations field. Reworded to a\nself-contained description of what the flag forwards: a numeric id or URN\nfor an organization/company page the account administers.\n\nNot a functional change — --as-organization still maps to the react_as\nbody field verbatim.",
          "is_bot": false,
          "headline": "fix(post): reword stale --as-organization help hint",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T10:30:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bce73f895dc84844a3e3bfa936562492d0e6aab0",
          "body": "…cription\n\nD14 dropped headline from `profile me`/`profile <id>` slim output, assuming\nno v2 source existed. Live evidence says otherwise: on a v2 read, LinkedIn\nserves the profile headline in the `description` wire field, not a field\nliterally named `headline` — a separate `bio` field carries the\nA\n[…]\n in `description` (About text in\n`bio`) across live profiles.\n\nslimProfileMe now returns 9 fields (was 8), slimProfile 8 (was 7). occupation\nand organizations remain removed — neither has a v2 source.",
          "is_bot": false,
          "headline": "fix(profile): restore headline in slim projections — sourced from des…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T10:29:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d6971bcf9eaf768a8ba8b5f1bfd869d78cff563a",
          "body": "…types miss\n\nLive verification (staging, company microsoft --verbose) showed area\n(region/state, e.g. \"Washington\") is genuinely populated on ~29% of\nreal locations[] entries, including the HQ entry itself — the SDK's\ngenerated .d.ts doesn't declare it for this endpoint, but it was never\nfictitious. It was already part of the pre-fix output; only its\nsibling country/country_code needed correcting. Restoring it avoids\ndropping working data on the strength of an incomplete generated type.",
          "is_bot": false,
          "headline": "fix(slim): restore area in company headquarters — real field the SDK …",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T10:12:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1e9a922d2cfdab62b57e292a5d58eee75965c3e0",
          "body": "…real v2 shape\n\nBoth commands are backed by the identical v2 user-profile response.\nprovider_id now sources from the real id field (no top-level\nprovider_id exists); network_distance and is_premium now source from\nspecifics.network_distance/specifics.is_premium (nested, not\ntop-level); current_posit\n[…]\nience exists, so it\nwas permanently null). profile me's email is renamed emails (the real\nfield is a plural array). headline, occupation, and organizations are\nremoved outright — none has a v2 source.",
          "is_bot": false,
          "headline": "fix(slim): rebuild profile me / profile <id> slim projections to the …",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T10:03:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bc034e43019fda7a1c95301669d90ef0745c337a",
          "body": "employee_count/employee_count_range now source from insights.headcount/\ninsights.headcount_range.from (was reading nonexistent top-level keys,\nalways null); foundation_date is renamed establishment_year (a bare\nyear, not a date string); followers_count is renamed follower_count\n(the real key is singular); messaging is removed outright (no such\nfield on the real schema). headquarters synthesis now reads the real\ncountry_code/postal_code location keys instead of the fictitious\ncountry/area.",
          "is_bot": false,
          "headline": "fix(slim): rebuild company <id> slim projection to the real v2 shape",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T09:59:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "afd0f09fa6d1831feaa1590d8790808227348bd2",
          "body": "…state\n\nLinkedIn's upstream state filter on GET /v1/{account_id}/jobs is\nbest-effort: OPEN commonly returns the same postings as DRAFT, and no\nquery is guaranteed to return an item whose own state is LISTED even\nthough LISTED is a valid value of that field (per the SDK's documented\ncontract on this \n[…]\nith a test asserting the second page's request still\ncarries the first page's cursor even when page 1 had a filtered item.\nThe --state help text now documents the best-effort nature and the\nre-filter.",
          "is_bot": false,
          "headline": "fix(job): D10 -- job list --state re-filters items against their own …",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T09:37:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4f08065645e1c98be79c6309f301cafc097e8d94",
          "body": "…v1-shaped\n\ncompany posts and search posts share one v2 item schema ({id, share_url,\ntext, author, reaction_count, comment_count, repost_count, is_repost,\nattachments, reactions, permissions}) but the slim projector emitted\npost_urn (never a real key) and posted_at (no timestamp field exists on\nthis\n[…]\nons, post reactions, job applicants, webhook list,\nrecruiter listApplicants/project-job get, sales-nav) all confirmed OK --\neither real key names or no CLI-side projection to drift in the first\nplace.",
          "is_bot": false,
          "headline": "fix(slim): D13 -- company/search posts and job slim projections were …",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T09:29:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ccb5cae2e7dce0ac4e0b6df4b0761b11792de5fa",
          "body": "Both were unmapped in EXIT_CODE_MAP because the old SDK ErrorCode union\nlacked them entirely. RATE_LIMITED -> 6 (rate-limited, alongside\nRATE_LIMIT_ACCOUNT/RATE_LIMIT_TENANT/PLATFORM_RATE_LIMIT/LINKEDIN_RATE_LIMITED).\nCONNECTION_REQUEST_CONFLICT -> 8 (account/connection state, alongside\nACCOUNT_ALRE\n[…]\nSDK's public export surface (only\nthe ErrorCode type is exported, not a runtime array), so the CLI's\nALL_ERROR_CODES test list stays intentionally hand-copied -- documented\ninline rather than derived.",
          "is_bot": false,
          "headline": "feat(exit-codes): map RATE_LIMITED and CONNECTION_REQUEST_CONFLICT",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T09:09:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "33cd17e5465cc54cda99406af744166b1ce72c92",
          "body": "connect/profile/message/search each declare a bare positional\n(<id>/<id>/<chat_id>/<url>) as `required: false` so their own run()\ncan print a richer, subcommand-listing usage block than citty's\ngeneric one-liner — but all four forgot to actually exit non-zero\nafter printing it, silently falling thro\n[…]\na\nbare invocation showing the group's menu at exit 0 is unchanged by\ndesign, not by omission. company already enforced its id natively via\ncitty's own required-positional default and needed no change.",
          "is_bot": false,
          "headline": "fix(cli): bare intent-shaped group invocation exits 2, not 0",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T08:17:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d1ee23212eec810c34847bc17e8c1008e8060ae0",
          "body": "The stream_truncated JSON sentinel (stdout) and the truncation prose\nnote (stderr) were hand-rolled at each of 47 streamAll() call sites\nand had drifted apart: search wrote the sentinel but dropped the\nprose, every other --all command wrote the prose but dropped the\nsentinel. Move both writes into s\n[…]\n-call-site duplication to drift again.\n\nAdds a structural regression guard (no call site may hand-roll either\nliteral) plus a functional sweep across one representative command per\n--all-capable file.",
          "is_bot": false,
          "headline": "fix(paginate): unify --all truncation sentinel across every command",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T08:05:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fcce21978dd740ea9dc25958bd3f473462ef21e8",
          "body": "…OT_SUPPORTED to exit 8\n\nBoth were previously unmapped: ACCOUNT_ALREADY_LINKED existed in the SDK's\nErrorCode union but was never added to EXIT_CODE_MAP, and\nLINKEDIN_OPERATION_NOT_SUPPORTED is a new SDK error code. Bucketed with\nthe other account/connection-state codes (ACCOUNT_RESTRICTED,\nRESOURCE\n[…]\nt being unable to do something against LinkedIn, not a\ntransient or user-input error. Refreshed the @curviate/sdk tarball\ndependency to pick up the new error code (pnpm-lock.yaml integrity hash\nonly).",
          "is_bot": false,
          "headline": "feat(exit-codes): map ACCOUNT_ALREADY_LINKED and LINKEDIN_OPERATION_N…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T07:06:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "67ea2ba051ed379a21c90df5f07e86b68a45e87f",
          "body": "account connect-session poll's help text and its terminal-failure\nre-connect instruction still described themselves in terms of the hosted\naccount connect-link command, which was removed in 0.15.0. The\nre-connect instruction told the caller to run a command that no longer\nexists (curviate account co\n[…]\nll the status of an in-progress connect (auth intent)\" instead of the\ndead hosted-link framing, and drops the stale account connect-link\ncross-reference from the poll description's --wait explanation.",
          "is_bot": false,
          "headline": "fix(cli): reframe stale hosted-connect-link copy as in-progress-connect",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T06:53:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7a52015eaa1762f0c0473abd7c89a77963f09a59",
          "body": "…ed vocabulary (D9)\n\nThe server's linkedin_sections vocabulary is prefixed (linkedin_skills, not\nskills), but the CLI forwarded --sections values verbatim and its own\n--help example (experience,education) was one of the values that 400s.\n\nAdds lib/sections.ts: parseSectionsFlag splits/trims a --sect\n[…]\nid>'s base users.get branch.\nUpdates both --sections --help strings to show the canonical\nlinkedin_-prefixed values instead of the broken bare example, plus the\nprofile endorse help's cross-reference.",
          "is_bot": false,
          "headline": "fix(cli): auto-prefix and validate --sections values against the serv…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T06:47:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d80b19cb4903a04834026f0c9995c77c9f45ab75",
          "body": "post user-posts, post user-reactions, comment user, and profile <id>\n--sections all 400 on a raw public slug/URL (only the \"me\" sentinel and a\nraw provider id route) — the same class of gap as the D6 follow/unfollow\nfix, but on reads rather than writes.\n\nAdds resolveMemberOrMeProviderId to lib/membe\n[…]\n00 (D1) are\nseparate, already-classified defects unrelated to id-form and are left\nalone. sales-nav save-lead's user_id is deliberately verbatim by design,\nwith no evidence of a slug-rejection defect.",
          "is_bot": false,
          "headline": "fix(cli): extend slug->provider-id resolution to the D7 read surface",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T06:42:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "07c48a11ab010758981c3c8083fb860fe43f0f61",
          "body": "…ape (D2)\n\nThe v2 SDK returns {id, created_at, message?, user:{id, type, display_name,\nfirst_name, last_name, public_picture_url, ...}} for sent/received\nconnect-requests, but the slim default still projected the removed v1 shape\n(invited_user_*/inviter/date/parsed_datetime/specifics) — every identi\n[…]\nentifier on the received side — the field that lets an agent\nsafely pick which invite to accept). --fields now projects real v2 keys.\nUpdates the connect sent/received help text to name the v2 fields.",
          "is_bot": false,
          "headline": "fix(cli): rebuild connect sent/received slim projection for the v2 sh…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T06:33:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7f38c0ca3f1666646e0866c39197b8c5154e833a",
          "body": "…sion prose fix\n\nAdds the optional --account-id <acc_...> flag to `account link` (0.15.0):\npresent -> forwarded as account_id in the auth.intent body (re-authenticate the\naccount in place / reconnect); absent -> the key is entirely absent from the\nbody (not undefined, not empty). This is the reconne\n[…]\nt response.\n\nCHANGELOG: non-breaking Added entry for --account-id + a Fixed section for the\ncompany id-first routing, company sub-resource slug resolution, and profile\nfollow/unfollow slug resolution.",
          "is_bot": false,
          "headline": "feat(cli): account link --account-id in-place reconnect + connect-ses…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T05:48:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "34420d7d2e03d425644eff240e5bb2e924d14f8b",
          "body": "`profile follow/unfollow <slug>` forwarded the raw slug, which 404s the\nfollow endpoint (provider-id only), while profile/connect/message auto-resolve.\nBoth now resolve a URL/slug to the member's provider id via a users.get READ\n(contact-safe, notifies no one) before the write — the same standard\nre\n[…]\nd runs under --preview too, so the preview renders\nthe resolved id; a genuinely unresolvable identifier surfaces users.get's\n404 as exit 4 with no write. Extracts the resolution into lib/member-id.ts.",
          "is_bot": false,
          "headline": "fix(cli): resolve profile follow/unfollow slugs to a provider id (D6)",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T05:43:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "df20b74f5790db66a982a3dc060af126c8bbc03e",
          "body": "…D4b)\n\n`company employees|posts|jobs <slug>` previously forwarded the raw slug and\ntook the sub-resource endpoint's 400 (numeric-id required), while bare\n`company <slug>` auto-resolves. The three sub-resources now share the same\nidentifier contract as the retrieve: a URL/slug is normalized then reso\n[…]\naight through with no extra call; a genuinely unresolvable\nidentifier surfaces companies.get's CurviateError (404 -> exit 4, 400 -> exit 2).\nHelp text and docstrings updated to the broadened contract.",
          "is_bot": false,
          "headline": "fix(cli): auto-resolve company sub-resource slugs to the numeric id (…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T05:40:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ef1727a41fbcd9adefa5bf98dc0b01b3ce574a60",
          "body": "…r silent-swallow\n\n`company <id> employees` silently returned the base company profile (exit 0),\nignoring the trailing `employees` token: citty binds only the node's declared\npositionals and swallows the rest into args._. The pre-router now detects an\nunexpected extra positional on any bare-form gro\n[…]\nnt node.\nSwept uniformly across every bare-form group (company/profile/connect/message/\nsearch/post/job/recruiter/sales-nav). Adds a table-driven pre-router unit test\nplus end-to-end dist-spawn cases.",
          "is_bot": false,
          "headline": "fix(cli): reroute id-first sub-resource forms in the pre-router, neve…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T05:37:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4fd3873ca323a0800f29ed9a263fabd58e248865",
          "body": "check:clean excluded dist/ from SKIP_DIRS, so the anti-leak gate never\nscanned what actually ships. Add a --dist mode to check-clean.mjs that\nscans dist/ only (fails closed if it doesn't exist yet) with the same\npattern set, and chain it into prepack after the build step so no\npublish path can skip it.",
          "is_bot": false,
          "headline": "fix(cli): scan built dist/ output for leak patterns, not just source",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T04:47:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f8a93100684b5e63b3401881e03b09c5e74f6890",
          "body": "The flag's value is an endorsement_id obtained from the target's\nskills section (profile <id> --sections skills), not a skill name —\nthe old name misled agents about what to pass. Clean rename, no\ndeprecated alias.",
          "is_bot": false,
          "headline": "fix(cli)!: rename profile endorse --skill to --endorsement-id",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T04:43:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b1456ebac5c64866456263b1c91d2993b20e24d8",
          "body": "… commands\n\npost-id-help.test.ts still probed the removed post comment/post comments\ndescriptions and the old --reply-to guidance; keep the get/reactions/react\npostId-description checks and repoint post get's guidance assertion at the\n`comment list` command.",
          "is_bot": false,
          "headline": "test(cli): drop post comment/comments help assertions for the removed…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T04:15:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "47c9de94e42b1bb531393c25fa771a6f82b85955",
          "body": "Drop the removed `company followers` recipe; rewrite the whole Recruiter\nsection to the project-centric v2 surface (project-job get, project-scoped\napplicants with --channel-id, save-candidate, --project-name on job create,\n--subject/--signature on message new) — no more add-candidate/add-applicant/\n[…]\naction like\nand drop a --preview on the read `search people` example (reads reject\n--preview). Also correct the parity manifest doc-label for the bare\n`recruiter applicant` command (no `get` keyword).",
          "is_bot": false,
          "headline": "docs(cli): realign README examples to the shipped v2 surface",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T04:12:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "624e2c6d24279537915dd74e8483faaa72c70023",
          "body": "Document every breaking category of the v2-parity release — removals (13\ncommands + the --notify/--surface/--video-thumbnail/--url flags), the command\nrelocations (comment group, connect accept/decline, save-candidate, project-job\nget, top-level applicants, profile relations), the CLI-visible shape \n[…]\ntage the package version\nat 0.15.0 (not published).\n\nNOTE: the @curviate/sdk dependency is a temporary local file: tarball on this\nbranch; the release step flips it to ^0.15.0 after the SDK publishes.",
          "is_bot": false,
          "headline": "chore(cli): CHANGELOG 0.15.0 + stage version 0.15.0",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T04:08:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6142b174af551bd5e576949aa08f523636f15948",
          "body": "…methods)\n\nRebuild PARITY_MANIFEST as a bijection over all 115 v2 SDK methods across 13\nnamespaces (adds the auth + comments namespaces and the users rename off\nprofiles). Fixes the pre-campaign baseline gap (webhook get -> webhooks.get was\nmissing, count was 93) and drops every orphan entry. The fi\n[…]\ncounted\naliases (profile me + the --posts/--comments/--reactions/--followers sub-flags)\nstay excluded so the bijection holds at exactly 115. Negative guards (phantom\nentry, uncovered method) retained.",
          "is_bot": false,
          "headline": "test(cli): reconcile SDK-parity manifest to the full v2 surface (115 …",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T04:05:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ee35b339977259b08075be0ba84dcd636ddd3249",
          "body": "… --url/--notify flags\n\nFR-009: rename `recruiter job applicants <project_id>` to the project-scoped\ntop-level `recruiter applicants <project_id>` (--channel-id still required) to\nmatch listApplicants' project scope.\n\nFlag hygiene sweep: remove the `--url` string flag from search people/companies/\np\n[…]\n, and finish the FR-002 `--notify` removal\nCLI-2 left half-done — the flag was still declared on `profile <id>` though never\nforwarded; it is now absent from the args, the type, and the help entirely.",
          "is_bot": false,
          "headline": "refactor(cli)!: promote recruiter applicants to top-level + drop dead…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T04:04:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "627928d1a61f8da7ce21dc953fd9ac11db56dc53",
          "body": "…mands\n\nDrop the CLI commands whose SDK method no longer exists on the v2 surface:\naccount connect-link/reconnect-link/reconnect, company followers,\ninbox sync/sync-chat, post list, recruiter sync/add-applicant/reject-applicant,\nrecruiter job checkpoint, sales-nav sync, webhook state-diff — plus the\n[…]\nt, and tests. Exempt and retained: account link,\nconfig *, webhook verify, profile me. New test/orphan-removal.test.ts guards\nthat every removed command is absent from its group's subcommand registry.",
          "is_bot": false,
          "headline": "feat(cli)!: remove 13 v2-orphan commands + relocated post comment com…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T03:55:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7f34b5751cdfbaaa2f5c1a38817fe94edfbf3ddd",
          "body": "Wires salesNavigator.searchFromUrl behind the bare `sales-nav search\n<url>` form (mirrors the top-level `search`/`recruiter search` pattern),\npaginated via --limit/--cursor/--all. Completes the 12-op v2 list\nsurface — save-account/save-lead's shrunk {list_id,company_id|user_id}\nbodies were already correctly wired.",
          "is_bot": false,
          "headline": "feat(sales-nav): add the search <url> from-URL variant",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T03:19:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e8f1f6d189a435aba0f00a843fc7bc59e7b3b51f",
          "body": "…h<url>\n\nNew project-centric commands: project update, pipeline, project-job\nget/create/budget/update, job close, talent-search, and the search <url>\nfrom-URL variant. Completes job create's v2 body (job_title:{id,name},\ncompany, workplace_type, employment_status, seniority_level, industry,\njob_func\n[…]\nply_method) with client-side required-field validation\nnaming the missing flag before any SDK call. job publish now requires\n--mode and validates the full --budget-* triple for PROMOTED/PROMOTED_PLUS.",
          "is_bot": false,
          "headline": "feat(recruiter): add project/pipeline/project-job/talent-search/searc…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T03:15:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9d976b041c2d868fa37ca7187d5547ecb6c2a2e9",
          "body": "…ing from-URL\n\nThe from-URL note is appended as a second sentence so the branding-rename\nhelp assertion ('Search people, companies, posts, and jobs.') stays green.",
          "is_bot": false,
          "headline": "fix(search): keep the group help one-liner substring stable after add…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:50:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "55a05ea8319b381131e127d6135a47e859e67af9",
          "body": "Marks a chat read via messaging.markChatRead(chatId, { read: true }); write\ncommand with --preview, chat id normalized from a thread URL. Verified the\nexisting message attachment binary read-back still matches the v2\ngetAttachment(chatId, messageId, attachmentId) signature (no change needed).",
          "is_bot": false,
          "headline": "feat(inbox): add inbox mark-read <chat_id> (messaging.markChatRead)",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:44:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9faf70a5b2f275e8e251485e7ef614eff8746181",
          "body": "The search group gains a bare url positional: 'search <url>' runs a pasted\nLinkedIn search / saved-search / lead-list URL directly via search.fromUrl,\nalongside the structured people/companies/posts/jobs/parameters subcommands.\nRead command; forwards --limit/--cursor; --all streams the polymorphic result.",
          "is_bot": false,
          "headline": "feat(search): add the search <url> from-URL variant (search.fromUrl)",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:42:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a5f5103eb6203ba8c61758237a65a237592effb7",
          "body": "post delete (bodyless) and post unreact (DELETE-with-body {reaction}) are\nwrites with --preview; post user-posts/user-reactions are first-class\npaginated reads over posts.listUserPosts/listUserReactions (user id via\nresolveIdentifier, accepts 'me'). Leaves the CLI-4 removals (post list,\npost comment/comments) untouched.",
          "is_bot": false,
          "headline": "feat(post): add delete/unreact/user-posts/user-reactions",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:39:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d60ca8fa99e89632bc0b9144dbad272b43446dca",
          "body": "… connections->relations\n\nprofile update -> users.update('me', body) (headline/bio/first-name/last-name/\nskills/pictures; no description key ever). profile follow/unfollow are bodyless\nwrites; profile followers/following become first-class paginated reads. Clean\nrename of profile connections -> profile relations (no alias).",
          "is_bot": false,
          "headline": "feat(profile): add update/follow/unfollow/followers/following; rename…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:37:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "76544ad5beaff68b60231f2bd59991fc3c674f0e",
          "body": "…/close/applicants)\n\nAdds the whole classic job-posting write + applicant surface over the SDK jobs\nnamespace: list (--state required), create (nested job_title/company +\napply_method oneOf, 7 required flags), update (partial), budget, publish\n(--mode required; PROMOTED/PROMOTED_PLUS require an explicit --budget-* triple),\nclose (bodyless), applicants (POST-as-search, paginated), applicant get, and\napplicant resume (binary -o). Required-flag misuse names the flag and exits 2\nbefore any SDK call.",
          "is_bot": false,
          "headline": "feat(job): complete the job family (list/create/update/budget/publish…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:32:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "361e5ffedf4d63cfc49adbb944c1545231893b47",
          "body": "connect accept <id> -> invites.accept and connect decline <id> ->\ninvites.decline, both bodyless with --preview. Removes the combined\nrespond --action command. invitation_id stays verbatim (never URL-resolved).",
          "is_bot": false,
          "headline": "feat(connect): split respond into accept/decline subcommands",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:26:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e323987a588e94316692a7be10eb4e22e2eba3ec",
          "body": "…omment list)\n\nDedicated intent-shaped surface over the SDK comments namespace, replacing the\noverloaded post-flag design: list/add/reply/edit/delete/replies/react/reactions/\nunreact/user. Reads paginate and reject --preview; writes render --preview\nhermetically. unreact is a DELETE-with-body; delete is bodyless (204). Wired\ninto the lazy dispatcher.",
          "is_bot": false,
          "headline": "feat(comment): add the comment command group (9 comments ops + post c…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:21:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "935513fb9e7f739e5e26dbc3d04561c93243abda",
          "body": "… Rule #1)\n\ncheck:clean flagged FR-NNN / sdk/NNN / cli/NNN citations that leaked into\nsource comments across the re-point chunk (account/connect/message/post/\nrecruiter/sales-nav/search/webhook/attach + one test file) — a public-repo\nviolation. Reworded every flagged comment to describe the reasonin\n[…]\nry tests (messaging-bin.test.ts) that predate\nthe message/chatId and inmail/--surface re-point: `message edit` now takes\na leading chat_id positional, and `message inmail` no longer accepts\n--surface.",
          "is_bot": false,
          "headline": "fix: strip internal spec/doc references from committed comments (Hard…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:10:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cdc794acf378f5880b0e620ecc9c6858acea0e58",
          "body": "… namespace\n\naccounts.link/solveCheckpoint/requestCheckpoint/pollCheckpoint/getConnectSession\nare split out of accounts into the root-scoped auth namespace in v2 —\nre-pointed to auth.intent/solveCheckpoint/requestCheckpoint/pollCheckpoint/\ngetSession. auth.intent's body is assembled dynamically acro\n[…]\nait loop it shares with connect-session poll is fixed here\nsince the latter is in-scope.\n\ncreateConnectLink/createReconnectLink/reconnect stay red (CLI-4 — their SDK\nmethods are removed, not renamed).",
          "is_bot": false,
          "headline": "fix(account): re-point link/checkpoint/connect-session to the v2 auth…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T02:02:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cf28a32dd3369d1c041f14a91b1c04472ca26c76",
          "body": "…s to v2\n\n- startChat: JSON-only, --subject/--signature now required; attachments\n  (incl. voice/video) ride the shared base64 attachments[] array with\n  send_mode:\"native\" for voice/video, no more voice_message/video_message.\n- search parameters: getParameters (GET) -> searchParameters (POST,\n  sou\n[…]\n 404 against the real v2 op); --channel-id\n  is now required in the body.\n\nrecruiter sync/add-applicant/reject-applicant/job checkpoint stay red for\nCLI-4 (their SDK methods are removed, not renamed).",
          "is_bot": false,
          "headline": "fix(recruiter): re-point startChat/searchParameters/saveCandidate/job…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T01:52:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42efe78f44aa23bc16886572c9dbe0605d83d08c",
          "body": "salesNavigator.getParameters requires --type (already citty-required) with\na typed query (paths[...] alias, narrow cast on the free-form --type flag).\n\nsalesNavigator.startChat is JSON-only in v2 — --subject is now required\n(the classic messaging surface's optional subject doesn't carry over), and\nt\n[…]\nre is no separate voice_message/video_message body field: every\nattachment (file/voice/video) rides the single attachments[] array as a\nbase64 payload, with send_mode:\"native\" for voice/video bubbles.",
          "is_bot": false,
          "headline": "fix(sales-nav): type getParameters/startChat against the real v2 shapes",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T01:39:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2fc907e545407ed2e00e997f9f69a3e7f716f6f8",
          "body": "posts.create is pure application/json in v2 (no multipart, no\nvideo_thumbnail field) — attachments now encode as base64\n{content,content_type,filename} via toAttachmentPayload; --video-thumbnail\nis dropped (no v2 home, same class as profile's --notify).\n\nposts.react's body is {reaction, react_as?} —\n[…]\nomment-id is dropped from\n`post react` and --as-organization now maps to the renamed react_as field.\n\npost list (removed) and post comment (relocates to the future comment\ngroup) stay red for CLI-3/4.",
          "is_bot": false,
          "headline": "fix(post): type create/react bodies against the real v2 shapes",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T01:36:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cc9f2b703086e6fe8d6daf26238e17af7770583b",
          "body": "…4 attach)\n\n- profiles.get -> users.get for --to slug/URL resolution (message new /\n  message inmail); reads the real UserProfile.id field, not the shim's\n  provider_id.\n- get/edit/delete/react/attachment re-homed under /chats/{chat_id}/... —\n  each now takes a leading chat_id (normalized the same w\n[…]\ntachments (message new / message send) now encode as base64\n  {content,content_type,filename} objects via the shared toAttachmentPayload\n  helper, matching v2's JSON-only write surface (no multipart).",
          "is_bot": false,
          "headline": "fix(message): re-point messaging to v2 (chat-scoped ops, users, base6…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T01:31:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "45c25d14e1490e93bb545c8e2c8d1029c18226e5",
          "body": "webhooks.create's body is a source-discriminated union (messaging | user |\naccount_status) with per-source events/data enums; source/events/data are\nfree-form CLI flags, so a narrow documented cast at the call site stands in\nfor full static discrimination (FR-001 body-typing rule). getStateDiff\n(webhook state-diff, orphaned in v2) stays red for CLI-4.",
          "is_bot": false,
          "headline": "fix(webhook): type create's body against the real v2 discriminated union",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T01:21:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e73d55be8cb256632360694d744526c9a3cd221c",
          "body": "search.getParameters(query: SearchParametersQuery) requires both type and\nkeywords in v2 (the pre-v2 API allowed omitting keywords for\nEMPLOYMENT_TYPE). --keywords is now a required flag with a client-side\nexit 2, and the query is built as a typed object (paths[...] alias)\ninstead of Record<string, unknown>, with a narrow cast on the\nfree-form --type flag against the served enum.",
          "is_bot": false,
          "headline": "fix(search): type getParameters against the real v2 query shape",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T01:20:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1fa1d039b8ac9b69e2843b87efc12a25c4e8ea3c",
          "body": "v2 splits the old accounts.respond(id,{action,shared_secret}) into two\nbodyless ops, invites.accept/invites.decline. connect respond keeps its\nnoun (cli/004's intent-shaped tree) but now dispatches on --action to the\nmatching bodyless call; --shared-secret has no v2 home (accept/decline take\nno body) and is dropped. connect <id> send's body is now a typed literal\ninstead of a Record<string, unknown> so it structurally matches\ninvites.send's real body type.",
          "is_bot": false,
          "headline": "fix(connect): re-point respond to invites.accept/decline (v2)",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T01:19:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "299cf6fd9552338554dc4c6d21af727462dff719",
          "body": "The v2 SDK's writes with attachments are pure application/json (no\nmultipart op on the served surface) — attachments travel as\n{content,content_type,filename} objects with base64-encoded bytes.\nAdd toAttachmentPayload/guessContentType as the shared Buffer->wire-object\nconverter for the command re-point (message/post/recruiter/sales-nav).",
          "is_bot": false,
          "headline": "feat(attach): add v2 base64 attachment-payload helper",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T01:16:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "07e4c1edbfd7ad12680bfa58594c45a434ae1c18",
          "body": "…ndation\n\nDelete the hand-rolled `MinimalClient` type + the `client as unknown as\nMinimalClient` cast from every remaining command file, and type each run\nfunction against the real exported `Curviate` client. The severing cast was\nmasking removed/renamed/relocated SDK methods as runtime-only breaks;\n[…]\n and a negative-control compile fixture proving\nthe identical stale call fails tsc once the shim is removed and type-checks\ngreen while it is present. Fixtures are excluded from the package typecheck.",
          "is_bot": false,
          "headline": "refactor(commands): remove MinimalClient shims — compile-coupling fou…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T00:57:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cfdd9c1c88babb4b10ba402cdbc5aec108d2c06a",
          "body": "…ny crash\n\nRe-point every `profile` run function off the hand-rolled `MinimalClient`\nshim and onto the real exported `Curviate` client type. With the shim gone,\nthe company-resolution path is corrected from the removed `profiles.getCompany`\nto the retained `companies.get`, and the whole group is re-\n[…]\nflagged for the re-point pass: v2 users.get exposes only\nlinkedin_sections, so `--notify` (the pre-v2 signal-a-view query) is not\nforwarded — guarded by a test and left for the command re-point chunk.",
          "is_bot": false,
          "headline": "refactor(profile): type against the real SDK client; fix the getCompa…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T00:57:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "706bfc4893c2344f0359d80584a33c278754dad0",
          "body": "Bump the @curviate/sdk dependency to the v2-parity 0.15.0 surface so the CLI\ncompiles and tests against the real client type set.\n\nTEMPORARY / BRANCH-LOCAL: 0.15.0 is not yet published to npm. The dependency\nis a `file:` reference to a local, out-of-repo tarball\n(../../.claude/tmp/pm/sdk-cli-v2/curv\n[…]\nh install\nresolves the built SDK without a registry. This MUST be flipped to `^0.15.0`\nwith a lockfile re-resolve at the release step, once the SDK is published. The\ntarball itself is never committed.",
          "is_bot": false,
          "headline": "chore(deps): point @curviate/sdk at 0.15.0",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-11T00:57:35Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5bf9492148ed47698a999b1571dfdacb9838237e",
          "body": "Adds webhook get <id> for the SDK's new webhooks.get() (net-new\nGET /v1/webhooks/{id}) -- a read command, --preview is a usage error like\nstate-diff. Bumps the @curviate/sdk dependency to match the coupled 0.14.0\nwebhooks cascade; this CLI never imports CurviateEvent directly, so the\nSDK's event-catalogue re-key does not affect it.",
          "is_bot": false,
          "headline": "feat(webhook): add get <id> + bump @curviate/sdk to ^0.14.0",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-07T00:26:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1970bdcb506b07fc8000a1bc0c1d99733af022fa",
          "body": null,
          "is_bot": false,
          "headline": "chore: lock sdk 0.13.0",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-06T14:58:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "20d2aa93db9e84049aa8e4b63d6ef51ee92e03e6",
          "body": "The coupled SDK 0.13.0 connect-fix regen adds `recovered`, a widened\ncompleted-account `status` (active | reconnect_needed | restricted |\ndisconnected), and `challenge_type` + `recovery_hint` on an expired\nmobile-approval poll. The CLI duck-types account-connection responses\n(reads `status` as a fre\n[…]\n with no code change and no typed read-path breakage.\nSurfacing `recovered` in the human-readable success line is deferred as a\nUX follow-up (needs consistent treatment across three completion paths).",
          "is_bot": false,
          "headline": "docs(changelog): note connect-fix response fields under 0.13.0",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-06T14:24:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bd6342523743112955f3503a2654289917e7fec6",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 0.13.0 — bump @curviate/sdk dep to ^0.13.0",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-05T21:16:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "011fd8aee4eb42625aedd4bc65487f3402dfa7d0",
          "body": "…path grammar\n\nCheckpoint commands move to a positional account_id: `checkpoint solve\n<account_id> --code`, `checkpoint request <account_id>`, and `checkpoint poll\n<account_id>` replace the old `--checkpoint`-flagged submit/resend/poll. New\n`account reconnect-link <account_id>` mints a hosted re-aut\n[…]\n3.\n\nFix: `account connect-session poll` passed the session id as an object,\nproducing a `/connect-sessions/[object Object]` path — now a string, with a\nregression test asserting the interpolated path.",
          "is_bot": false,
          "headline": "feat(account): reshape checkpoint/connect commands to the account-in-…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-05T21:16:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "597e4350ad0d35b8657f62a63db7999e6fb28a1d",
          "body": null,
          "is_bot": false,
          "headline": "chore: lockfile — resolve @curviate/sdk@0.12.0 (published)",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-05T06:09:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "15cad47533789c3368df83489ce234930c5fb2c0",
          "body": "…tion",
          "is_bot": false,
          "headline": "docs: reconcile 0.12.0 dep bullet to ^0.12.0 + add Company README sec…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-05T06:06:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7c7513d4e6518cf50c35375e33acbbbaea588a0d",
          "body": null,
          "is_bot": false,
          "headline": "chore(release): 0.12.0 — bump @curviate/sdk dep to ^0.12.0",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-05T05:59:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5bc31c4337490b296dfc0bf5ccba169b74e25140",
          "body": "…ng save-lead re-signature\n\nAdds account-lists/lead-lists/browse-account-list/browse-lead-list/save-account\nsubcommands calling the SDK's new v2 salesNavigator methods (SDK-before-CLI\nordering, no re-implementation of the HTTP call). List/browse subcommands keep\npagination flags; save-account is a w\n[…]\nst semantics).\n\nUpdates the SDK-parity manifest (88->93 methods) and flag-hygiene negative\ncontrols; adds dist-level routing + --help checks for the five new\nsubcommands; README gains worked examples.",
          "is_bot": false,
          "headline": "feat(sales-nav): v2 list-surface cascade — 5 new subcommands + breaki…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-05T01:37:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "60fba7fea96a1cb4e8fb9801183e4ed72741e206",
          "body": "…t retrieve\n\ncompany <id> now routes to companies.get (the SDK's hard-move off\nprofiles.getCompany) and requires --account (the endpoint always requires\naccount_id). Four new subcommands facade the SDK's new companies resource:\nemployees, posts, jobs, followers. Coexistence of the bare positional wi\n[…]\nist/cli.js.\n\nAlso adds RESOURCE_ACCESS_RESTRICTED to EXIT_CODE_MAP (exit 8) — the SDK's\nnew error code for the followers non-admin case. SDK-parity manifest and\nmethod-count target move from 84 to 88.",
          "is_bot": false,
          "headline": "feat(company): add employees/posts/jobs/followers subcommands, repoin…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T23:55:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2cac0c0918f3ac59f215d217dd92aa9d88d7b35d",
          "body": "… credential safe-entry, dispatch fix\n\nBumps @curviate/sdk to ^0.11.0 (published) and closes out the two\nparity-manifest entries held back pending that SDK regen: `account\ncheckpoint resend` -> accounts.resendCheckpoint and `account\nconnect-session poll` -> accounts.getConnectSession. Manifest + SDK\n[…]\nesend command, connect-link browser\nhandoff + connect-session poll, pagination-flag suppression on\nsingle-op account commands, and the no-prefixed-flag dispatch fix.\n\nSee CHANGELOG.md for full detail.",
          "is_bot": false,
          "headline": "release: 0.11.0 — checkpoint resend/poll-wait/connect-session parity,…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T18:53:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0a8909247b052222593754fb81e6a2911827a173",
          "body": "`account connect-link` now completes the hosted-link round trip instead of\njust minting a URL. On an interactive TTY it auto-opens the URL via `open`\n(new dependency, pinned `^10.1.0` — the last major floored at Node >=18) and\nwaits on the same adaptive cadence as `checkpoint poll --wait` (1000ms, t\n[…]\n vs --json\nsilence, --no-open/--no-wait overrides), the non-interactive short-circuit\n(zero timers scheduled, open never called), the standalone poll command, and\nflag-suppression/registration checks.",
          "is_bot": false,
          "headline": "feat(account): connect-link browser handoff — open + adaptive wait",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T17:01:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "05b0cee4fd8737c4b8c3375f1fafccd767273dd0",
          "body": "Add `account checkpoint resend --checkpoint <id>`, a body-addressed\none-shot write mirroring `checkpoint submit`/`poll`: WRITE_SINGLE_FLAGS\n(pagination suppressed, --fields kept), no --code (nothing to submit),\n--preview support, and the shared exit-code table unchanged (404/409\ncheckpoint-flow errors exit 9, 501 exits 1). Exit is 0 on any 200\nregardless of the response's `resent` boolean — a false value is an\nhonest answer, not a command failure.",
          "is_bot": false,
          "headline": "feat(account): checkpoint resend command",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T14:36:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3289ff714dc267eb0a9a2a6ea62c323ebb05b31e",
          "body": "findUnknownFlag always stripped a \"no-\" prefix before checking the\ndeclared-flag set, so a flag literally declared with that prefix (e.g.\n\"no-interactive\") was misread as negating an undeclared name and\nrejected as unknown on every invocation. Check the full declared name\nfirst, then fall back to the stripped name only for citty's implicit\nnegation of an undeclared no-* flag.",
          "is_bot": false,
          "headline": "fix(dispatch): accept literally-declared no-prefixed flags",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T12:40:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "47c467d35811f3ef6f3cce3889961a385f798d77",
          "body": "…202 exit-12\n\n`account checkpoint poll` gains --wait (default off, single-poll behavior\nunchanged) — the same adaptive cadence as the interactive mobile-approval\nsub-loop (1000ms, then 1500ms for 30s, then 3000ms), until active (exit 0),\nexpired/failed (exit 9), or the wait window elapses while stil\n[…]\nll sits outside the try/catch so it can never be miscaught and\nmisrouted through the generic error handler.\n\nAlso drops a stale, unimplemented flag-description reference on\n`checkpoint submit --code`.",
          "is_bot": false,
          "headline": "feat(account): checkpoint poll --wait adaptive loop + submit chained-…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T09:29:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b0e2b7c3c6d00a81027d85072a7bf8d025d4ce5e",
          "body": "On a 202 checkpoint_required response, link/reconnect now resolve the\nchallenge in-process on an interactive TTY (code prompt, 422 retry loop,\nchained-challenge follow-through, a codeless mobile-app-approval poll\nsub-loop, and a resend hint) instead of just printing the envelope.\nNon-interactive sessions (either stream not a TTY, or --no-interactive)\nstill render the envelope and exit with the new AUTH_NEEDED (12) code.",
          "is_bot": false,
          "headline": "feat(account): guided checkpoint follow-through on link/reconnect",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T09:10:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "776f96dccf096a13f210874f722c2952abf5a553",
          "body": "check:clean scans test/ too (not just src/) — section-header comments\nciting internal AC/TS identifiers tripped the public-repo leak scan.",
          "is_bot": false,
          "headline": "chore(test): strip internal spec-ref comments from credential test file",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T08:46:15Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7356c2ca709bd618b9000a7d4792c6c5ff5db946",
          "body": "…prompt\n\nAdd env-var fallbacks (flag > env), --password-stdin/--li-at-stdin flags\nwith a 5-way conflict matrix, a masked TTY prompt + non-TTY fail-fast for\nthe credentials-method password, ps/shell-history warnings on the four\nsecret value flags, and --preview masking so a LinkedIn credential never\nrenders in cleartext. Applies across account link/reconnect/update.",
          "is_bot": false,
          "headline": "feat(account): safe credential entry — env vars, stdin flags, masked …",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T08:44:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b095fc33a7f31568202ef08d16d53121b0b9baf1",
          "body": "…kpoint hint in link/reconnect help\n\nAdds a WRITE_SINGLE_FLAGS flag set (pagination suppressed, --fields kept)\nfor the 8 account subcommands that mutate or resolve exactly one resource\n(link, connect-link, reconnect, refresh, update, disconnect, checkpoint\nsubmit, checkpoint poll) — --limit/--cursor/--all/--max-pages have no\nmeaning on a one-row response. account list is unaffected. link/reconnect\ndescriptions gain a one-line note about the checkpoint-required path.",
          "is_bot": false,
          "headline": "feat(account): suppress pagination flags on single-op commands + chec…",
          "author_name": "Raphael Redmer",
          "author_login": "RaRedmer",
          "committed_at": "2026-07-04T07:09:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 13,
      "commits_last_year": 171,
      "latest_release_at": "2026-07-17T16:49:17Z",
      "latest_release_tag": "cli-v0.17.0",
      "releases_from_tags": false,
      "days_since_last_push": 5,
      "active_weeks_last_year": 5,
      "days_since_latest_release": 6,
      "mean_days_between_releases": 1.5
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 50,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@curviate/cli",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": false,
          "registry_url": "https://www.npmjs.com/package/@curviate/cli",
          "is_deprecated": false,
          "latest_version": "0.18.1",
          "repository_url": "https://github.com/curviate/cli",
          "versions_count": 25,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 3853,
          "first_published_at": "2026-06-22T18:39:48.692000Z",
          "latest_published_at": "2026-07-18T10:12:25.974000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 90875,
      "source_files_sampled": 117,
      "oversized_source_files": 4,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "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": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@curviate/sdk",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.18.1"
        },
        {
          "name": "citty",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.1.6"
        },
        {
          "name": "open",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.1.0"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 13,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "RaRedmer",
          "commits": 159,
          "avatar_url": "https://avatars.githubusercontent.com/u/44050496?v=4"
        },
        {
          "type": "User",
          "login": "rapha-red",
          "commits": 12,
          "avatar_url": "https://avatars.githubusercontent.com/u/276905213?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.93
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": true,
      "ci_workflows": [],
      "has_docs_dir": false,
      "linter_configs": [
        "eslint.config.mjs"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "pnpm-lock.yaml"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 0,
            "reason": "0 out of 5 merged PRs checked by a CI test -- score normalized to 0",
            "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/11 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": null,
            "reason": "no dependencies found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "761ea169b86234d3ee9103dc548e7235263fd127",
        "ran_at": "2026-07-23T17:38:36Z",
        "aggregate_score": 2.2,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": null,
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-18T09:57:32Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/Curviate/curviate-cli",
    "host": "github.com",
    "name": "curviate-cli",
    "owner": "Curviate"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 42,
      "inputs": {
        "security": 22,
        "vitality": 75,
        "community": 24,
        "governance": 38,
        "engineering": 44
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 75,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 58,
            "inputs": {
              "commits_last_year": 171,
              "human_commit_share": 1,
              "days_since_last_push": 5,
              "active_weeks_last_year": 5
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "5/52 weeks with commits",
                "points": 3.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "171 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 171
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 13,
              "latest_release_tag": "cli-v0.17.0",
              "releases_from_tags": false,
              "days_since_latest_release": 6,
              "mean_days_between_releases": 1.5
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "13 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 13
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 6 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~1.5 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 1.5
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 24,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "at_risk",
        "name": "Sustainability & Governance",
        "value": 38,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 13,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.93
            },
            "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 93% of commits",
                "points": 1.6,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 93
                    }
                  }
                ],
                "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 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 72,
            "inputs": {
              "merged_prs": 13,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "13/13 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 13,
                      "decided": 13
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/11 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 35,
            "inputs": {
              "followers": 0,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "Curviate",
              "public_repos": 3,
              "account_age_days": 32
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "0 followers of Curviate",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 0,
                      "login": "Curviate"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "3 public repos, account ~0 yr old",
                "points": 4.6,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 3
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "at_risk",
        "name": "Engineering Quality",
        "value": 44,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "at_risk",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_ci": false,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "eslint.config.mjs",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.mjs"
                    }
                  }
                ],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "0 out of 5 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "critical",
        "name": "Security",
        "value": 22,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "critical",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "pinned_dependencies",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 22,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 13,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 5,
              "scorecard_aggregate": 2.2
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "0 out of 5 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "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/11 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "3 existing vulnerabilities detected",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 60,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_pinned_dependencies"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "pnpm-lock.yaml"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "tsconfig.json"
              ],
              "agent_commit_share": 0,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": "eslint.config.mjs",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.mjs"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 98,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 90875,
              "source_files_sampled": 117,
              "oversized_source_files": 4
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "4/117 source files over 60KB",
                "points": 53.1,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 117,
                      "oversized": 4
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "npm package '@curviate/cli' points at a different repository (https://github.com/curviate/cli); excluded from ecosystem scoring",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
    "deps.dev does not index npm:@curviate/cli@0.18.1; advisories assessed against the repository dependency graph instead"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-23T17:38:50.034133Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/c/Curviate/curviate-cli.svg",
  "full_name": "Curviate/curviate-cli",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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