Öffentliches Register
Software-GesundheitsberichtSchema 0.27.0 · Metriken 1.13.0 · 2026-07-23 17:38 UTC

Curviate / curviate-cli

Official CLI for the Curviate API

TypeScriptMIT★ 0 Sterne⑂ 0 Forksseit Juni 2026Auf GitHub ansehen ↗

Curviate/curviate-cli erreicht einen Gesundheitsindex von 42 von 100 und liegt damit im Bereich Gefährdet. Am stärksten schneidet es bei Vitality (75/100) ab, am schwächsten bei Security (22/100). Zuletzt vor 5 Tagen aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

42
gesamt / 100
Gefährdet

Software-Gesundheitsindex

Metriken werden auf einer Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr Mittel; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze 49 (Gefährdet). AI Readiness liegt außerhalb.

42
Exzellent85-100Vorbildlich; erfüllt im Wesentlichen alle geprüften Kriterien
Gut70-84Gesund; geringfügige Lücken
Mittel50-69Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Gefährdet30-49Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-29Schwerwiegende Probleme (aufgegeben, nur ein Maintainer, keine Hygiene)
VitalitätCommunity &VerbreitungNachhaltigkeit &GovernanceEngineering-QualitätSicherheitAI Readiness

Bewertungsprofil

Jede Achse ist eine Kategorie. Die Form zählt mehr als der Durchschnitt — ein gesundes Projekt füllt die gesamte Fläche, während ein Profil aus Spitzen und Kratern bedeutet, dass Stärke in einer Dimension Risiken in einer anderen verdeckt.

Eigentümerschaft

CurviateOrganisation
0 Follower3 öffentliche Reposseit Juni 2026

Dieses Repository wird von einer Organisation getragen — geteilte, rechenschaftspflichtige Trägerschaft, die jeden einzelnen Maintainer überdauern kann.

Paket-Ökosysteme

RegistryPaketVersionDownloads / MonatVersionenZuletzt veröffentlicht
npm@curviate/cliverweist auf ein anderes Repo — nicht bewertet0.18.13.85325vor 5 Tagen

Metriken nach Kategorie

Vitalität

Lebt das Projekt — wird Code geschrieben und werden Releases ausgeliefert?

75Gut · 22 % des Gesamtindex
Wie die Bewertung erfolgt
36/36Push-Aktualität — letzter Push vor 5 Tagen
3.5/36Commit-Rhythmus — 5/52 Wochen mit Commits
18/18Commit-Volumen — 171 Commits im letzten Jahr
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Verwendete Eingangsdaten
commits_last_year171
human_commit_share1
days_since_last_push5
active_weeks_last_year5

Release-Disziplin

100Exzellent
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 13 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 6 Tagen
27/27Release-Rhythmus — ein Release etwa alle 1,5 Tage
0/10OpenSSF Scorecard: Signed-Releases — keine Daten
Verwendete Eingangsdaten
releases_count13
latest_release_tagcli-v0.17.0
releases_from_tagsnein
days_since_latest_release6
mean_days_between_releases1,5
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: Signed-Releases. Die verbleibenden Gewichte wurden renormalisiert.

Community & Verbreitung

Hat das Projekt Nutzer, Downloads, Aufmerksamkeit und ein einladendes Umfeld für Beitragende?

24Kritisch · 18 % des Gesamtindex
Wie die Bewertung erfolgt
0/60Stars — 0 Stars
0/25Forks — 0 Forks
0/15Watcher — 0 Watcher
Verwendete Eingangsdaten
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Wie die Bewertung erfolgt
22.5/22.5README
22.5/22.5Lizenz — anerkannte Lizenz (MIT)
0/18CONTRIBUTING-Leitfaden
0/13.5Verhaltenskodex
0/7.2Issue-Vorlage
0/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licenseja
has_contributingnein
has_issue_templatenein
has_code_of_conductnein
has_pull_request_templatenein

Nachhaltigkeit & Governance

Überdauert das Projekt die Menschen, die es tragen — Bus-Faktor, Reaktionsfähigkeit, Trägerschaft und Paketpflege?

38Gefährdet · 24 % des Gesamtindex
Wie die Bewertung erfolgt
9/54Bus-Faktor — 1 Beitragende decken die Hälfte aller Commits ab
1.6/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 93 % der Commits
2.7/13.5Breite der Beitragenden — 2 Beitragende
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Verwendete Eingangsdaten
bus_factor1
contributors_sampled2
top_contributor_share0,93
Wie die Bewertung erfolgt
0/46.8Issue-Lösungsquote — keine Issues oder keine Daten
38.2/38.3PR-Annahme — 13/13 entschiedene PRs gemergt
0/15OpenSSF Scorecard: Code-Review — Found 0/11 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
merged_prs13
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Issue-Lösungsquote. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
30/30Organisatorische Trägerschaft — im Besitz einer Organisation
0/20Verifizierte Domain
0/25Reichweite des Inhabers — 0 Follower von Curviate
4.6/25Kontohistorie — 3 öffentliche Repos, Kontoalter ca. 0 Jahre
Verwendete Eingangsdaten
followers0
owner_typeOrganization
is_verified
owner_loginCurviate
public_repos3
account_age_days32

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

