原始 JSON 报告 机器可读
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 1611,
"has_wiki": true,
"homepage": null,
"languages": {
"JavaScript": 16865,
"TypeScript": 1775426
},
"pushed_at": "2026-07-18T15:13:56Z",
"created_at": "2026-06-21T16:13:28Z",
"owner_type": "Organization",
"updated_at": "2026-07-18T15:14:00Z",
"description": "TypeScript SDK 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": "sdk-v0.17.0",
"kind": "other",
"published_at": "2026-07-17T16:40:43Z"
},
{
"tag": "sdk-v0.16.0",
"kind": "other",
"published_at": "2026-07-17T09:11:23Z"
},
{
"tag": "v0.15.0",
"kind": "minor",
"published_at": "2026-07-11T11:03:41Z"
},
{
"tag": "v0.14.1",
"kind": "patch",
"published_at": "2026-07-07T03:28:15Z"
},
{
"tag": "v0.14.0",
"kind": "minor",
"published_at": "2026-07-07T02:58:11Z"
},
{
"tag": "v0.13.0",
"kind": "minor",
"published_at": "2026-07-06T14:56:08Z"
},
{
"tag": "sdk-v0.12.0",
"kind": "other",
"published_at": "2026-07-05T06:10:22Z"
},
{
"tag": "sdk-v0.11.0",
"kind": "other",
"published_at": "2026-07-04T18:49:12Z"
},
{
"tag": "sdk-v0.10.0",
"kind": "other",
"published_at": "2026-07-03T20:09:29Z"
},
{
"tag": "sdk-v0.2.1",
"kind": "other",
"published_at": "2026-06-29T11:44:52Z"
},
{
"tag": "sdk-v0.2.0",
"kind": "other",
"published_at": "2026-06-28T17:18:09Z"
},
{
"tag": "v0.1.1",
"kind": "patch",
"published_at": "2026-06-22T18:17:52Z"
}
],
"recent_commits": [
{
"oid": "5855d2d476aee0212348d33509248591f132edea",
"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:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "feef41ed082ec99e8c97e7b34a3aa75f2daccfc8",
"body": null,
"is_bot": false,
"headline": "chore(release): @curviate/sdk 0.18.1",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-18T10:05:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8ef7982802f52322d9855c292695bd7b919c5aa0",
"body": "The company reply endpoint now accepts the same 2-… conversation id that\ncompanies.chats()/searchChats() return and resolves the page mailbox\ninternally from the identifier. Drop the send-ready COMPANY_ chat-id\nrequirement and the inboxes.listChats() sourcing from the class + method\nJSDoc and the example; add an Unreleased CHANGELOG entry. Method signature\nand response shape are unchanged (documentation only).\n\nCo-authored-by: Raphael Redmer <ra.redmer@outlook.com>",
"is_bot": false,
"headline": "docs(companies): sendMessage takes the normal 2-… chat id (#11)",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-07-18T09:57:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9d0c226735db61e20e768df125b9a64ee508caf4",
"body": null,
"is_bot": false,
"headline": "chore(release): @curviate/sdk 0.18.0",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-17T21:17:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3e177b30fa50321bb1388d80ea03b47d8c3db2c7",
"body": "…/029)\n\nPOST /v1/{account_id}/companies/{identifier}/chats/{chat_id}/messages —\nreply to a company-inbox conversation as the page. chatId must be the\nsend-ready COMPANY_ id from inboxes.listChats(), not the 2-… id\ncompanies.chats()/chat()/searchChats() return; reply-only. Result\ncarries sent_as, the\n[…]\ni.json + src/generated/types.ts off the\nfeat/company-chat-reply server branch (also picks up the Messaging:\nInboxes tag flatten, api/029 FR-006). Parity pin +1 (145 methods);\npath-grammar bank +1 row.",
"is_bot": false,
"headline": "feat(companies): add sendMessage (reply as the company page, spec api…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-17T19:05:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4c70bddd8835586bc910df2e40211d80d1cb0f36",
"body": "companies.followInvite + release 0.17.0",
"is_bot": false,
"headline": "Merge pull request #10 from Curviate/feat/company-follow-invite",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-07-17T16:38:22Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f1930b9a3c6299b1cfd820c7156b6f9c02db0994",
"body": null,
"is_bot": false,
"headline": "chore(release): @curviate/sdk 0.17.0",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-17T16:37:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "19efb7f290085d777193f606b3b13fe9a393fc28",
"body": "…ak-scan)",
"is_bot": false,
"headline": "chore(companies): drop internal spec refs from follow-invite copy (le…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-17T16:37:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3f120ef34ad84682a7a7cc79c6593faaf09d4001",
"body": "… success)\n\nqa live-verify proved the substrate top-level-rejects a batch containing any\ninvalid/nonexistent invitee (404 RESOURCE_NOT_FOUND); only an all-valid batch\nreturns 200 with per-invitee results (server commit c2dcd451). Reconcile the\nSDK side:\n\n- JSDoc: reword to the all-or-nothing contrac\n[…]\nurviateError(RESOURCE_NOT_FOUND), not a 200.\n- Re-dump fixtures/openapi.json off the corrected server + regenerate\n types.ts; only the follow-invite path changes.\n- CHANGELOG entry reworded to match.",
"is_bot": false,
"headline": "fix(companies): reconcile followInvite to all-or-nothing (not partial…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-17T13:58:58Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c82bd786373ddd04d048cb9b98f31c3239875a6d",
"body": "Re-dump the feat-branch server OpenAPI (server commit 53183f2b dropped em\ndashes from the follow-invite endpoint/param/response descriptions) and\nregenerate types.ts. Only the follow-invite path entry changes; every other\npath is byte-identical. One pre-existing, out-of-scope em dash remains on\nthe shared company sub-resource identifier param description (used by 10+\nother company endpoints, not touched by 53183f2b).",
"is_bot": false,
"headline": "fix(companies): drop em dashes from follow-invite OpenAPI snapshot",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-17T12:31:12Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bc054e75446c2303771ef101e68d2824d5804510",
"body": "Extend the companies resource with followInvite(identifier, body) —\nPOST /v1/{account_id}/companies/{identifier}/follow-invite — modeled on\ninvites.send. Invites the connected account's 1st-degree connections to\nfollow an administered page; partial-success results, one outcome per\ninvitee in request\n[…]\n.json + src/generated/types.ts off the\nfeat-branch server snapshot (adds the new path only, byte-identical\notherwise). Update the parity pin (+1 companies method, 144 total) and\npath-grammar coverage.",
"is_bot": false,
"headline": "feat(companies): add followInvite (spec api/028 FR-003)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-17T12:18:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "10397297cf8398a8807820ef8c23e680b7041f07",
"body": "feat: inboxes resource, sent_as, requested_products; remove disabled_features (0.16.0)",
"is_bot": false,
"headline": "Merge pull request #9 from Curviate/feat/company-scope-surface",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-07-17T09:09:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f4fc087439b076cf357afa716eba0f97c00928e4",
"body": "Founder follow-up: the company-behalf send must be first-class on the SEND\nmethod's own doc, not only on the inboxes resource that discovers a\nCOMPANY_ chat id.\n\n- messaging.sendMessage(): added an explicit \"Sending on behalf of a\n company page\" paragraph (no separate method, pass a COMPANY_ chat i\n[…]\ned in README.md and used by the tool's own\n auto-synthesized examples elsewhere.\n\nNo API shape change, documentation only (stays 0.16.0 pre-publish).\n\ntypecheck/test(514)/check:clean/build all green.",
"is_bot": false,
"headline": "docs: document company-behalf send explicitly on sendMessage itself",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-17T08:28:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "83f7708ab4ebcd6957204063448da0d12aa2561a",
"body": "No API shape change, documentation and ergonomics only (version stays\n0.16.0 pre-publish).\n\n- inboxes.ts: rewrote the module and method doc comments around the\n three-step reply-as-a-page pattern (list -> listChats -> sendMessage),\n spelled out explicitly rather than left implicit. list()'s exampl\n[…]\ncs.ts extracts it into the public docs site). Pre-existing prose\nelsewhere in these files (and in README.md) is untouched, out of scope for\nthis pass.\n\ntypecheck/test(514)/check:clean/build all green.",
"is_bot": false,
"headline": "docs: enrich inboxes/sent_as JSDoc with the full reply-as-page flow",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-17T07:59:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "61983912b970328aacd55de9a8ab31b7a8b0c39b",
"body": "…; PREMIUM_CONFLICT/REAUTH_REQUIRED codes (0.16.0)\n\nNew account-scoped `inboxes` namespace (2 methods, Beta), following the\nexisting resource pattern: `list(query?)` discovers the account's personal\ninbox plus, when the company product is attached, one entry per company\npage x folder; `listChats(inb\n[…]\npre-1.0 breaking release, matching the\n0.14.1 -> 0.15.0 precedent). Not published — publish is a separate,\nfounder-gated step.\n\ntypecheck/test(514)/check:types/check:clean/build/verify:dist all green.",
"is_bot": false,
"headline": "feat(inboxes): add inboxes namespace; sent_as/requested_products docs…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-16T23:01:47Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "272df4764b317c888c687fe54e22ec9bfe807427",
"body": "Regenerated from the running trunk server's live OpenAPI document\n(/.well-known/openapi.json, fake substrate lane) to pick up the WP4\ncompany-scope cascade: the two new Messaging: Inboxes endpoints\n(GET /v1/{account_id}/inboxes, GET /v1/{account_id}/inboxes/{inbox_id}/chats,\nboth Beta), the additive\n[…]\nations\naccount for the delta. No other schema components added or removed.\n\nsrc/generated/types.ts regenerated to match via `pnpm gen:types:fixture`.\n\ntypecheck/test/check:types/check:clean all green.",
"is_bot": false,
"headline": "chore(fixtures): refresh openapi.json + regen generated types",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-16T23:01:30Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7ac33509c4a0cfb9bd5aaa96ccd8050282b4b8e6",
"body": "Fixture had drifted from the served surface across two prior server-side\npasses (deliberately not pulled in surgically at the time): post-id path\nparams on the comment/reaction endpoints now document the opaque get-post/\nlist-posts id as the only accepted form (share URLs/URNs/bare numeric ids\ndropp\n[…]\n?: string` to\n`cursor: string | null`, which the shared PageEnvelope pagination type\nalready declared as `string | null` so no consumer breaks.\n\ntypecheck/test/build/check:types/check:clean all green.",
"is_bot": false,
"headline": "chore(fixtures): refresh openapi.json + regen generated types",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-16T17:42:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7306c6c11f2c9793c8f3ea6bbbc6dbcd57b877f2",
"body": "… returns\n\nchats/search reused the shared full-chat schema, but the mapper backing it\nis strictly sparser (no user{}, last_message never carries timestamp/\nis_sender). Regenerated from the corrected served OpenAPI document — types\nnow match the wire, not the shared shape.",
"is_bot": false,
"headline": "fix(types): searchChats item schema narrows to what the wire actually…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-16T12:29:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "648445e395a44f5c19a5752140d1e8af2ab21c3d",
"body": "…scan)",
"is_bot": false,
"headline": "chore(tests): strip internal doc references from test comments (leak-…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T20:09:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "74c45e3c204a1c1ac41d444bdaa8b07446636aa2",
"body": "New notifications namespace on client.account(id).notifications — the\nconnected account's own notification centre (api/019):\n\n- list(query?) -> GET /v1/{account_id}/notifications — cards newest-first,\n plus the account-level unread_count/latest_published_at alongside the page.\n- delete(cardUrn) -> \n[…]\n: parity pin 141 methods across 17\nnamespaces (was 138/16 after the prior posts commit; 135/16 baseline before\nthis feature slice — accounts(4)+auth(5)+webhooks(6) root, 14 account-scoped\nnamespaces).",
"is_bot": false,
"headline": "feat(notifications): add NEW account-scoped notifications namespace",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T20:07:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "795b8ff4651645d05190d790128a6d99d3e3e13d",
"body": "Extends the posts resource with the saved-posts bookmark surface (api/023):\n\n- listSaved(query?) -> GET /v1/{account_id}/saved-posts — the connected\n account's own saved posts, a self resource (no {user_id}). Items are\n previews only (snippet capped at <=140 chars) — never the full post body.\n- sa\n[…]\nunsaving re-asserts the same state).\n\nposts is now 12 methods (was 9). Parity pin: 138 methods across 16 namespaces\n(was 135/16) — notifications lands in the next commit for the campaign-final\n141/17.",
"is_bot": false,
"headline": "feat(posts): add saved-posts methods (listSaved/save/unsave)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T20:06:32Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "57370d5663846b6abfd3e78cb19d5311f1ca8b1a",
"body": "Documents the 12 additive methods landed across the three preceding\ncommits: companies +8 (company-insights trio + Beta company-inbox\nquintet), search +3 (groups/services/getServiceParameters), messaging +1\n(searchChats). Nothing removed, renamed, or reshaped.",
"is_bot": false,
"headline": "docs(changelog): note the companies/search/messaging extensions (M2/F2)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T19:50:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fb8d6521265455ee6f21859a46ebf09257d9e0f5",
"body": "Adds messaging.searchChats(params), mirroring listChats:\nGET /v1/{account_id}/chats/search. Free-text searches the account's own\ninbox (participant names and message content) -- distinct from the new\ncompanies.searchChats, which searches a company page's admin inbox.\n\nmessaging is now 13 methods (was 12). Parity pin 134->135 methods / 16\nnamespaces -- the final M2/F2 aggregate (companies +8, search +3,\nmessaging +1 = +12 total, 123->135).",
"is_bot": false,
"headline": "feat(messaging): add searchChats method",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T19:50:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b171d4406ba990b1c106a2dd8fa0eac607f01ac8",
"body": "Extends the search resource with 3 account-scoped methods, mirroring the\nexisting getParameters/people naming:\n\n- groups(query) -> GET /v1/{account_id}/search/groups\n- services(body & query) -> POST /v1/{account_id}/search/services (body +\n query merged, as people/companies already are)\n- getServic\n[…]\nice-category/location terms into the opaque\n ids services() accepts\n\nsearch is now 9 methods (was 6). Parity pin 131->134 methods / 16\nnamespaces (intermediate; F2 lands 135/16 once messaging lands).",
"is_bot": false,
"headline": "feat(search): add groups, services, and service-parameters methods",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T19:49:07Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d7c5da194522cf239e3bd9eddb897dcd858cba90",
"body": "Extends the companies resource with 8 account-scoped methods:\n\n- managed(query?) -> GET /v1/{account_id}/companies/managed\n- followers(identifier, query?) -> GET .../companies/{identifier}/followers\n (re-added under a different item shape than the pre-0.15.0 method of the\n same name -- company_fol\n[…]\nror block + absent-list entry, companies.test.ts's removal\ndescribe block) to positive coverage. Parity pin 123->131 methods / 16\nnamespaces (intermediate; F2 lands 135/16 once search/messaging land).",
"is_bot": false,
"headline": "feat(companies): add company-insights + Beta company-inbox methods",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T19:48:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bd0097c63754c0fb31f2fc505218b4679a220041",
"body": "…/F1)\n\nUnreleased section documenting the three new account-scoped read namespaces\n(8 methods total); additive and non-breaking. F2/F3 extend this section.",
"is_bot": false,
"headline": "docs(changelog): note the additive profile/groups/feed namespaces (M2…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T19:30:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "eb4eeff4a25f78daf33015737f57e6b53ebf58be",
"body": "New feed namespace on client.account(id).feed — home() reads the connected\naccount's LinkedIn home feed as agent-actionable posts (api/019 FR-001), two\nsort orders on one endpoint, unbounded cursor-walked stream. Account-scoped\nonly. Completes M2/F1: parity pin 122->123 methods / 15->16 namespaces (F1\nfinal; notifications/saved-posts/companies-followers land in F2/F3).",
"is_bot": false,
"headline": "feat(feed): add account-scoped feed namespace (home read)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T19:28:11Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1c22c6b055fa28652e8ae3d0e9e9c48121195094",
"body": "New groups namespace on client.account(id).groups — list (own groups, or\nanother member's via {profile}), get (single group detail), members (roster,\nwith the folded-in {name} search) — per api/022. Account-scoped only; group\nids interpolate into the path leading with account_id. Parity pin 119->122\nmethods / 14->15 namespaces (intermediate; F1 lands 123/16).",
"is_bot": false,
"headline": "feat(groups): add account-scoped groups namespace (3 methods)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T19:24:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ea0e7f6b72c7ee922b2d5e3fda818a96867c3de2",
"body": "New profile namespace on client.account(id).profile — subscription,\nanalytics, visitors, ssi — each a self-read of the connected account's own\nLinkedIn insight surface (api/017). Account-scoped only, mirroring\ncompanies/users; never mounted on the root client. Types alias off the\nregenerated OpenAPI snapshot. Parity pin 115->119 methods / 13->14 namespaces\n(intermediate; F1 lands 123/16).",
"is_bot": false,
"headline": "feat(profile): add account-scoped profile insights namespace (4 methods)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T19:21:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "858f8da417bf7274419cbb124df2b00351d2a0db",
"body": "…ints\n\nRe-snapshot fixtures/openapi.json from the served spec (90->115 paths,\n115->141 operations) and regenerate src/generated/types.ts. Adds the paths\nfor the M2 profile/groups/feed/notifications/companies/search/messaging/posts\nsurfaces; resource classes for the first three namespaces follow. check:types\ngreen; vendor-name grep clean.",
"is_bot": false,
"headline": "chore(types): refresh OpenAPI fixture + regenerate types for M2 endpo…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-15T19:17:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b3c747ab90c4005f17f832cb6739eefcedf34386",
"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.\n\nAlso reword the .gitignore comment explaining why the generated types\nare committed, dropping an internal reference that had slipped into\npublic view.",
"is_bot": false,
"headline": "chore(hygiene): scan dotfiles in check-clean; reword .gitignore comment",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-13T11:08:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a0dd1d65f464062493d006f76d08ddce3caa6442",
"body": "Co-authored-by: Raphael Redmer <ra.redmer@outlook.com>",
"is_bot": false,
"headline": "revert: drop unused RATE_LIMIT_INGRESS error code (#8)",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-07-12T17:37:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "dcc09fd0bc2e4054a5e7cc1cb8fde3eee7baaf87",
"body": "Co-authored-by: Raphael Redmer <ra.redmer@outlook.com>",
"is_bot": false,
"headline": "feat: add RATE_LIMIT_INGRESS error code (#7)",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-07-12T15:00:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "cea5862e162750032625f3bae43e8a291a75bc83",
"body": "…15.0",
"is_bot": false,
"headline": "docs(changelog): note the users.update description-strip fix under 0.…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T10:48:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "85b61cd466b08accb97589480cc78ddfcad42407",
"body": "UserUpdateBody never declared description, so a typed caller was already\nrejected at compile time — but an untyped/JS caller (or an as-cast) could\nstill put it on the object, and update() forwarded the body verbatim with\nno runtime check. Strip description from the outgoing payload before the\nreques\n[…]\ner the strip existed. It now sends a raw, untyped object literal\ncarrying description alongside legitimate keys and asserts the captured\nrequest body omits it while still carrying the legitimate keys.",
"is_bot": false,
"headline": "fix(users): strip a smuggled description key from update() at runtime",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T10:48:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "770b6e56410d53e190c68195d7ba1c1167d7626d",
"body": null,
"is_bot": false,
"headline": "docs(changelog): note the RATE_LIMITED decode fix under 0.15.0",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T08:58:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6f8df44757adda7a4bfce5a13816fe0c3aa98bae",
"body": "RequiredTier (errors.ts) and the transport's local REQUIRED_TIERS runtime\nset (transport.ts) were a hand-mirrored union+Set pair, identical today\nbut able to silently drift apart — the same class of bug ERROR_CODES /\nKNOWN_ERROR_CODES already closed off. Introduces REQUIRED_TIERS as the\nsingle sourc\n[…]\nD_TIERS\n(exported from errors.ts, replacing transport.ts's private copy) are both\nderived from it. Pure refactor — the four tier values are unchanged, and\nthe public RequiredTier export is unaffected.",
"is_bot": false,
"headline": "refactor(errors): derive RequiredTier from a single-source array",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T08:58:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c0048f23892b669b34584fe9678766391999230f",
"body": "The 429 the Recruiter and Sales Navigator read surface returns under\nLinkedIn-platform throttling (dedicated RateLimit-Policy / RateLimit /\nRetry-After response headers, retry_likely_to_succeed: true) is a real,\ndocumented error code — deliberately self-referenced in the served docs\nthe same way ACC\n[…]\nf\nevery error code the served OpenAPI document self-documents, so a future\nserver code that reaches the public docs fails the SDK suite until the\ntaxonomy learns it — the same class of gap this fixes.",
"is_bot": false,
"headline": "fix(errors): decode RATE_LIMITED instead of downgrading to INTERNAL",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T08:57:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5fe2668dbb53c525fa29b27dadc3f85a2abbac1b",
"body": "Fixture was pinned to a stale served surface. Refreshed from the live\nstaging document (path/op counts unchanged at 90/115): the following-op\ngained a 422 LINKEDIN_OPERATION_NOT_SUPPORTED example and a self-only\nuser_id description, the user-profile op's skills-section items now\ndocument endorsement\n[…]\n the\nendorse-skill op's description states the same precondition. Purely\nadditive description/example text plus a widened (non-breaking) skills\nitem shape — no path, method, or request-schema changes.",
"is_bot": false,
"headline": "chore(sdk): refresh OpenAPI fixture + regen generated types",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T08:38:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "40496deca483c372113f94e64e49e63e3d9bf133",
"body": "…r 0.15.0",
"is_bot": false,
"headline": "docs(changelog): note the CONNECTION_REQUEST_CONFLICT decode fix unde…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T08:28:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0dd3580c33123ccb2cecb4aa802eb6c976535489",
"body": "…g to INTERNAL\n\nThe runtime error-code set and the ErrorCode type were maintained as two\nindependent hand-written lists. CONNECTION_REQUEST_CONFLICT — a real 409 the\nAPI returns when a connect-request to a member already exists — was in\nneither, so the transport silently downgraded it to INTERNAL. E\n[…]\nver drift again. Add exhaustive per-code decode coverage, an\nexplicit CONNECTION_REQUEST_CONFLICT round-trip test, an unknown-code negative\ncontrol, and a compile-time lock on the type/array equality.",
"is_bot": false,
"headline": "fix(errors): decode CONNECTION_REQUEST_CONFLICT instead of downgradin…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T08:26:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f119bd859e3a41199e417c8ecf9db87f5cb9bbda",
"body": "Server ships this 422 for a permanent LinkedIn platform limitation on\nthe attempted operation (e.g. listing a non-self user's following\nlist) — user-fixable is false in the sense the operation can't be\nretried into success, so retry_likely_to_succeed is false. Added to\nthe ErrorCode union and the transport's known-code set so it decodes\nto its own code instead of falling back to the retryable INTERNAL.",
"is_bot": false,
"headline": "feat(errors): add LINKEDIN_OPERATION_NOT_SUPPORTED error code",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T06:59:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "508afc0aada9163d820d3f84f02565eb86a922d6",
"body": "accounts.link -> auth.intent (prose), profiles.get -> users.get('me'/id),\ndrop an unverifiable field from the pagination example, bump status to 0.15.0.",
"is_bot": false,
"headline": "docs(sdk): realign README examples to the v2 users/auth surface",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T00:05:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "008dfb05faa1db09c0916da4bc7ede444a87e331",
"body": "Document every breaking category — 14 removals, 3 namespace renames/splits, 11\nmethod rename/relocations, the 6 stale-shape + new write-body reshapes, and the\naccount-first path-grammar migration — plus the new surface (comments, jobs\nwrites, project-centric recruiter, follow/update/markChatRead/fromUrl/delete).\nStage package version at 0.15.0 (not published).",
"is_bot": false,
"headline": "docs(sdk): changelog 0.15.0 v2-parity; stage version 0.15.0",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T00:03:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c33349ac3ecc46bfea6b73beadb9d72c9a3982e1",
"body": "…ces)\n\nTable-driven set-equality per namespace (extra/missing method fails by name),\nroot/account mounting guards, total==115, and a compile-time @ts-expect-error\nblock proving the 14 removed methods + the split respond are gone.",
"is_bot": false,
"headline": "test(sdk): add public-surface bijection test (115 methods, 13 namespa…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-11T00:01:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "aacc1a96c73cf93806419e7d1601357d28ccb6b6",
"body": "….getProjectJob\n\n- recruiter.listProjectJobs -> getProjectJob (op returns a single posting)\n- root client mounts exactly {accounts, auth, webhooks}; account(id) mounts the\n 10 account-scoped namespaces only. buildAccountScopedNamespaces no longer\n leaks webhooks; add buildRootNamespaces/RootNamespaces for the root half.\n- transport: drop unused catch binding",
"is_bot": false,
"headline": "refactor(sdk): enforce root/account namespace split; rename recruiter…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T23:59:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2a8247e607d1f25d5a6350f2349a144f0664c892",
"body": "Append 14 representative account-first rows for the recruiter namespace to\nthe shared table-driven grammar bank — covering every distinct path shape:\nid-GET (getProfile), POST (startChat, searchParameters — the was-GET reshape,\nsearchFromUrl), PATCH (updateProject), deep project-scoped GET/POST\n(sea\n[…]\neateProjectJob, getProjectJobBudget), the client-side\nresolved getJob, the deepest publish path, bodyless closeJob, the pipeline\ncandidate-save POST, listApplicants, and the binary downloadResume GET.",
"is_bot": false,
"headline": "test(resources): add recruiter rows to the path-grammar bank",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T23:50:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e3136170fe792a78ec9bba6a7f4b4788ead27d86",
"body": "Rebuild the recruiter namespace against the v2 served surface: account-first\npath grammar (account_id is the leading /v1/ segment, never query/body), 10\nrealigns, 3 reshapes, 9 new project-centric ops. startChat is now JSON-only\n(signature + subject required, base64 attachments in-body — no multipar\n[…]\nlveJobCheckpoint; addCandidate renamed to saveCandidate.\n\nReplaces the stale test/resources.recruiter.test.ts with a per-resource\ntest/resources/recruiter.test.ts (29 wire tests, path + body + query).",
"is_bot": false,
"headline": "refactor(recruiter): project-centric rebuild — 23 account-first methods",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T23:48:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3558bd9d75a40edc3ee318e5970dbc1b43001d7a",
"body": "10 methods: list, create, get (realign — account-first path, id/URL\nclient-side resolution preserved), update, getBudget, publish, close,\nlistApplicants, getApplicant, downloadResume. account_id is now the\nleading /v1/ path segment. list's state query param is required.\ncreate/update's job_title/com\n[…]\nst.ts to\ntest/resources/jobs.test.ts (established convention) with fixtures\nupdated for the new job_posting response shape (company is now an\nobject; applicants_counter renamed to applications_count).",
"is_bot": false,
"headline": "refactor(jobs): realign get to account-first, add 9 new methods",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T23:34:34Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cc45e9712eddddff8d122907c10532cf8731305e",
"body": "listUserComments, create, edit, delete, reply, listReplies,\nlistReactions, addReaction, removeReaction. account_id is the leading\n/v1/ path segment on every request. create relocates from\nposts.comment; listUserComments relocates from profiles.listComments\n(both realigns, not new). reply shares its \n[…]\nE-with-body: DELETE .../comments/{comment_id}/reactions carries\n{reaction}, same unified lowercase enum as posts.react/unreact. Wired\ninto the namespace bag (index.ts) and the root client (client.ts).",
"is_bot": false,
"headline": "feat(comments): add new comments namespace (9 methods)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T23:30:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4ec271a948ff59113777499a3846504fdaf8a422",
"body": "…chFromUrl\n\n12 methods: searchPeople, searchCompanies, getParameters, startChat,\ngetProfile, accountLists, leadLists, browseAccountList, browseLeadList,\nsaveAccount, saveLead, searchFromUrl (new — POST .../sales-navigator/search\nbody {url}). account_id is now the leading /v1/ path segment on every\nr\n[…]\nJSON objects. saveAccount /\nsaveLead bodies shrink to just their own field ({company_id} / {user_id})\nnow that account_id lives in the path, not the body. Removed: syncMessages\n(no served equivalent).",
"is_bot": false,
"headline": "refactor(sales-navigator): realign to account-first grammar, add sear…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T23:21:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1d3339d3d6b3ef58c44ba26e70953e315af007f2",
"body": "9 methods: listComments, get, delete (new — bodyless, 204), create,\nlistUserPosts, listReactions, react, unreact (new — DELETE-with-body\n{reaction}), listUserReactions. account_id is now the leading /v1/ path\nsegment on every request. create drops multipart entirely — the served\nsurface has zero mul\n[…]\nnot new). The\ncomment-write surface (comment, comment editing) relocates to the\nupcoming comments namespace — listComments (a post's own comment read)\nstays here. Removed: list (no served equivalent).",
"is_bot": false,
"headline": "refactor(posts): realign to account-first grammar, add delete/unreact",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T23:18:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "078e001113ce2b448a6087701cb00838cac404fc",
"body": "…line\n\n6 methods: send, listSent, listReceived, accept, decline, cancel.\naccount_id is now the leading /v1/ path segment on every request. The\nold combined respond(invitationId, {action}) splits into two dedicated,\nbodyless POSTs matching the served surface — accept and decline — each\nissuing .../invites/received/{invitation_id}/{accept|decline} with no\nrequest body. respond is removed. cancel realigns to DELETE\n.../invites/sent/{invitation_id}, also bodyless.",
"is_bot": false,
"headline": "refactor(invites): realign to account-first grammar, split accept/dec…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T23:08:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "649d2095e85d8f7329526db2d204bc1136596a9d",
"body": "12 methods: listChats, startChat, getChat, markChatRead (new — PATCH\n.../chats/{chat_id} body {read}), listMessages, sendMessage, getMessage,\neditMessage, deleteMessage, addReaction, getAttachment, sendInMail.\naccount_id is now the leading /v1/ path segment on every request.\ngetMessage/editMessage/d\n[…]\nvel as base64 JSON objects, never multipart — the served\nsurface has zero multipart ops. Removed: syncChat, syncMessages (no\nserved equivalent); getInMailBalance (relocated to users.getInMailCredits).",
"is_bot": false,
"headline": "refactor(messaging): realign to account-first grammar, add markChatRead",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T23:08:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0339aacbe6be4cb2ffa52ac44875fdc269b5bdeb",
"body": "6 methods: getParameters, people, companies, posts, jobs (all realigned),\nplus new fromUrl (POST /v1/{account_id}/search body {url}) — the sole\nhome of URL-mode search now that the structured endpoints no longer\naccept a url field. Pagination (offset/limit/cursor) stays a top-level\nquery param on every op, split out of the merged body+pagination\nargument on the wire. Completes the path-grammar bank and paginate\nwiring for the users/companies/search chunk.",
"is_bot": false,
"headline": "refactor(search): realign to account-first grammar, add fromUrl",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T22:58:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d600b2f429c6f04f6d32f58cb54cae219bafbdd2",
"body": "4 methods: get, employees, posts, jobs. account_id moves from a query\nparam to the leading /v1/ path segment, fixing the pre-existing\ncompanies.get query-param-injection test failure. followers has no\nserved equivalent and is removed; get()'s follower_count is the\naudience-size signal that replaces it.",
"is_bot": false,
"headline": "refactor(companies): realign to account-first grammar, drop followers",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T22:57:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fff0e9ee4fd49ad2352e86e8103edd059e9976ad",
"body": "…mmar\n\n9 methods: get (folds getMe via 'me' sentinel), update, listRelations,\nlistFollowers, listFollowing, follow, unfollow, getInMailCredits\n(relocated from messaging), endorseSkill (body key endorsement_id, was\nskill_endorsement_id). account_id is now the leading /v1/ path segment\non every request, never a query param.",
"is_bot": false,
"headline": "refactor(users): rename profiles->users, realign to account-first gra…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T22:56:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d12e9d5c02fc3d633a728b7b23da3c60ca78b6ce",
"body": "Proves, at the resource-wrapper level, that a root-scoped method builds a URL\nwith no account segment and that account_id never leaks into the query\nstring — for accounts/auth/webhooks, the namespaces realigned so far. The\nseam itself is already proven directly against createContext in\ntest/internal\n[…]\nnner, with an inline\nexample showing the account-scoped row shape, so later resource realignments\n(messaging, users, recruiter, sales navigator, ...) append their own rows\nwithout touching the runner.",
"is_bot": false,
"headline": "test(resources): add the table-driven path-grammar bank",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T22:39:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5a45b97c19f99cb1cd6ba08e8a7f9b8afd2cde03",
"body": "The 6 remaining webhooks ops (create/list/listEvents/get/update/delete) were\nalready aligned to the served snapshot; only getStateDiff had no matching\npath in the regenerated types. The whole-SDK method-count coverage test\nmoves out of this file (it now only asserts webhooks' own 6-method surface)\nsince the cross-namespace bijection is inherently a moving target until every\nnamespace realigns — a dedicated parity test picks that up.",
"is_bot": false,
"headline": "fix(webhooks): remove getStateDiff — no served equivalent",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T22:38:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "886f98daf690d77e07923a1821aabadee0e8591c",
"body": "…scoped auth namespace\n\naccounts keeps its 4 aligned ops (list/get/update/disconnect). The 5\nconnect/checkpoint ops (link, solveCheckpoint, requestCheckpoint,\npollCheckpoint, getConnectSession) move to a new root-scoped auth namespace,\nre-keyed to the served /v1/auth/* paths. link and reconnect merg\n[…]\nnticates an existing\naccount in place via auth.intent({ account_id, ... }).\n\nauth is wired as root-only: buildAccountScopedNamespaces now strips both\naccounts and auth out of the account(id) accessor.",
"is_bot": false,
"headline": "feat(auth): split connect/checkpoint ops out of accounts into a root-…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T22:36:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "971d9eec326264112efa48d622972d34e1596f6a",
"body": "… 115 ops)\n\nReplace `fixtures/openapi.json` with the current served OpenAPI (staging,\ndeep-equal to the live `/.well-known/openapi.json` — verified byte-for-byte),\nand regenerate `src/generated/types.ts` from it via `gen:types:fixture`. The\nfixture is written pretty-printed (`JSON.stringify(doc, nul\n[…]\naccount-first realignment owned by the later chunks. This regen\ncommit's own scope (fixture + generated types) is coherent and clean; the\npackage returns to whole-tree green when the wrappers realign.",
"is_bot": false,
"headline": "chore(generated): regen types from the v2 served snapshot (90 paths /…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T22:22:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "840dbd0b6a4bd0a5e8f218c41590393f76d13297",
"body": "…seam\n\nMove `account_id` from a query/body/`none` field into the leading `/v1/`\npath segment. An account-scoped method now declares its path template with a\nliteral `{account_id}` placeholder; the bound `createContext(config, id)`\nsubstitutes the fixed id into it. Query and body are forwarded to the\n[…]\ne final chunk returns the whole package to green. This foundation\ncommit's own scope (context seam + its test) is green: targeted vitest 18/18,\ncheck:clean OK. Zero tsc errors in the foundation files.",
"is_bot": false,
"headline": "feat(internal): account-first path grammar; retire AccountIdLocation …",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-10T22:21:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "92780b68ea26c24a5edcb23c95459d227c5d233a",
"body": "…nt-count description\n\nconstructEvent's JSDoc and both code examples (Express, Hono) named the\nsignature header X-Curviate-Signature; the dispatcher actually sends\nCurviate-Signature (curviate-signature on req.headers), so integrators\ncopying the examples verbatim got undefined. Also corrects the ge\n[…]\n\"default: all 11 lifecycle events\", matching the account_status catalogue\n(fixture + generated types kept in sync; check:types drift gate green).\n\n0.14.1 patch, docs-only — no runtime behavior change.",
"is_bot": false,
"headline": "fix(webhooks): docs patch — correct signature header name + stale eve…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-07T03:17:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7f89c16cf0583eba1d7712a71f254f33b47ecfcf",
"body": "…0.14.0)\n\nRegenerates types.ts from the W2 OpenAPI (surgical patch, webhook paths only)\nand adds webhooks.get(id) for the net-new GET /v1/webhooks/{id}. Re-keys\nCurviateEvent 19->24 deliverable events to match the create-subscribable\ncatalogue (messaging 8, user 2, account_status 14), pinned at comp\n[…]\nerated create-variant `events`\n enums, plus @ts-expect-error negatives for all 7 removed names.\n- Method-count coverage guard bumped 93->94.\n- README/CHANGELOG/package.json version updated to 0.14.0.",
"is_bot": false,
"headline": "feat(webhooks): v2 catalogue cascade — get() + CurviateEvent re-key (…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-07T00:18:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "791289551edfbe9f02995806d1047f7e0870f580",
"body": "The server's W7 409 duplicate-connect code (accounts.link/reconnect/\nsolveCheckpoint) was missing from the hand-maintained ErrorCode union and\ntransport's KNOWN_CODES set, so toErrorCode() silently narrowed it to\nINTERNAL — which is also in RETRYABLE_CODES, so a client would retry a\nrequest that can\n[…]\n RESOURCE_ACCESS_RESTRICTED in 0.12.0.\n\nAlso notes the 422 checkpoint challenge_type (captcha | phone_register)\nas typed-generic in the changelog (documented in prose, no typed field\nyet on the wire).",
"is_bot": false,
"headline": "fix(errors): add ACCOUNT_ALREADY_LINKED to the ErrorCode surface",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-06T14:44:31Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "dccff61f37d09ffc3cc90ec6a29dc1a04bca9153",
"body": "Regenerate types from the current merged server OpenAPI (emitted locally\nfrom the worktree server) to pick up the connect-fix round's additive,\nnon-breaking response fields:\n\n- `recovered?: boolean` on the accounts.link() and accounts.solveCheckpoint()\n 201 responses — true only when the connect re\n[…]\ne new\nfields; adds pass-through + type-surface tests; CHANGELOG under 0.13.0.\nAccompanying request/response description improvements already merged into\nthe server ride along in the regenerated types.",
"is_bot": false,
"headline": "feat(accounts): regen types for connect-fix response fields",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-06T14:17:21Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "52a8451f2de2d7841dca9ae246cbce42f21fa8e1",
"body": "Server-side fix (campaign feat/v2-migration-w1 @ 360747f2) makes the served\nOpenAPI express nullability on PATCH /v1/accounts/{id}'s proxy property and\nPATCH /v1/webhooks/{id}'s name property (both genuinely `.nullable()` at\nruntime). Regenerated by surgically adding `nullable: true` to exactly thos\n[…]\ng gen:types:fixture.\n\nAccountUpdateBody.proxy and the webhooks update body's name now carry `| null`\nin the generated type, matching the runtime schema. No version bump — 0.13.0\nunpublished amendment.",
"is_bot": false,
"headline": "chore(sdk): regen types — PATCH proxy now nullable",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-05T21:37:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bcde9d2a15a7dedaf0f4e0dbc78a6cf54f36bf6d",
"body": null,
"is_bot": false,
"headline": "chore(release): 0.13.0",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-05T20:48:12Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8042c182caa14b190ec6666ca06869b1ad1de561",
"body": "Checkpoint operations move account-in-path: solveCheckpoint(id, { code }),\nrequestCheckpoint(id), and pollCheckpoint(id) replace the old\nsubmit/resend/poll methods that carried account_id in the body. connect-link\nbecomes create-only; new createReconnectLink(id, body?) mints a hosted\nre-auth link. u\n[…]\n Types regenerated from\nthe current API surface.\n\nBREAKING CHANGE: submitCheckpoint, resendCheckpoint, and refresh are removed;\npollCheckpoint and update change signature; connect-link is create-only.",
"is_bot": false,
"headline": "feat(accounts): v2 accounts/auth surface reshape",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-05T20:48:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "051d00d6a48370918416c573a77f7ce0cd48c3f7",
"body": null,
"is_bot": false,
"headline": "chore(release): 0.12.0",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-05T05:57:05Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f450a27fa83e3a87e6ac5c11ae16c9a91348b5ce",
"body": "…king saveLead re-signature\n\nFixture-surgical regen of fixtures/openapi.json + src/generated/types.ts\n(the six new /v1/sales-navigator/{account-lists,lead-lists}... paths; the\nretired POST /v1/sales-navigator/leads/{user_id} removed, no alias).\n\nAdds accountLists/leadLists/browseAccountList/browseLe\n[…]\ne v2\nsave-lead surface: saveLead(userId, body) -> saveLead({ list_id, user_id,\naccount_id }) against POST /v1/sales-navigator/lead-lists/{list_id}/save\n(BREAKING, no alias — list_id is now mandatory).",
"is_bot": false,
"headline": "feat(sales-navigator): v2 list-surface cascade — 5 new methods + brea…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-05T01:26:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c77fcbb2959e583a9e303c5903e22f15cf15dbda",
"body": "The server added this code for the companies.followers() non-admin mapping\nbut it was missing from the SDK's ErrorCode union and the transport's known-\ncode set, so it would have silently narrowed to INTERNAL on the wire.",
"is_bot": false,
"headline": "feat(errors): add RESOURCE_ACCESS_RESTRICTED error code",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-04T23:54:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fcdad8c8bc389f283bfd5874a64bbfd317f6ef2c",
"body": "…les.getCompany\n\nNew companies namespace (get/employees/posts/jobs/followers) mirrors the\nserver's new Companies REST group. profiles.getCompany is removed (BREAKING) —\nits endpoint was hard-moved with no alias, so this is the intended compile-time\nsignal at call sites. Types regenerated from the campaign server's OpenAPI\ndocument, patched surgically into fixtures/openapi.json (verified: only the\n5 added + 1 removed companies paths differ, no sibling drift).",
"is_bot": false,
"headline": "feat(companies): add companies resource (5 methods) — hard-move profi…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-04T23:39:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9e47f2bb13b10d3d839166e1a9c43b2cf6d0d477",
"body": "Wholesale type regen from the current OpenAPI surface plus the hosted\nconnect-session poll method, bringing the SDK current with the full\naccounts-overhaul surface:\n\n- accounts.getConnectSession(session_id) — poll a hosted connect session\n minted by createConnectLink(); returns status + account_id \n[…]\ntatus on list, get, and both sides of state-diff\n (previous_status/current_status now typed enums)\n- 501 response variant on accounts.update()\n\nPublic method surface 83 -> 84. Version already 0.11.0.",
"is_bot": false,
"headline": "feat(accounts): full accounts-overhaul regen + getConnectSession()",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-04T17:41:45Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f13d51172a686d9185e424c505f5a07f6cb64a64",
"body": "New accounts.resendCheckpoint({ account_id }) re-sends the pending\nverification challenge notification for a connect in progress. Returns\n{ object, account_id, resent } — resent echoes the substrate outcome\nhonestly (false when the challenge type has nothing to re-send; never\nthrows just for that). \n[…]\ny.\n\nTypes generated from a surgical fixture patch (the one new path only,\ndiff-confirmed against the fixture — no sibling drift). Extends the\nAccounts surface to 11 methods (83 total). Bump to 0.11.0.",
"is_bot": false,
"headline": "feat(accounts): add accounts.resendCheckpoint() — checkpoint resend",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-04T13:55:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9b8b9306453f98a99f3205a5c2e09d28725495e1",
"body": "…eve (#373)\n\nNew `jobs` namespace: jobs.get(jobIdOrUrl, query?) retrieves one public\nLinkedIn job posting's full detail, accepting either a bare numeric id or a\nfull job URL (the id is extracted client-side; the wire request always\ncarries the numeric id). Throws a client-side INVALID_REQUEST error\n\n[…]\nition), extending\nthe Recruiter surface to 18 methods.\n\nRegenerated types from a surgical fixture patch (the two new paths only,\ndiff-confirmed against the fixture — no sibling drift). Bump to 0.10.0.",
"is_bot": false,
"headline": "feat(jobs): add jobs.get() and recruiter.getJob() — job-posting retri…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-03T18:09:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e7dcf7b4e2c09df2b19c46670a0f26235e42881a",
"body": "…ics (rides 0.9.0)\n\nRegenerated from the current API surface: quotas[] and\nrecommended_throttle_hint descriptions now state the advisory\ncontract (daily families never reject; only account.per_minute is a\nbinding limit enforced with HTTP 429). JSDoc-only, no shape change.",
"is_bot": false,
"headline": "docs(quotas): advisory usage-safety framing on quotas[] + hint semant…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-03T15:00:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "335156240ebce4c9f85a34fa4675e241ca56ae7c",
"body": "…t (0.9.0) (#6)\n\nRegenerate types from the accounts endpoints only (scope-guarded diff\nconfirmed no other path drifted): username, premium_id, public_identifier,\nsubstrate_created_at, signatures, groups on both accounts.list() items and\naccounts.get(); seat_id added to accounts.get(). connected_at/last_checked_at\nnow consistently ISO-8601 UTC. All additive; no method signature changes.\n\nCo-authored-by: Raphael Redmer <ra.redmer@outlook.com>",
"is_bot": false,
"headline": "feat(accounts): account enrichment fields on list/get + seat_id on ge…",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-07-03T12:09:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f4d102bc9c00502a61fa32c4c2b2bb92a5a1e1bb",
"body": "…cumented",
"is_bot": false,
"headline": "release: 0.8.0 — recruiter job-lifecycle wired, search guard-rails do…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-02T16:22:50Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fccbdb80e54d37864e23b9a679cd7029d3ff9339",
"body": null,
"is_bot": false,
"headline": "docs: flag annual_revenue enum narrowing as breaking for typed consumers",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-02T16:22:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "139051b634b14a525f9e55eba312c030bb36b99c",
"body": "Recruiter job-lifecycle endpoints are fully implemented server-side\n(501 removed), richer parameter docs and surfaced defaults, and\nsearch filter guard-rail documentation (companies limit, jobs\nbenefits/commitments, people open_to, posts filter examples, SN\nrevenue buckets). No method signature changes.",
"is_bot": false,
"headline": "chore: bump version 0.7.0 -> 0.8.0",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-02T16:06:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e4413493767e6d7db35fdb07ae2d5ae3fe57b1d5",
"body": "Recruiter job-lifecycle endpoints are now fully implemented server-side\n(501 stub responses removed), parameter documentation is richer across\nrecruiter/search surfaces, server-side defaults are now surfaced in\nJSDoc, and the Sales Navigator company revenue filter is now a bucketed\nenum. Search filt\n[…]\nn is also reflected: company\nsearch minimum page size, valid values for jobs benefits/commitments and\npeople open_to, and corrected post-search filter examples.\n\nNo resource method signatures changed.",
"is_bot": false,
"headline": "chore: regenerate types from live API surface",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-02T16:06:08Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b81cc10b5bbb645935010155c372987a3ac04280",
"body": "BREAKING (typed consumers): recruiter.startChat 201 response drops\nattendee_ids and returns message_id (the opening message id), matching\nmessaging.startChat / salesNavigator.startChat. chat_id is now non-nullable\non a 201. Regenerated types from the updated recruiter chats path; request\nbody unchanged. Migration: read res.message_id.",
"is_bot": false,
"headline": "feat(sdk): align recruiter start-chat response to message_id (0.7.0)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-01T20:33:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "aa074d202ee89113546a51da2adcf9ef017be5fe",
"body": "…hes CHANGELOG + CLI dep)",
"is_bot": false,
"headline": "chore: bump version 0.5.0 -> 0.6.0 (SN/Recruiter parity release; matc…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-01T19:25:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1f947d94641725d484c01dfa0d4e0414a99ef363",
"body": "…ter start-chat field rename + object discriminator\n\nBREAKING (typed consumers):\n- salesNavigator.syncMessages + recruiter.syncMessages: response sync_status -> status\n- recruiter.startChat request: attendee_ids -> attendees_ids (response attendee_ids unchanged)\n- recruiter.startChat response: gains object:\"chat_started\" discriminator, drops quota field",
"is_bot": false,
"headline": "feat(sdk): SN/Recruiter messaging parity — sync status rename, recrui…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-01T19:05:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "df837cd64c347a96f37e5d527f71158e6b10c017",
"body": "… (0.5.0)\n\nRegenerate types from the current API surface:\n- people search: connections_of / followers_of are now string[] (arrays of\n opaque member IDs) instead of a single string\n- posts search: nested posted_by / mentioning / author filter objects replace\n the flat member_urn / company_urn field\n[…]\naries in the SDK JSDoc.\n\nBREAKING CHANGE: connections_of/followers_of (string -> string[]),\nlocation_within_area (string -> number), and the posts filter shape change\nare breaking for typed consumers.",
"is_bot": false,
"headline": "feat(search): v2 search request/response types + de-branded summaries…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-01T15:29:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1dd97515b0cb6f0b96c9ea8697a27e5ccf80d470",
"body": "chore(release): @curviate/sdk 0.4.2 — reintegrate invites specifics.provider + 422 drop (regression fix)",
"is_bot": false,
"headline": "Merge pull request #5 from Curviate/chore/sdk-0.4.2-invites-reintegrate",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-07-01T10:09:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "67fdea4c0c43f75f39afb78ed0833e221cbd5e54",
"body": "…rovider + cancel/handle 422 drop\n\nReconciles two lines that diverged off 0.4.0: 0.4.1 (people-search id) and\nmain (6d41863 — invites specifics.provider + cancel/handle 422 drop). The 0.4.1\nrelease was cut off 0.4.0 and bypassed the invites types, dropping them from the\npublished/gitlinked SDK; this\n[…]\nfull superset: invites specifics.provider (sent+received), people-\nsearch id, and profile primary_locale + messaging status rename all present.\nVerified: check:types OK, check:clean OK, tsup build OK.",
"is_bot": false,
"headline": "chore(release): @curviate/sdk 0.4.2 — reintegrate invites specifics.p…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-07-01T10:05:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "15b6fa32066f9966b3cdd0c9e8cbdfb813ab7cee",
"body": "Adds `id: string` (raw LinkedIn provider id, ACoAA… format) as the first\nproperty on the `people_search_result` item type. Regenerated from the\nupdated OpenAPI fixture (search-people id + limit-description trim on all\n4 search ops). No invites/messaging/recruiter/501 changes.\n\nBump 0.4.0 → 0.4.1 (additive patch).",
"is_bot": false,
"headline": "feat(types): people search item — add id field (0.4.1)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-06-30T19:21:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6d41863c99b4837ce973456fe27c81fffe0ece38",
"body": "…vider + cancel/handle 422 drop (#3)\n\nAdds specifics.provider:\"LINKEDIN\" to InvitationSent/InvitationReceived item\nschemas, and removes the 422 response from the cancel and handle operations\n(both reflect the merged API surface). Regenerated on top of the current 0.4.0\ntypes via gen:types --fixture; diff is invites-only.\n\nCo-authored-by: Raphael Redmer <ra.redmer@outlook.com>",
"is_bot": false,
"headline": "chore(types): regenerate from staging OpenAPI — invites specifics.pro…",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-06-30T18:15:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "71d5066021e163a75b4a5f806589f6283b539dc6",
"body": "…d rename (0.4.0)\n\nRegenerated types from the merged API: adds primary_locale ({country,language}|null)\non Profile and OwnProfile; renames GET /v1/messages/sync response field sync_status to\nstatus (SN/Recruiter re-sync unchanged); neutral endpoint/error descriptions. Part of #335.",
"is_bot": false,
"headline": "feat: primary_locale on Profile/OwnProfile + account-sync status fiel…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-06-30T12:59:08Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fcb34295418647785100a47003b140333adc8a4c",
"body": "Widen sendInMail surface union to sales_nav | recruiter | classic and\naccept a member URN or provider id for recipient_urn. Regenerated types\nfrom the current API reference (also refreshes stale endpoint\ndescriptions). Bumps to 0.3.0 (additive).",
"is_bot": false,
"headline": "feat(messaging): accept classic InMail surface (#328)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-06-29T19:11:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f9d765e0acd0cd631c85a4d08f876114365833ee",
"body": "…n (0.2.1) (#2)\n\n* fix(sdk): stop injecting account_id on deleteMessage/addReaction (#324)\n\nBoth methods set accountIdIn:'none' — the server resolves the owning account\nserver-side from the message id, so the SDK must not inject account_id into\nquery or body. Adds AccountIdLocation:'none' branch to createContext. Bumps\nto 0.2.1 (patch); CHANGELOG updated.\n\n* chore(sdk): strip internal issue/spec refs for public repo (check-clean)\n\n---------\n\nCo-authored-by: Raphael Redmer <ra.redmer@outlook.com>",
"is_bot": false,
"headline": "fix(messaging): stop injecting account_id on deleteMessage/addReactio…",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-06-29T11:41:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "79eee0bfc96abaae27bff6aa170e5ae837026194",
"body": null,
"is_bot": false,
"headline": "chore: normalize repository.url to git+https (npm canonical)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-06-28T17:50:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3ebbb5e498e7fb0df8bdca8297d83241825c20a5",
"body": null,
"is_bot": false,
"headline": "chore(release): bump @curviate/sdk to 0.2.0",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-06-28T17:15:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b93cff6f713ab684ed4b614924bb034fec01c91d",
"body": "…lized OwnProfile, Chat subject (#1)\n\n* feat(transport): support array query params (repeated key serialization)\n\n* chore(types): regen from live server — is_premium/is_open_profile, linkedin_sections on getMe, Chat subject, OwnProfile enriched fields\n\n* feat(profiles): getMe accepts linkedin_sections; export ProfileGetMeParams; tests for is_premium/is_open_profile, enriched fields, Chat subject\n\n---------\n\nCo-authored-by: Raphael Redmer <ra.redmer@outlook.com>",
"is_bot": false,
"headline": "feat(profiles,chat): #319 SDK parity — getMe linkedin_sections, norma…",
"author_name": "Raphael",
"author_login": "rapha-red",
"committed_at": "2026-06-28T17:13:13Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "63c47cfe8382502f632fc496a623af6a0d0092bf",
"body": "The account-scoped context (`curviate.account(id)`) always injected\n`account_id` into the query string, regardless of the operation. That is\ncorrect for GET reads, body-less DELETEs, and filter-search POSTs (where\naccount_id is a documented query param), but wrong for account-scoped\nwrite requests t\n[…]\nnt.\n\nAdds a regression test asserting the wire location across namespaces:\nbody for JSON and multipart writes, query for reads, deletes, and search.\n\nBumps version to 0.1.1 and adds a CHANGELOG entry.",
"is_bot": false,
"headline": "fix: send account_id in the request body for account-scoped writes",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-06-22T18:10:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a446963ecfae9c36b918fca7b8321667a46bdd80",
"body": "…i-leak guard",
"is_bot": false,
"headline": "chore: anonymize internal references across the public repo + add ant…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-06-22T07:58:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ba621691c9b6c7589e5b7393bad2a2d305f8e1a7",
"body": null,
"is_bot": false,
"headline": "fix: default baseUrl -> https://api.curviate.com (app host 404s on /v1)",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-06-22T07:52:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "31d050bb73d89f2ee895edee2498b67f2db778fb",
"body": "…a fail)\n\nD1: account list items expose account_id, not id — fix every .id access on\naccount items (.account_id) and guard items? optional chain.\nD2: chat.last_message_text is not a real field — replace with chat.unread_count.\nD3: AccountListParams has no status param — remove { status: \"active\" } f\n[…]\n snippets into examples-check.ts, ran\ntsc --noEmit against strict tsconfig; confirmed zero errors. Deleted temp file.\npnpm test 150/150 green; grep -ri unipile exits clean; npm pack --dry-run 7 files.",
"is_bot": false,
"headline": "docs(sdk): fix README examples against real exported types (cycle-2 q…",
"author_name": "Raphael Redmer",
"author_login": "RaRedmer",
"committed_at": "2026-06-21T20:03:19Z",
"body_truncated": true,
"is_coding_agent": false
}
],
"releases_count": 12,
"commits_last_year": 125,
"latest_release_at": "2026-07-17T16:40:43Z",
"latest_release_tag": "sdk-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": 2
},
"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/sdk",
"exists": true,
"license": "MIT",
"keywords": [],
"ecosystem": "npm",
"matches_repo": false,
"registry_url": "https://www.npmjs.com/package/@curviate/sdk",
"is_deprecated": false,
"latest_version": "0.18.1",
"repository_url": "https://github.com/curviate/sdk",
"versions_count": 24,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": 1,
"monthly_downloads": 4056,
"first_published_at": "2026-06-22T11:34:30.425000Z",
"latest_published_at": "2026-07-18T10:07:28.907000Z",
"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": [
"fixtures/openapi.json"
],
"has_devcontainer": false,
"typecheck_configs": [
"tsconfig.json"
],
"toolchain_manifests": [],
"largest_source_bytes": 79415,
"source_files_sampled": 63,
"oversized_source_files": 1,
"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": "zod",
"manifest": "package.json",
"ecosystem": "npm",
"version_constraint": "^3.25.17"
}
],
"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": 11,
"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": 115,
"avatar_url": "https://avatars.githubusercontent.com/u/44050496?v=4"
},
{
"type": "User",
"login": "rapha-red",
"commits": 10,
"avatar_url": "https://avatars.githubusercontent.com/u/276905213?v=4"
}
],
"contributors_sampled": 2,
"top_contributor_share": 0.92
},
"quality_signals": {
"has_ci": false,
"has_tests": true,
"ci_workflows": [],
"has_docs_dir": false,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [],
"scorecard": {
"checks": [
{
"name": "Binary-Artifacts",
"score": 10,
"reason": "no binaries found in the repo",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
},
{
"name": "Branch-Protection",
"score": 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 3 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/7 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": 10,
"reason": "0 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "5855d2d476aee0212348d33509248591f132edea",
"ran_at": "2026-07-23T17:24:28Z",
"aggregate_score": 2.5,
"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:29Z",
"ci_last_conclusion": null,
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/Curviate/curviate-sdk",
"host": "github.com",
"name": "curviate-sdk",
"owner": "Curviate"
},
"metrics": {
"overall": {
"key": "overall",
"band": "at_risk",
"name": "Overall health",
"note": null,
"notes": [],
"value": 41,
"inputs": {
"security": 25,
"vitality": 75,
"community": 24,
"governance": 39,
"engineering": 34
},
"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": 125,
"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": "125 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 125
}
}
],
"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": 12,
"latest_release_tag": "sdk-v0.17.0",
"releases_from_tags": false,
"days_since_latest_release": 6,
"mean_days_between_releases": 2
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "12 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 12
}
}
],
"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 ~2 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 2
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "no releases found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "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": 39,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 14,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 2,
"top_contributor_share": 0.92
},
"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 92% of commits",
"points": 1.8,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 92
}
}
],
"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": 11,
"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": "11/11 decided PRs merged",
"points": 38.2,
"status": "met",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 11,
"decided": 11
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/7 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": 34,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "critical",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 24,
"inputs": {
"has_ci": false,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"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": null,
"points": 0,
"status": "missed",
"details": [],
"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 3 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": 25,
"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": 25,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 13,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 5,
"scorecard_aggregate": 2.5
},
"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 3 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/7 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": "0 existing vulnerabilities detected",
"points": 7.5,
"status": "met",
"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": "at_risk",
"name": "AI Readiness",
"value": 48,
"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": "at_risk",
"name": "Verify loop (build / test / typecheck)",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_pinned_dependencies"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 37,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [],
"has_dockerfile": false,
"typed_language": true,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": false,
"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": null,
"points": 0,
"status": "missed",
"details": [],
"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": null,
"points": 0,
"status": "missed",
"details": [],
"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": 99,
"inputs": {
"primary_language": "TypeScript",
"largest_source_bytes": 79415,
"source_files_sampled": 63,
"oversized_source_files": 1
},
"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": "1/63 source files over 60KB",
"points": 54.1,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 63,
"oversized": 1
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "at_risk",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"example_dirs": [],
"has_mcp_signal": false,
"api_schema_files": [
"fixtures/openapi.json"
]
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": "fixtures/openapi.json",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "fixtures/openapi.json"
}
}
],
"max_points": 40
},
{
"key": "mcp_server",
"name": "MCP server",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "runnable_examples",
"name": "Runnable examples",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 40
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"npm package '@curviate/sdk' points at a different repository (https://github.com/curviate/sdk); 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/sdk@0.18.1; advisories assessed against the repository dependency graph instead"
],
"report_type": "repository",
"generated_at": "2026-07-23T17:24:41.275574Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/c/Curviate/curviate-sdk.svg",
"full_name": "Curviate/curviate-sdk",
"license_state": "standard",
"license_spdx": "MIT"
}