44Gefährdet · 20 % des Gesamtindex
Wie die Bewertung erfolgt
0/24CI-Workflows
24/24Tests vorhanden
16/16Linter-Konfiguration — eslint.config.mjs
0/9.6Pre-Commit-Hooks
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — 0 out of 5 merged PRs checked by a CI test -- score normalized to 0
Verwendete Eingangsdaten
has_cinein
has_testsja
has_editorconfignein
has_linter_configja
has_precommit_confignein
Wie die Bewertung erfolgt
30/30README
0/25Dokumentationsverzeichnis
0/15Dokumentations-/Homepage-Site
10/10Repository-Beschreibung
0/10Topics
10/10Wiki
Verwendete Eingangsdaten
topics
has_wikija
homepage
has_readmeja
has_docs_dirnein
has_descriptionja

Sicherheit

Sind die sichtbaren Sicherheits- und Lieferkettenpraktiken belastbar, ohne ungeklärte Exposition gegenüber Hochrisikojurisdiktionen?

22Kritisch · 16 % des Gesamtindex

Sicherheitslage

22Kritisch
Wie die Bewertung erfolgt
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 — keine Daten
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5Lizenz — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — keine Daten
0/5Pinned-Dependencies — keine Daten
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 — keine Daten
0/7.5Token-Permissions — keine Daten
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated13
scorecard_versionv5.5.0
checks_inconclusive5
scorecard_aggregate2,2
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions. Die verbleibenden Gewichte wurden renormalisiert.

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Ein unabhängiges, experimentelles Badge — Gewicht 0,0, es wird eigenständig ausgewiesen und verändert den Gesamt-Gesundheitswert nicht.

60Mittel · 0 % des Gesamtindex
Wie die Bewertung erfolgt
0/45Agentenanweisungen — keine CLAUDE.md / AGENTS.md / Editor-Regeln
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 100 von 100 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
Wie die Bewertung erfolgt
0/18Bootstrap mit einem Befehl
22/22Automatisierte Tests
11/11Lint-/Format-Konfiguration — eslint.config.mjs
11/11Statische Typprüfung — tsconfig.json
10/10Reproduzierbare Umgebung — lockfile
0/10Belegte Agentenpraxis — keine von Agenten verfassten Commits unter den letzten 100
0/8Automatisierte Wartung — keine automatisierten Abhängigkeits-Updates beobachtet
0/10OpenSSF Scorecard: Pinned-Dependencies — keine Daten
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfilespnpm-lock.yaml
has_dockerfilenein
typed_languageja
bootstrap_files
has_devcontainernein
has_linter_configja
typecheck_configstsconfig.json
agent_commit_share0
toolchain_manifests
dependency_bot_commit_share0
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: Pinned-Dependencies. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
45/45Typprüfbarer Code — TypeScript (statisch typisiert)
53.1/55Handhabbare Dateigrößen — 4/117 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languageTypeScript
largest_source_bytes90.875
source_files_sampled117
oversized_source_files4

Eckdaten

0GitHub-Sterne
2Mitwirkende
171Commits, letzte 12 Monate
5Tage seit letztem Push
13Releases
1Bus-Faktor
0offene Issues
npmPaket-Ökosysteme

Warnungen zur Datenerhebung

  • 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

Weitere Details

OpenSSF Scorecard 2.2 / 10
2.2Gesamtwert

Unabhängige, werkzeugneutrale Sicherheitsbewertung durch das quelloffene OpenSSF Scorecard. Jede Prüfung honoriert eine Sicherheits-Praxis, nicht das Werkzeug eines bestimmten Anbieters. Prüfungen, die Scorecard nicht ermitteln konnte, sind mit k. A. markiert und vom Sicherheitswert ausgeschlossen (nie als null gezählt).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
k. A.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
k. A.Packagingpackaging workflow not detected
k. A.Pinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
k. A.Signed-Releasesno releases found
k. A.Token-PermissionsNo tokens found
7Vulnerabilities3 existing vulnerabilities detected
Direkte Abhängigkeiten 3
RegistryPaketVersionsvorgabeManifest
npm@curviate/sdk^0.18.1package.json
npmcitty^0.1.6package.json
npmopen^10.1.0package.json
Alle Abhängigkeiten nicht erhoben

Der aufgelöste Abhängigkeitssatz konnte für diesen Bericht nicht erhoben werden: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

JSON-Rohbericht maschinenlesbar
{
  "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"
}

Bewertungen sind Signale, keine Garantien. Sie spiegeln öffentlich sichtbare Praxis auf GitHub wider — kein Code-Audit und keine Sicherheitsgarantie.

Fehlende Daten werden ausgeschlossen und die Gewichte neu normiert, nie als null bewertet. Die Methodik ist versioniert und offen: Metriken v1.13.0, Schema v0.27.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte Statistikennpm.