原始 JSON 报告 机器可读
{
"data": {
"repo": {
"topics": [
"ai",
"cli",
"code-search",
"context",
"gitlab",
"knowledge-graph",
"mcp",
"developer-tools",
"git",
"offline-first",
"python",
"semantic-search"
],
"is_fork": false,
"size_kb": 21582,
"has_wiki": true,
"homepage": "http://sayak.in/contextlake/",
"languages": {
"CSS": 33593,
"HTML": 741996,
"Shell": 2678,
"Python": 1511608,
"Dockerfile": 1573,
"JavaScript": 118499
},
"pushed_at": "2026-07-26T19:34:48Z",
"created_at": "2026-06-28T07:03:00Z",
"owner_type": "User",
"updated_at": "2026-07-26T19:34:43Z",
"description": "A local context layer for AI tools: mirror your repositories, index them into a knowledge graph, and serve it over MCP so agents answer from real source instead of guessing.",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "Python",
"significant_languages": [
"Python",
"HTML"
]
},
"owner": {
"blog": "http://sayak.in",
"name": "Sayak Sarkar",
"type": "User",
"login": "sayak-sarkar",
"company": "Accelya Inc.",
"location": "Pune, India",
"followers": 101,
"avatar_url": "https://avatars.githubusercontent.com/u/1418735?v=4",
"created_at": "2012-02-08T07:25:39Z",
"is_verified": null,
"public_repos": 108,
"account_age_days": 5282
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v2.54.0",
"kind": "minor",
"published_at": "2026-07-26T19:36:22Z"
},
{
"tag": "v2.53.0",
"kind": "minor",
"published_at": "2026-07-26T11:43:23Z"
},
{
"tag": "v2.52.0",
"kind": "minor",
"published_at": "2026-07-26T11:14:11Z"
},
{
"tag": "v2.51.1",
"kind": "patch",
"published_at": "2026-07-26T09:57:31Z"
},
{
"tag": "v2.51.0",
"kind": "minor",
"published_at": "2026-07-26T08:54:50Z"
},
{
"tag": "v2.50.0",
"kind": "minor",
"published_at": "2026-07-26T07:01:23Z"
},
{
"tag": "v2.49.0",
"kind": "minor",
"published_at": "2026-07-26T05:43:13Z"
},
{
"tag": "v2.48.2",
"kind": "patch",
"published_at": "2026-07-26T05:10:23Z"
},
{
"tag": "v2.48.1",
"kind": "patch",
"published_at": "2026-07-25T20:18:11Z"
},
{
"tag": "v2.48.0",
"kind": "minor",
"published_at": "2026-07-25T19:13:21Z"
},
{
"tag": "v2.47.0",
"kind": "minor",
"published_at": "2026-07-25T15:35:16Z"
},
{
"tag": "v2.46.0",
"kind": "minor",
"published_at": "2026-07-25T15:01:27Z"
},
{
"tag": "v2.45.1",
"kind": "patch",
"published_at": "2026-07-25T14:15:52Z"
},
{
"tag": "v2.45.0",
"kind": "minor",
"published_at": "2026-07-25T07:30:06Z"
},
{
"tag": "v2.44.0",
"kind": "minor",
"published_at": "2026-07-22T21:16:23Z"
},
{
"tag": "v2.43.0",
"kind": "minor",
"published_at": "2026-07-22T10:46:00Z"
},
{
"tag": "v2.42.0",
"kind": "minor",
"published_at": "2026-07-21T08:47:41Z"
},
{
"tag": "v2.41.0",
"kind": "minor",
"published_at": "2026-07-21T06:57:36Z"
},
{
"tag": "v2.40.0",
"kind": "minor",
"published_at": "2026-07-20T17:48:27Z"
},
{
"tag": "v2.39.0",
"kind": "minor",
"published_at": "2026-07-20T02:25:59Z"
},
{
"tag": "v2.38.0",
"kind": "minor",
"published_at": "2026-07-19T19:12:50Z"
},
{
"tag": "v2.37.0",
"kind": "minor",
"published_at": "2026-07-08T15:11:35Z"
},
{
"tag": "v2.36.0",
"kind": "minor",
"published_at": "2026-07-08T10:05:05Z"
},
{
"tag": "v2.35.0",
"kind": "minor",
"published_at": "2026-07-08T04:48:43Z"
},
{
"tag": "v2.34.0",
"kind": "minor",
"published_at": "2026-07-07T12:31:27Z"
},
{
"tag": "v2.33.2",
"kind": "patch",
"published_at": "2026-07-06T15:34:33Z"
},
{
"tag": "v2.33.1",
"kind": "patch",
"published_at": "2026-07-06T14:16:38Z"
},
{
"tag": "v2.33.0",
"kind": "minor",
"published_at": "2026-07-06T11:11:51Z"
},
{
"tag": "v2.32.0",
"kind": "minor",
"published_at": "2026-07-06T10:27:54Z"
},
{
"tag": "v2.31.0",
"kind": "minor",
"published_at": "2026-07-06T09:40:13Z"
},
{
"tag": "v2.30.1",
"kind": "patch",
"published_at": "2026-07-06T08:59:05Z"
},
{
"tag": "v2.30.0",
"kind": "minor",
"published_at": "2026-07-06T08:18:18Z"
},
{
"tag": "v2.29.0",
"kind": "minor",
"published_at": "2026-07-06T07:30:21Z"
},
{
"tag": "v2.28.0",
"kind": "minor",
"published_at": "2026-07-06T06:44:04Z"
},
{
"tag": "v2.27.0",
"kind": "minor",
"published_at": "2026-07-06T06:10:29Z"
},
{
"tag": "v2.26.0",
"kind": "minor",
"published_at": "2026-07-06T05:23:45Z"
},
{
"tag": "v2.25.0",
"kind": "minor",
"published_at": "2026-07-02T15:06:54Z"
},
{
"tag": "v2.24.0",
"kind": "minor",
"published_at": "2026-07-02T11:36:45Z"
},
{
"tag": "v2.23.0",
"kind": "minor",
"published_at": "2026-07-02T09:09:01Z"
},
{
"tag": "v2.22.0",
"kind": "minor",
"published_at": "2026-07-02T05:33:34Z"
},
{
"tag": "v2.21.0",
"kind": "minor",
"published_at": "2026-07-02T04:24:01Z"
},
{
"tag": "v2.20.1",
"kind": "patch",
"published_at": "2026-07-01T11:57:10Z"
},
{
"tag": "v2.20.0",
"kind": "minor",
"published_at": "2026-06-30T16:31:47Z"
},
{
"tag": "v2.19.2",
"kind": "patch",
"published_at": "2026-06-28T17:17:48Z"
},
{
"tag": "v2.19.1",
"kind": "patch",
"published_at": "2026-06-28T16:59:25Z"
},
{
"tag": "v2.11.0",
"kind": "minor",
"published_at": "2026-06-28T07:09:10Z"
},
{
"tag": "v2.19.0",
"kind": "minor",
"published_at": "2026-06-28T12:18:06Z"
},
{
"tag": "v2.18.0",
"kind": "minor",
"published_at": "2026-06-28T10:26:29Z"
},
{
"tag": "v2.17.0",
"kind": "minor",
"published_at": "2026-06-28T10:12:22Z"
},
{
"tag": "v2.16.0",
"kind": "minor",
"published_at": "2026-06-28T10:06:38Z"
},
{
"tag": "v2.15.0",
"kind": "minor",
"published_at": "2026-06-28T09:59:29Z"
},
{
"tag": "v2.14.0",
"kind": "minor",
"published_at": "2026-06-28T08:42:21Z"
},
{
"tag": "v2.13.0",
"kind": "minor",
"published_at": "2026-06-28T08:28:23Z"
},
{
"tag": "v2.12.0",
"kind": "minor",
"published_at": "2026-06-28T07:59:56Z"
},
{
"tag": "v2.10.0",
"kind": "minor",
"published_at": "2026-06-28T07:09:07Z"
},
{
"tag": "v2.9.1",
"kind": "patch",
"published_at": "2026-06-28T07:09:04Z"
},
{
"tag": "v2.9.0",
"kind": "minor",
"published_at": "2026-06-28T07:09:02Z"
},
{
"tag": "v2.8.0",
"kind": "minor",
"published_at": "2026-06-28T07:09:00Z"
},
{
"tag": "v2.7.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:57Z"
},
{
"tag": "v2.6.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:55Z"
},
{
"tag": "v2.5.1",
"kind": "patch",
"published_at": "2026-06-28T07:08:53Z"
},
{
"tag": "v2.5.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:50Z"
},
{
"tag": "v2.4.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:48Z"
},
{
"tag": "v2.3.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:45Z"
},
{
"tag": "v2.2.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:42Z"
},
{
"tag": "v2.1.6",
"kind": "patch",
"published_at": "2026-06-28T07:08:40Z"
},
{
"tag": "v2.1.5",
"kind": "patch",
"published_at": "2026-06-28T07:08:38Z"
},
{
"tag": "v2.1.4",
"kind": "patch",
"published_at": "2026-06-28T07:08:36Z"
},
{
"tag": "v2.1.3",
"kind": "patch",
"published_at": "2026-06-28T07:08:33Z"
},
{
"tag": "v2.1.2",
"kind": "patch",
"published_at": "2026-06-28T07:08:31Z"
},
{
"tag": "v2.1.1",
"kind": "patch",
"published_at": "2026-06-28T07:08:28Z"
},
{
"tag": "v2.1.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:26Z"
},
{
"tag": "v2.0.1",
"kind": "patch",
"published_at": "2026-06-28T07:08:24Z"
},
{
"tag": "v2.0.0",
"kind": "major",
"published_at": "2026-06-28T07:08:23Z"
},
{
"tag": "v1.18.1",
"kind": "patch",
"published_at": "2026-06-28T07:08:22Z"
},
{
"tag": "v1.18.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:21Z"
},
{
"tag": "v1.17.1",
"kind": "patch",
"published_at": "2026-06-28T07:08:20Z"
},
{
"tag": "v1.17.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:20Z"
},
{
"tag": "v1.16.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:19Z"
},
{
"tag": "v1.15.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:18Z"
},
{
"tag": "v1.14.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:17Z"
},
{
"tag": "v1.13.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:16Z"
},
{
"tag": "v1.12.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:15Z"
},
{
"tag": "v1.11.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:15Z"
},
{
"tag": "v1.10.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:14Z"
},
{
"tag": "v1.9.1",
"kind": "patch",
"published_at": "2026-06-28T07:08:13Z"
},
{
"tag": "v1.9.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:12Z"
},
{
"tag": "v1.8.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:11Z"
},
{
"tag": "v1.7.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:11Z"
},
{
"tag": "v1.6.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:10Z"
},
{
"tag": "v1.5.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:09Z"
},
{
"tag": "v1.4.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:08Z"
},
{
"tag": "v1.3.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:07Z"
},
{
"tag": "v1.2.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:07Z"
},
{
"tag": "v1.1.0",
"kind": "minor",
"published_at": "2026-06-28T07:08:06Z"
},
{
"tag": "v1.0.0",
"kind": "major",
"published_at": "2026-06-28T07:08:05Z"
}
],
"recent_commits": [
{
"oid": "59f37704ac168d457b742321958b3061af67b94b",
"body": "Minor release: graph --format deploymentdiagram (Mermaid Terraform resource\ndiagram), plus a data-block categorization fix caught before this shipped.",
"is_bot": false,
"headline": "chore(release): v2.54.0",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T19:34:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "28561bd0bc6b596f8b1ff862a6eabf53828d1f65",
"body": "…lock categorization\n\nRenamed --format deployment to deploymentdiagram before its first release, for\nconsistency with the other Mermaid-specific formats (classdiagram, sequencediagram,\nstatediagram, erdiagram all use the <noun>diagram suffix).\n\nAlso fixes a real bug: a Terraform `data` block's addre\n[…]\n data resource under\n\"other\" regardless of its actual type. The `data.` prefix is now stripped before\ncategorizing.\n\nDocs (visualize.md, index-code-graph.md) and site (llms-full.txt) updated to match.",
"is_bot": false,
"headline": "fix(graph): rename deployment format to deploymentdiagram; fix data-b…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T19:33:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b3303274e7a0ec13d6858832e9826867f021163a",
"body": "…agram\n\nRenders kb/hcl.py's existing resource/data/module nodes and reconstructed\ndepends_on edges, grouped by an inferred category (network/compute/storage/\ndatabase/security/module). No new extraction pass, same spirit as\nerdiagram. --c4 continues to reject text-diagram formats (deployment added\nto that rejection list).",
"is_bot": false,
"headline": "feat(graph): add --format deployment, a Mermaid Terraform resource di…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T19:21:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c0ba733f7cbf6307d4fb216dabf88ddfc9499d8b",
"body": "styling.py (colors/icons), payload.py (subgraph extraction, the\ncanonical payload), diagrams.py (text-format renderers: dot/mermaid/\nclassdiagram/sequencediagram/statediagram/erdiagram), html_render.py\n(the self-contained cytoscape.js page + wiki/site pages), serve.py\n(live graph/site HTTP servers).\n[…]\ntween the two; updated\npyproject.toml's E501 per-file-ignore (long embedded SVG/HTML-template\nlines) from the single old file to the new package glob.\n\nSee plan-kb-module-split.md for the full design.",
"is_bot": false,
"headline": "refactor(kb): split visualize.py (1462 lines) into visualize/ subpackage",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T19:01:17Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8b7ae33459ea792d7441b729e4246274d661b610",
"body": "One module per CLI command handler (index/connect/embed/wiki/steer/\nlint/query/owners/impact/ingest/enrich/serve/doctor/graph/eval/\ndashboard/hook) plus a _common.py for the cross-cutting helpers\n(_open_store, _guard_store, _connect_targets, _watch_loop, _git_head,\n_repo_id_suggestions, _unknown_rep\n[…]\ne mocked one) --\ncaught live via process inspection (stuck in hrtimer_nanosleep),\nfixed by patching cmd_embed's own module instead of the shim's copy.\n\nSee plan-kb-module-split.md for the full design.",
"is_bot": false,
"headline": "refactor(kb): split commands.py (2091 lines) into kb/cmds/ subpackage",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T19:01:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3cd50c1f59dc8d7fe1fa07738f57dcb7f229d67c",
"body": "Minor release: graph --c4 --c1 (C1 external-system layer).",
"is_bot": false,
"headline": "chore(release): v2.53.0",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T11:41:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "57ad85b3c017542f73d4b2b6eb03f022963097e4",
"body": "Adds one dashed box per distinct host an indexed repo calls over HTTP\nthat never resolves to any indexed repo's exposed route, drawn outside\nevery namespace boundary, connected by a calls_external edge. Ships\nper spec-D's own recommended defaults: V1 stays deliberately\nunclassified (a real third par\n[…]\nrnal HTTP\ncall and an unresolved external call (Stripe) both classify correctly,\nthe external one rendered as a dashed box outside every boundary, and\nconfirmed absent entirely when --c1 isn't passed.",
"is_bot": false,
"headline": "feat(graph): C1 system-context layer (graph --c4 --c1)",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T11:40:51Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "dbfcba5f166dc6a0ed0c24a1fd238d052ecd8c15",
"body": "Minor release: ADR/decision-record surfacing, graph --format erdiagram,\nthe builtin-model wiki hint, and the docs em-dash cleanup.",
"is_bot": false,
"headline": "chore(release): v2.52.0",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T11:12:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5dd182e8e60ad00209a80aba566b88169033c9dd",
"body": "… nodes\n\ndocs/adr/, docs/decisions/, decisions/, adr/ markdown files become `adr`\nnodes in the repo's own shard during index -- no separate command, no\n@enrich:/@ingest: side-channel, since these are genuinely part of the\nrepo's own git history, not external connector content. Semantically\nsearchabl\n[…]\nlive: indexed a repo with a real docs/adr/0001-*.md, confirmed\nthe adr node in the store, and confirmed repo_brief/render_prompt\ncorrectly cite it with a \"Decisions\" section added to the page outline.",
"is_bot": false,
"headline": "feat(kb): surface a repo's own ADR/decision docs as first-class graph…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T11:04:46Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "8d83f5f890b8ea0d659d5ba04712a9dc688c288b",
"body": "…FK data\n\nRenders the table/view nodes and references edges the SQL DDL extractor\nalready collects -- no new extraction pass. Verified live against both\na real-DDL repo (2 tables + 1 view + 1 FK edge, matching source) and an\nORM-only repo (0 table/view nodes), so the empty-schema case ships with\ngui\n[…]\nttp.py's normalize_path() strips the host/scheme before the endpoint\nnode exists, so no unresolved outbound-call target survives anywhere in\nthe graph today -- it needs new extraction, not a renderer.",
"is_bot": false,
"headline": "feat(graph): add --format erdiagram, a Mermaid ER view of table/view/…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T10:54:08Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "65b5a71faca8cdd2bf265e70abb6727855a1e5e8",
"body": "…-dash strip\n\n- wiki: print a one-time note before generation when the council is running\n on the builtin 0.5B model, which mostly rubber-stamps instead of gating\n meaningfully -- points at a real --llm backend instead.\n- docs: strip the em-dashes that crept back into docs/*.md since the\n original 2026-07-24 house-style pass (serve, cli-reference,\n index-code-graph, visualize, dashboard, connect-enrich).",
"is_bot": false,
"headline": "fix(wiki,docs): hint on the weak builtin reviewer; finish the docs em…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T10:25:03Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b21f1111f4a0a37a8fd1620caf48822ee5944d15",
"body": "Patch release for two bug fixes accumulated since v2.51.0: the\nmisleading top-level \"Unknown command\" argparse error, and the\ndashboard architecture-view repo-label overlap.",
"is_bot": false,
"headline": "chore(release): v2.51.1",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T09:55:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "120215889e00d5501aa73ee331a2f95e841ee467",
"body": "The mindmap drill-in's grid layout (gridKids, one repo cluster's local grid\nbeneath its namespace node) only kept node shapes apart via avoidOverlap --\nlabel text extends well past a node's own circle, so adjacent repos with\nlonger names (catalog-api, auth-service, shared-lib) ran their labels into\n\n[…]\nrk\ntheme against the exact repro from the v2.50.0 playground testing pass\n(the bundled --sample demo fleet): the six repo names under \"acme\" are\nnow clearly legible where they previously ran together.",
"is_bot": false,
"headline": "fix(dashboard): repo labels no longer overlap in the architecture view",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T09:49:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "502c83fd0ccd8868e6668d4e68d2327be30331f6",
"body": "…nown command\n\ncontextlake --work-d /tmp doctor (--work-d isn't a real root flag) reported\n\"Unknown command: '/tmp'\" instead of the actual problem: argparse never\nlearns --work-d expects a value, so /tmp falls into the <command>\npositional slot and fails there first. Only this exact shape (unrecogni\n[…]\nmediately preceded by a token that starts with\n\"-\" and isn't a registered root option. If so, that's the real error.\nFound by the v2.50.0 playground testing pass (flagged low severity,\naddressed now).",
"is_bot": false,
"headline": "fix(cli): unrecognized top-level flag no longer masquerades as an unk…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T09:37:51Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5f9f21e095ecb06ec90b7681d902922b6993634a",
"body": "Python-Markdown's plain fenced_code extension doesn't handle a fence\nindented inside a list-item continuation -- it silently falls back to\ntreating the fence markers as literal text merged into one run-on\nparagraph, and merges every following list item into it too. Confirmed\nlive in model-providers.\n[…]\n/\ncli-reference (tables, tabs, diagrams, top-level fences) shows no\nregressions -- the one remaining literal ``` in the built site is an\nintentional style-guide example showing markdown syntax itself.",
"is_bot": false,
"headline": "fix(site): fenced code blocks nested in list items now render correctly",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T09:31:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "eeefab1344e823c7982da0edaa067b88122e4766",
"body": "Agent worktrees and job scratch dirs under .claude/ were untracked but not\ngitignored, so they showed up in every git status. Local-only, never meant\nto be committed.",
"is_bot": false,
"headline": "chore: gitignore .claude/ (Claude Code session state)",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T09:28:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "372f19488ff3aba0624a399b5acdc1f629d76583",
"body": "These shipped in v2.50.0/v2.51.0 but were never written up: a mistyped\ncommand's \"Did you mean\" suggestion and the no-partial-flag-matching\nbehavior (cli-reference.md), --plain's actual scope -- strips color, not\nglyphs (console-output.md), -n/--dry-run on the mirror commands (usage.md),\nand source \n[…]\nted, unnoticed, in model-providers.md. Worked around\nit locally by using inline code instead of a nested fence; the underlying\nbuild-pipeline limitation is still there and worth a real fix separately.",
"is_bot": false,
"headline": "docs: document typo-suggestions, allow_abbrev, --plain, -n, --from-stdin",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T09:20:59Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ffa6f2d659478f745a2569267a8a2ae8358fe582",
"body": "sys.exit(main()) referenced sys without importing it. Python resolves the\nsys.exit attribute access before evaluating main()'s call, so the NameError\nfired first -- main() never actually ran, meaning the docs search index\nhas never shipped its build-time semantic \"related\" neighbours despite\nlooking\n[…]\n|| true`, so the traceback was silently swallowed and the plain\nlexical index shipped instead. Caught while redeploying after the 2.51.0\nrelease. Verified live: all 447 entries now populate `related`.",
"is_bot": false,
"headline": "fix(site): gen_search_index.py's missing sys import silently no-op'd",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T09:01:35Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e7acffb0e9f2fab389b0152343dab4a2fff915ad",
"body": "Dashboard MCP console + Settings surfaces, and six correctness/UX fixes\nfound by the v2.50.0 post-release playground testing pass (repo-identity\nmisattribution, --json empty-argument leak, MCP empty-query crash, init\n--config ignored, update/branches summary glyph, --set traceback + --plain\nhelp text). See CHANGELOG.md for full detail.",
"is_bot": false,
"headline": "chore(release): 2.51.0",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T08:52:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d8a47538194539afe125c24ad2e3b3ccf2f37ecc",
"body": "source add --set KEY (no \"=\") raised an uncaught ValueError all the way\nout of cmd_source_add, printing a raw Python traceback instead of the\nCLI's normal clean error style -- the message itself was already right,\nit just wasn't caught. Wrap it and route through the same style.fail()\npattern the sib\n[…]\nn/NO_COLOR (which only strip ANSI color). Fixed the\ntext rather than add fallback glyph rendering, matching what NO_COLOR=1\nhas always actually done. Both found by the v2.50.0 playground testing pass.",
"is_bot": false,
"headline": "fix(cli): clean error for malformed --set, accurate --plain help text",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T08:19:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3586e65c5028f53b5378f76250158d2fe78f6b66",
"body": "index/embed/wiki already swap their summary line's glyph from ok to warn\nwhen any repo failed; update/branches called style.ok() unconditionally,\nso a failed run's final summary line still read as success at a glance --\nthe failure detail was only apparent in the next-step text below it.\nFound by the v2.50.0 playground testing pass. Apply the same\nstyle.ok() if not errors else style.warn() pattern to both.",
"is_bot": false,
"headline": "fix(cli): update/branches summary line warns on partial failure",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T08:15:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4b711aee54e6672d97f95c93a5e4db62d848010d",
"body": "init is the one command that writes both generated files (mirror INI +\nkb.toml); it always targeted the fixed defaults (~/.contextlake.ini,\n~/.contextlake/kb.toml) regardless of --config, unlike every other command.\nHarmless only when the defaults already existed and --force wasn't passed\n(init corr\n[…]\ntesting pass.\n\n--config now redirects the mirror INI (matching its documented meaning for\nmirror commands), with kb.toml written alongside it as a sibling -- same\nrelative layout as the real defaults.",
"is_bot": false,
"headline": "fix(init): --config no longer silently ignored",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T08:12:53Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "041e639896658a59483d92a2d1e006089fc66970",
"body": "…query\n\nAn empty string embeds to a zero vector, which crashed downstream in the\nvector store's similarity scoring with a raw, uncaught\nTypeError: unsupported operand type(s) for -: 'float' and 'NoneType'\ninstead of degrading gracefully the way search_code already does. Found by\nthe v2.50.0 playgrou\n[…]\nP client. Guard all three\ncall sites to skip straight to an empty result (or, for ask, fall through\nto the existing FTS fallback) on an empty/whitespace-only query, before\nthe embedder is ever called.",
"is_bot": false,
"headline": "fix(mcp): semantic_search/hybrid_search/ask no longer crash on empty …",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T08:09:10Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f6426e591389f0cd695ade1d07573a678318741a",
"body": "…ument\n\nThe empty-argument guard ran before args.json was checked in all three\ncommands, so `contextlake query \"\" --json` printed a plain-text\n\"usage: ...\" line with a log timestamp to stdout instead of the structured\nJSON error format used for every other error case -- breaking --json's\n\"always val\n[…]\nJSON\" contract on exactly the case a jq pipeline needs it\nmost. Found by the v2.50.0 playground testing pass. Check args.json first\nin all three and emit {\"error\": \"missing_argument\", \"usage\": \"...\"}.",
"is_bot": false,
"headline": "fix(cli): query/owners/impact --json emits valid JSON on an empty arg…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T08:05:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "69ad16d5a65d44b662f1a6c68af86eb042621248",
"body": "…entity\n\ngit -C <path> silently walks UP the filesystem tree past an incomplete or\ncorrupted .git to find the nearest real one -- so index --workspace could\nattribute a broken nested checkout to an unrelated ancestor repo's remote\nand full commit history, with the failed counter never incrementing (\n[…]\nexisting tests that used a bare `mkdir(\".git\")` as a\nfixture shorthand -- never a structurally valid repo to begin with, which\nis part of why this bug was possible -- to use a real minimal `git init`.",
"is_bot": false,
"headline": "fix(kb): never silently index a corrupted .git under an ancestor's id…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T08:02:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "694c506235abf72a6f0879e54a09a4e0e47b2074",
"body": "The fixture store has no embeddings.sqlite, so semantic_available is false\nregardless of the fix -- the previous assertion (tool_count > 0) passed\nidentically with the leak present or fixed. Spy on build_embedder's actual\ninput instead: verified this version fails against the pre-fix code\n(EmbeddingsCfg(enabled=True, provider='builtin') from the real ambient\nconfig) and passes against the fix.",
"is_bot": false,
"headline": "test(dashboard): strengthen the mcp_console sample-mode regression test",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T07:50:29Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "34151472606ea5656a0bb3901b8d3a031bbb4304",
"body": "…equest\n\nbuild_server only checks vector_store is not None at tool-registration time;\nthe object is queried later, inside a tool body, only when a client actually\ncalls semantic_search/hybrid_search. mcp_console() was opening a real\nembeddings.sqlite vector store on every request just to satisfy tha\n[…]\n --\na cheap sentinel does the same job without the file open. Flagged by advisor\nreview; store_size_bytes' rglob was also flagged but measured at 0.3s over\nthe real 8GB/3064-file store, so left as is.",
"is_bot": false,
"headline": "perf(dashboard): stop opening a real vector store on every /api/mcp r…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T07:47:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7f5daab813dfd1b5e7796c194070f6b72b0375b6",
"body": "load_kb_config(None) still merges ~/.contextlake/kb.toml regardless of\nconfig_path, so the new MCP console / Settings surfaces would resolve a\nuser's real languages/embeddings/llm/connector config under --sample,\na mode billed as \"fictional data, nothing local is read, safe to share\".\nThread a sample flag through to bypass the precedence chain entirely and\nuse bare KbConfig defaults instead. Caught by advisor review before release.",
"is_bot": false,
"headline": "fix(dashboard): --sample never leaks the real ambient kb.toml",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T07:46:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5afc18e25f1d5a0a6f087efb4b3d8bb48f1936d5",
"body": "Two read-only, live-only dashboard panels from the product-roadmap catalogue\n(app-prototype.html cross-check). MCP shows the live tool catalog introspected\nfrom a real server.build_server() instance (never drifts from what serve\nactually exposes) plus copyable .mcp.json/.vscode/mcp.json snippets. Se\n[…]\ncaught and fixed a real bug in testing (statTile always numeric-\nformats its value, so a non-numeric \"On\"/\"Off\"/byte-size string rendered\n\"NaN\" -- added a textTile variant for non-numeric stat tiles).",
"is_bot": false,
"headline": "feat(dashboard): MCP console + Settings surfaces",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T07:36:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0da5e157f3fa6ee9c2dd539c8c8bb528d45aa7c1",
"body": "CLI UX improvements from a cli-guidelines.dev + multi-article review: typo\nsuggestions, no silent flag abbreviation, --json on query/owners/impact/lint,\nconcrete next-step guidance on failure across update/branches/index/embed/\nwiki, -n/--plain/--from-stdin, and docs/issues links in --help. Also fixes\nembed/wiki silently reporting a partial failure as a clean success.",
"is_bot": false,
"headline": "chore(release): v2.50.0",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T06:59:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "65f9ac93c772f66022c78a661f44cff244efca21",
"body": "…otgun\n\nlint --json returning 1 on an unclean graph (mirroring the human path) was\nasserted as `in (0, 1)`, which papered over the actual, deliberate contract.\nPinned to the real deterministic value and documented the reasoning in the\nCHANGELOG so a CI script author isn't surprised by a non-zero exi\n[…]\nRootArgumentParser's regex-based interception is the\nmost stable point available (ArgumentError is always stringified before\nreaching error()) and its one known degradation mode (a translated locale).",
"is_bot": false,
"headline": "test: pin lint --json's exit-code contract, remove a test-env-leak fo…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T06:57:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ce4a9a500d5cc8cad11930130279319ce06bccff",
"body": "These four commands answer questions -- exactly the use case contextlake\nexists for -- but had no machine-readable output, so piping any of them to\njq failed outright. Reuses graph's already-proven stdout/stderr split\n(use_stderr() for logs, the JSON payload is the only thing on stdout).\nStructured error cases too (unknown_repo with suggestions, not_found,\nambiguous), not just the success path.",
"is_bot": false,
"headline": "feat(kb): --json on query, owners, impact, and lint",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T06:52:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d6afae362a0a48e48ee496760c4ff05f22b8ae85",
"body": "…cess\n\nThe summary line for embed and wiki (per-repo and --namespaces) kept its ✓\nglyph and silently dropped the failed count whenever at least one repo/\nnamespace in the batch succeeded, so a partial failure was indistinguishable\nfrom a fully clean run. Both now show ⚠ and the failed count.\n\nAlso g\n[…]\nready-good ending pattern (name the next\ncommand, be specific about what failed) to update, branches, index\n--workspace, embed, and wiki, none of which pointed anywhere useful when a\nrun had failures.",
"is_bot": false,
"headline": "fix(kb): embed/wiki no longer report a partial failure as a clean suc…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T06:45:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fc33f9c39c49be21ec4a52bcc599fd9e714bee46",
"body": "Three small conveniences, each backing an existing equivalent rather than\ninventing new behavior: -n mirrors the rm/cp/make --dry-run shorthand,\n--plain is a discoverable spelling of NO_COLOR=1, and --from-stdin closes\nthe shell-history exposure gap in `source add --set` (which already never\nechoes to logs, but the raw value still landed as a literal CLI argument).",
"is_bot": false,
"headline": "feat(cli): -n, --plain, and source add --from-stdin",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T06:36:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6e488b65f44f8c847298f8a035132c828e3abcef",
"body": "…/issues\n\nThree small, independently-verified CLI UX fixes from a cli-guidelines.dev\nreview: a mistyped subcommand now suggests the closest real one instead of\ndumping the full 30-item choice list; allow_abbrev=False on every parser so\nflags can't be silently abbreviated; --help points at the docs site and the\nissue tracker.",
"is_bot": false,
"headline": "feat(cli): typo suggestions, no flag abbreviation, help links to docs…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T06:32:26Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bfaf54d14edc5674dfcc632c70b931aa805a5b1f",
"body": "…eted upstream\n\nA tracked branch missing on origin almost always means it was\nrenamed, merged, or superseded -- not something that needs a human\nto run `branches` by hand every time. `update` now fetches the full\nbranch list and switches to the most-active remaining branch\nautomatically (the same selection `branches` makes), reporting\n\"switched\" with both branch names. Falls back to the previous clean\nskip only if the broader reselect fetch also fails, or no other\nbranch exists.",
"is_bot": false,
"headline": "feat(update): auto-switch to a new branch when the tracked one is del…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T05:54:01Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d48a75ec99665663b9aa2492d499f562c73c027f",
"body": "Nobody uses gitlab_sync anymore. Removed: the gitlab-sync console-\nscript alias; reading a legacy ~/.gitlab_sync.ini / .gitlab_sync.ini\nfile or its [gitlab_sync] INI section; reading a legacy\n~/.gitlab-sync/kb.toml / .gitlab-sync.kb.toml config, and falling\nback to a pre-existing ~/.gitlab-sync/kb s\n[…]\nsserted the now-removed legacy behavior.\n\nBREAKING CHANGE: anyone still on a pre-rename gitlab-sync config or\nstore must migrate to .contextlake.ini/~/.contextlake/ before\nupgrading past this release.",
"is_bot": false,
"headline": "feat!: drop the gitlab-sync backward-compat layer (v2.49.0)",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T05:40:25Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e508a8d477596d22facd428b6587aeda382b3ef6",
"body": "Folds all 6 code fixes shipped since v2.48.1 (mermaid diagram\nescaping, steer/commands.py file-corruption chain, hook silent\nrepo_id mismatch, wiki council review-parsing fragility, c4\nnamespace-boundary tagging) into one CHANGELOG section, matching\nthe actual state of what's landing in this tag.",
"is_bot": false,
"headline": "chore(release): v2.48.2",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T05:00:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9e4d22dcea4b82adc348d43b713cffec7c9db629",
"body": "Two bugs in bucketing repos into c4 namespaces for boundary-tagging:\na repo whose id IS exactly a namespace prefix fell into the shared\n\"(ungrouped)\" catch-all instead of that namespace's own boundary,\nmismarking a real edge as crossing a boundary; and \"(ungrouped)\" was\nitself treated as one shared \n[…]\n dashboard's display grouping, which\ncorrectly wants a graceful shared catch-all for its own purpose):\neach repo's own path prefix, or its full id when shorter than\ngroup_depth, becomes its namespace.",
"is_bot": false,
"headline": "fix(c4): boundary tagging no longer shares derive_groups' display bucket",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T04:55:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fa344fd3505f895f3be751723ee466da54f53ac4",
"body": "Three related bugs in the malformed-JSON fallback a small local model's\noutput regularly takes: a naive brace-slice broke on any trailing\nprose containing a brace, discarding a validly-parsed issues list;\nthe score-recovery regex scanned the entire raw text so an unrelated\n\"rating is N\" aside could win over the real, later \"score\" field; and\n\"N out of 10\" matched anywhere in prose, misreading a coverage-gap\ncount (\"3 out of 10 endpoints\") as a review score.",
"is_bot": false,
"headline": "fix(wiki): harden council review-parsing recovery paths",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T04:51:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "fd2b7a19e556faff8169f97fb4f24fde3a793c06",
"body": "_canonical_repo_id's bare except caught genuine problems (a bad\n--config, a corrupt/too-new store) as if they were the benign \"not\nyet indexed\" case -- which SqliteStore never actually raises for,\nsince it creates the store on open. A bad --config produced a hook\ninstall reported as a clean success but permanently inert. Now logs\na warning naming the actual cause instead of swallowing it.",
"is_bot": false,
"headline": "fix(hook): stop silently swallowing repo_id resolution failures",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T04:47:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ff989d14593cd746f5a9dfe83f9bae908a3cc2da",
"body": "…rd MCP merge\n\nA repo id or package name (package names reachable verbatim through\nmanifest.py's unvalidated package.json parsing) could carry a\nbacktick or the literal END marker text, breaking out of its markdown\ncode span or smuggling a duplicate marker into the generated body --\nthe next refresh\n[…]\nvers/\nservers value after markdown/skill files were already written, and a\nrelative --config path was embedded verbatim though it may launch\nfrom --out, not the invocation directory. Both now handled.",
"is_bot": false,
"headline": "fix(steer): sanitize interpolated names, validate splice markers, gua…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T04:45:25Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "71ccb871f9dbcac3fd4dd4f3d6bd0b6ccac92615",
"body": "…ction\n\n_mermaid_escape only escaped quotes and square brackets. A pipe in an\nedge relation broke the -->|label| delimiter syntax; a brace in a\nclass member signature closed the class body early; a newline in a\nnode name became a genuine new Mermaid line, rendering as a real Note\nannotation in the output SVG. All three confirmed against a real\nMermaid parser. Now also escapes {, }, |, and newlines.",
"is_bot": false,
"headline": "fix(graph): mermaid diagrams no longer break or accept directive inje…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-26T04:41:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9c62860a6f721aaef12bc0037901389be6c826d2",
"body": "docs/dashboard.md documents `contextlake wiki <repo-id> --llm\nbuiltin`; the dashboard's actual generated/copied command (shared by\nboth --serve and --site) had no --llm flag at all -- and without it\n(or [llm] enabled in kb.toml), the wiki stage silently no-ops. Not\njust a docs mismatch: the copied command didn't do anything. Found by\nan independent post-release docs-accuracy review.",
"is_bot": false,
"headline": "fix(dashboard): Generate-wiki action now copies a command that works",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T21:12:30Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b27408e5b948a5c5f4864f385bd1684c8e80cded",
"body": "docs/serve.md's own headline example, ask(\"explain the catalog-api\"),\nsilently fell through to search instead of returning wiki prose or a\nrepo brief. Repo ids are always host-qualified\n(gitlab.example.com/acme/catalog-api), but the router only extracts\nthe trailing \"catalog-api\" out of the question\n[…]\nhe\nrepo's last path segment when an exact id lookup misses. Wired into\nboth explain and owners (who_knows has the identical exact-match gap).\nFound by an independent post-release docs-accuracy review.",
"is_bot": false,
"headline": "fix(serve): ask's explain/owners routes now resolve a repo's short name",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T21:09:56Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b7d253e745ffc167e374b7fdee3f8300ba7cb41c",
"body": "scan_repo_metrics called get_local_repos directly and never consulted\nrepo_filter, so `contextlake audit --repos PATTERN` accepted the flag\n(it's in --help) but scanned every repo regardless -- contradicting\ndocs/usage.md's \"every mirror command ... accepts --repos\". Now\nfilters via the same match_r\n[…]\nse. repo_filter_patterns is promoted\nfrom _repo_filter_patterns to a public name (kb/commands.py already\ncalled it across module boundaries). Found by an independent\npost-release docs-accuracy review.",
"is_bot": false,
"headline": "fix(mirror): audit now honors --repos like every other mirror command",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T21:06:52Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "72505cd7b173a18718bd4a1d966dc28e4e41c9b3",
"body": "float(True) == 1.0 in Python (bool is an int subclass), so a\nmalformed {\"score\": true, ...} review silently passed as a perfect\nscore in the primary parsing path. _extract_score's own fallback\nladder already guards against this (not isinstance(val, bool)); the\nprimary path now applies the same guard and abstains instead. Found\nby an independent post-release review.",
"is_bot": false,
"headline": "fix(wiki): a bool JSON score no longer scores 1.0/0.0 as if real",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T21:03:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "099ec5b3eb3788a30a5ec9a7bcb8b45d477d6de5",
"body": "skill_md()/workflow_md() carry a MARKER but no closing END marker\n(unlike AGENTS.md's bounded managed block), so the writer could not\ntell a still-pristine contextlake-managed file from one the user\nedited since -- MARKER presence alone triggered a blind whole-file\noverwrite, silently discarding the\n[…]\nwhose on-disk content is byte-identical\nto what's about to be written (a true no-op); anything else -- foreign\nor locally edited -- is kept unless --force. Found by an independent\npost-release review.",
"is_bot": false,
"headline": "fix(steer): a locally-edited skill/workflow file is no longer clobbered",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T21:02:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e67c6627cf1b5f2d7192c6110cb7970cf23d0bbd",
"body": "Two bugs found by an independent post-release review of the mirroring\ntier:\n\n- The most-active-branch scan filtered any git for-each-ref line\n containing the substring \"HEAD\" anywhere, not just the origin/HEAD\n symbolic ref -- silently dropping a real branch like\n \"release/HEAD-fix\" from consider\n[…]\nr, unlike update_repository's fetch path, which a\n prior fix already classifies as a clean skip. Both hit the same\n origin, so both now use the same classify_error(...) ==\n \"project-deleted\" check.",
"is_bot": false,
"headline": "fix(core): branch-name substring bug + inconsistent deleted-project skip",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T20:59:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6e4dabe9674aeebedbc0c0485f5d45423489b7e3",
"body": "Two bugs found by an independent post-release review of the flow\nextractor family (the same class already fixed in state.py/data.py):\n\n- The flat-JSX React Router extractor treated every <Route> as an\n independent, absolute route with no nesting awareness, so a nested\n <Route path=\"detail/:id\"> un\n[…]\noute inside a plain string literal (not a comment) remains a known,\ndocumented residual gap -- stripping generic strings would also strip\nthe path=\"...\" attribute values this extractor exists to find.",
"is_bot": false,
"headline": "fix(flow): web-route extraction no longer emits false-positive routes",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T20:57:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2269a409b77a41edfe75dff35c9bdd68be4fbae1",
"body": null,
"is_bot": false,
"headline": "chore(release): 2.48.1",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T20:16:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c0f199dc3577b65eedb5b4932111e3bb842b72b6",
"body": null,
"is_bot": false,
"headline": "docs(changelog): note the triple-quoted-SQL undercount trade-off",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T20:13:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2cd6e2c1550eb5f38f159386a0182ec1651fd5b2",
"body": "It's called from kb/dashboard/server.py, not just within visualize.py\n-- the underscore read as private when it's actually a two-module\ncontract.",
"is_bot": false,
"headline": "refactor(graph): rename _repo_node_sizes to repo_node_sizes",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T20:13:45Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "17b3c71c15d093d29de0802d3170f97592a788b5",
"body": "…eview",
"is_bot": false,
"headline": "docs(changelog): document the state/data/graph fixes from tonight's r…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T20:11:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7eb82a613fe30d7898aabf9134910f86f4113a19",
"body": "Finding #10 (v2.48.0) gave shared nodes their own stable repo_id, which\nthen showed up in the raw GROUP BY repo_id query the fleet overview and\nsite builder use to enumerate repos -- \"(shared)\" is now the single\nlargest node bucket fleet-wide and could displace a real repo when the\nfleet exceeds max\n[…]\n\"/\"(external)\" to\nnamed constants (PACKAGES_REPO/EXTERNAL_REPO) beside SHARED_REPO in\nkb/model.py, replacing the bare string literals at their four call\nsites, per the same review that found the leak.",
"is_bot": false,
"headline": "fix(graph): a shared-node sentinel no longer renders as a fleet repo",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T20:11:51Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cdb57a025fa6f2b7c4d2a53754ceae48eb3f40c3",
"body": "A `# DELETE FROM orders` left in a data-access file, or SQL quoted in a\ndocstring, asserted a read/write dependency that doesn't exist. Blank\nout line comments, block comments, and triple-quoted strings (newlines\npreserved so line numbers on real matches don't shift) before scanning.\nFound by an independent review of the v2.48.0 code.",
"is_bot": false,
"headline": "fix(flow): dataflow extraction no longer reads commented-out SQL as live",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T20:11:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "df6b3cf5d70a034eedb42544089a43cae412d790",
"body": "The guard->assignment regex's lazy gap could cross into an else/elif\nsibling branch, a different method, or past an unrelated second guard\non the same field, asserting a transition the code doesn't actually\nestablish. Reject the match whenever the gap contains a boundary\nkeyword or a second mention of the same receiver+field, and drop a\ntransition whose value is the field name itself (a field copy, not a\nstate literal). Found by an independent review of the v2.48.0 code.",
"is_bot": false,
"headline": "fix(flow): state-diagram extraction no longer emits false transitions",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T20:11:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "6ec4cef06b535e0011052755f4041182765adefd",
"body": "…er ran\n\nThe v2.48.0 gate failure was the misplaced core-suite test failing on\nits own, not the kb suite catching anything -- clarify that distinction\nso the historical record doesn't imply two separate coverage gaps.",
"is_bot": false,
"headline": "docs(changelog): correct release-gate entry to say tests/kb still nev…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T19:55:16Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e0cc417c49fc38a952923b14c265063c548944df",
"body": "release.yml installed only the core package and ran `pytest --ignore=\ntests/kb`, mirroring CI's \"core (no knowledge layer)\" job rather than\nits \"knowledge-layer\" job -- so a broken tests/kb test could tag and\nship a release without ever running. Found cutting v2.48.0: the first\ntag attempt failed th\n[…]\nrate\nknowledge-layer job caught it afterward.\n\nNow installs the [kb] extra (pip install -e \".[dev,kb]\") and runs the\nfull suite, matching what CI's knowledge-layer job already validates\non every push.",
"is_bot": false,
"headline": "fix(ci): release gate now runs the full test suite, kb included",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T19:48:57Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ab2f766dbb3df934366db9bf758abfcab1f18887",
"body": "…Each\n\nThe cytoscape style sheet maps node width/height from a deg data field\non every node, but app.js only set deg in a .forEach() that ran AFTER\nthe graph's first style pass -- so cytoscape logged a console warning\nper node on initial render (\"no mapping for property... try a [deg]\nselector\") bef\n[…]\n the weight-always-present pattern already used for edges,\nso every node carries it from creation. Verified live: the warning is\ngone from a fresh graph --serve render, graph still displays correctly.",
"is_bot": false,
"headline": "fix(graph): compute node degree server-side, not in a post-render for…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T19:46:46Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ba31a482f6b22cd400b3b3f8380d6b6fb898f5d4",
"body": "A shell (or terminal wrapper -- Claude Code's own included) that sets\nFORCE_COLOR made style.ok()/style.warn() emit ANSI codes even under\npytest's non-tty capsys capture, silently breaking any test asserting\na literal plain-text log/output string. Three tests were failing on\nexactly this in one envi\n[…]\nhing the pattern several\nindividual tests (test_logging.py, test_style_helpers.py) already used\nad hoc. Tests that want the colored path still opt in explicitly via\nmonkeypatch.setenv, same as before.",
"is_bot": false,
"headline": "test: neutralize FORCE_COLOR/NO_COLOR for every test",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T19:41:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c94f2015ee9371b73003af49e4e74bf39a7bf785",
"body": "It exercises `index`, which needs the [kb] extra (pydantic) -- CI's\n\"core (no knowledge layer)\" job runs `pytest --ignore=tests/kb` and\npicked this test up anyway since it lived one directory too high,\nfailing there with an unrelated \"needs the knowledge-layer extra\"\nmessage instead of the ConfigError text it was asserting on. Caught\nby v2.48.0's post-tag CI run.",
"is_bot": false,
"headline": "test(config): move the --config CLI test under tests/kb",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T19:08:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "70bf24ae3b727ec8706679d0e941219c6d4c885d",
"body": "Additive/fix release: statediagram graph format, intra-repo dataflow\nreads/writes edges, dashboard breadcrumb cross-linking, the Finding #10\nshared-node repo_id fix, and the --config hard-fail fix.",
"is_bot": false,
"headline": "chore(release): v2.48.0",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T19:06:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "51fba484d1604fdd71a5f516be22dd81a0fcb2f7",
"body": "…nt repo\n\nFinding #10's fix made module/endpoint/topic nodes correctly report a\npseudo-repo like \"(shared)\" instead of a real repo id. The symbol\nbreadcrumb (any search result's \"Blast\" button reaches this) didn't\naccount for that -- it still tried to render Diagram/Wiki/Links crumbs\nlinking to #/re\n[…]\nting module node now shows a clean Lake > module_\nrequests breadcrumb with no dead crumb, Cross-repo only correctly disabled,\nand the provenance drawer showing \"(shared)\" as plain text (never a link).",
"is_bot": false,
"headline": "fix(dashboard): shared-node breadcrumb no longer links to a nonexiste…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T18:07:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "afd4a5860e23ec274180738f356dcf27840ea4d7",
"body": "load_kb_config's precedence chain treated an explicit --config path exactly\nlike an absent auto-discovered file: silently empty, keep going down the\nchain. That let a typo'd or not-yet-created --config path fall through to\n~/.contextlake/kb.toml -- the real global config -- without any signal that\nh\n[…]\ndy covered its own --kb-config.\n\nFour source_cmd tests were relying on the old fallback (passing a\ndeliberately nonexistent --config as shorthand for \"no overrides\") and now\nwrite an empty file first.",
"is_bot": false,
"headline": "fix(config): a missing explicit --config path is now a hard error",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T18:01:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d4057e259f20a6d33acdd5f75a7354063d8b4ae2",
"body": "Finding #10: module/endpoint/topic node ids don't encode a repo (two repos\nimporting \"requests\" produce the identical node), so the store dedupes them\nto one row. SqliteStore.upsert_nodes stamped every node in a shard's batch\nwith that shard's own repo_id, ignoring each Node's own .repo entirely --\n\n[…]\nflow signals have always read it from the\nproducing file's edge, never the shared node's own repo column.\n\nNo store migration needed; existing shared nodes self-correct as each\nrepo is next reindexed.",
"is_bot": false,
"headline": "fix(graph): shared nodes no longer flip owning repo on every reindex",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T17:54:47Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "af8cf1b91225482e3c7872695f1885d030b3fd33",
"body": "…Links\n\nApproved nav model: repo -> node -> its diagram -> its wiki page -> linked\nticket. Wiki/Links are honestly omitted (not shown disabled) when the repo\nhas neither -- verified against both the empty and populated case with a\nreal store, not assumed.\n\nBackend: /api/impact never returned the see\n[…]\ne 1-2 character fragments even though the a11y tree\nreported the full correct labels. Fixed: crumbs no longer shrink: 0 auto,\nthe row scrolls horizontally instead -- verified visually, light and dark.",
"is_bot": false,
"headline": "feat(dashboard): breadcrumb continues repo -> symbol -> Diagram/Wiki/…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T17:10:22Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "44f55d16673b57fea679f521c683392bcb5922a6",
"body": null,
"is_bot": false,
"headline": "docs: note why transitions_to is not in impact's default relation set",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T16:32:17Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2d29b25689070823211c5587dea0aac27f546686",
"body": "Spec C phase 2. New kb/flow/data.py: a literal SELECT/INSERT/UPDATE/DELETE\nin any file's source becomes a reads/writes edge to the matching table/view\nnode the SQL DDL extractor already found, resolved by name repo-wide via\nthe same _resolve_name_refs mechanism an FK references edge uses -- a query\n\n[…]\nw edges\nexisting. Fixed alongside since it's the natural way anyone would ask\n'what breaks if I change this table' -- reads/writes are now default,\nmatching how a references (FK) edge already behaves.",
"is_bot": false,
"headline": "feat(graph): add intra-repo dataflow (reads/writes edges to SQL tables)",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T16:31:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cabb1052c3331b1b15f9acf25c3434d08bfd2556",
"body": "Spec C phase 1 (specs/spec-C-state-and-dataflow-diagrams.md option a): a new\nkb/flow/state.py extractor finds guarded assignments to a status/state/stage\nfield per entity (Python/JS-TS/C#) and emits transitions_to edges only where\na preceding comparison on the same field establishes the source state\n[…]\ning edges once hop budget\nis spent reaching it -- documented, and the CLI/docs examples point at\n--repo (matching classdiagram's own convention) rather than the seed mode\nthat doesn't fully work here.",
"is_bot": false,
"headline": "feat(graph): add statediagram format (entity state machines)",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T16:22:24Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fdae8c0ed7d164e7723f0c16e817bbc019288a94",
"body": "Two repos in a real fleet run hit 'could not be found or you don't have\npermission to view it' during update -- indistinguishable from a genuine\nfetch failure, so they inflated the error count even though, like a\ndeleted branch, there is nothing to fix. classify_error now recognizes\nthis case and update_repository reports it as a skip.",
"is_bot": false,
"headline": "fix(sync): treat a deleted upstream GitLab project as a clean skip",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T16:10:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "652ef8c30b848e6cfff76c81ac4e24f03c041626",
"body": "init already supports six forges and repo_id is host-agnostic since 2.47.0.",
"is_bot": false,
"headline": "docs(pkg): drop stale GitLab-only claim from package docstring",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T15:45:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "75294a2ba6c03e53d390d02708f39579f633c5c6",
"body": null,
"is_bot": false,
"headline": "chore(release): 2.47.0",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T15:34:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "39e7ea2ec38f0fc6d3e71ec49af0564a656af281",
"body": "repo_id was a repo's path relative to --workspace, so the same physical repo\ngot a different id from a different index root: duplicate ids, broken\npath-based owners/graph/impact views. repo_id is now derived from the repo's\norigin remote (repo_identity.py), normalized so SSH and HTTPS forms of the\ns\n[…]\nparse every repo once to pick up the new ids\n(content doesn't change, only identity) and lose embeddings for migrated\nrepos -- re-run `embed` afterward if semantic search is enabled. See\nCHANGELOG.md.",
"is_bot": false,
"headline": "feat(kb)!: canonical repo_id from git remote, with automatic migration",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T15:31:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "964e32f4d532714cdd7d8ad747ab01efc722723c",
"body": null,
"is_bot": false,
"headline": "chore(release): 2.46.0",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T15:00:10Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "d8d4d5c6d33fdd34510e0720cad961eef0c24424",
"body": "Adds it to visualize.md's format list (matching classdiagram's style) and\nthe --c4 unsupported-formats note, records both this session's fixes in\nCHANGELOG.md's Unreleased section, and regenerates site/llms-full.txt.",
"is_bot": false,
"headline": "docs: document the sequencediagram graph format",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T14:49:26Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bcdc7e6c2650671e7d5fe283da9f32c38a988168",
"body": "`contextlake graph --node/--name/--search ID --format sequencediagram` walks\noutgoing `calls` edges depth-first from the view's single seed node, each\ncaller's callees ordered by call-site line (already carried by every calls\nedge's provenance -- no new extraction needed, just a consumer for data\nal\n[…]\na separate \"call-ordering extraction\" lane, folded into\nthis once investigation showed the ordering data (provenance.source_line on\nevery calls edge) already existed; the only real gap was a renderer.",
"is_bot": false,
"headline": "feat(kb): add a Mermaid sequenceDiagram graph format",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T14:48:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5e4c746cbbcac2b9c937389c6e848bf5878b0fc1",
"body": "_resolve_name_refs deduplicated repeated (src, dst) references by first-seen\nin tree-sitter's capture order, which is not guaranteed to match source\norder -- a call site hit twice from the same caller could surface an\narbitrary later line instead of the first one. Sorting refs by line before\nresolution makes the surviving line deterministic (the lowest), which a\nline-ordered consumer like a sequence diagram depends on.",
"is_bot": false,
"headline": "fix(kb): deterministic lowest-line dedup for repeated call/inherit refs",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T14:48:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "51e2bc06116977a50c2c2190e6055ba85477cc42",
"body": "…code\n\nREADME.md, docs/cli-reference.md, docs/connect-enrich.md, docs/storage.md,\nand the `ingest` command's own --help text all enumerated the built-in\nsource types or steering files and had drifted after the graphql source and\n.vscode/mcp.json emitter landed -- the same undercount-drift class the\nDevin doc fix caught. Adds a worked graphql example to connect-enrich.md\nmatching the existing api one. Also records the R5 additions (Unreleased)\nin CHANGELOG.md and regenerates site/llms-full.txt.",
"is_bot": false,
"headline": "docs: catch up source-type and steering-file lists after graphql + vs…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T14:35:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "28a3e90b81accd4c4fdba807621408005a1cce25",
"body": "docs/serve.md previously told Devin users to add the MCP server the same way\nas Windsurf, via a repo-committed JSON file. That's wrong: Devin's MCP\nconnections are account/org-level (mcp.devin.ai, API key + org header), not\nread from a file in the repo it's working in -- contextlake cannot\nself-regi\n[…]\nin.\n\nAlso documents the new .vscode/mcp.json wiring (both automatic via `steer`\nand by hand) and adds VS Code to the \"any MCP client\" list. Regenerated\nsite/llms-full.txt from the updated docs source.",
"is_bot": false,
"headline": "docs(serve): correct the Devin MCP wiring claim, document VS Code",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T14:31:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3b1847a646e77f62a88dc2981e04ac1df74c595a",
"body": "VS Code's MCP config uses a `servers` top-level key, a different schema from\nthe `mcpServers` key that Claude Code/Windsurf/Cursor read from .mcp.json --\nso it needs its own file, not a copy of the existing one. The per-server\nentry (command/args) is identical, so `contextlake steer` now merges it i\n[…]\neserving any other servers already configured.\n\nAlso drops the unverified \"(Windsurf / Devin)\" claim from the generated\n.windsurfrules heading -- no source this session confirms Devin reads that\nfile.",
"is_bot": false,
"headline": "feat(kb): emit .vscode/mcp.json alongside .mcp.json in steer",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T14:31:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4722b52243f6a5fd011e932914cc3edbf213c51e",
"body": "POSTs a query+variables to one endpoint and maps records in the response's\n`data` payload the same way ApiSource maps JSON records, so RAG aggregation\ncovers GraphQL APIs alongside REST. Auth is a bearer token read from an env\nvar named in config, never stored. Verified against a live local HTTP\nserver, not just mocked unit tests.",
"is_bot": false,
"headline": "feat(kb): add a GraphQL source type for document ingest",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T14:30:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "918c14c3701cbfae256da2d5e5ba8bc101fcb879",
"body": null,
"is_bot": false,
"headline": "chore(release): 2.45.1",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T14:11:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9db9669f00e6762982141975ac9a63649eff9f00",
"body": "…olesale\n\nload_kb_config() merged each top-level TOML table via a plain dict.update() per\nfile in the precedence chain. For [llm]/[kb]/[embeddings], that meant a local\n.contextlake.kb.toml setting only one field (e.g. [llm] model = \"...\") replaced\nthe entire table, silently reverting sibling fields \n[…]\not merge\nper-entry).\n\nVerified against the actual failure scenario: global [llm] enabled=true\nprovider=anthropic model=X, local [llm] model=Y -> enabled/provider now survive,\nonly model is overridden.",
"is_bot": false,
"headline": "fix(kb): deep-merge scalar config tables instead of replacing them wh…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T14:10:34Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "edfdcd280dde6e07493816e1321ea14feeb8d584",
"body": "The live progress bar renders on stderr while per-item status lines go to\nstdout. Both share one terminal cursor, and the bar padded each frame out to\nthe full width, leaving the cursor at the right margin: every frame stayed in\nthe scrollback with the next status line welded onto its right edge.\n\nB\n[…]\n- stop ok()'s rstrip from eating the space in \"<verb> complete: <counts>\"\n\nVerified by rendering a real run under a pty: no stranded frames, no padding\nruns, no wrapped lines, no multi-line git dumps.",
"is_bot": false,
"headline": "fix(cli): keep the terminal readable while a long run is in flight",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T13:29:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "33e6b511bac355b3461080a571b6e5721650eca7",
"body": "…e writes\n\n- shard_path interpolated an untrusted repo_id straight into a path, so an MCP tool arg\n like '../../x' escaped the store and read an arbitrary .json (read happens before schema\n validation, and the resulting error text can echo content back to the caller). Reject any\n id that resolves\n[…]\n resolve every endpoint's repo in batched queries and insert with executemany (same flag,\n far fewer round trips at fleet scale).\nRegression tests added for the traversal and the wedged-store paths.",
"is_bot": false,
"headline": "fix(kb): block shard-path traversal, unwedge the vec store, batch edg…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T12:56:30Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "379b84ab28e8811ee8a26ff794b4f303aa601fdc",
"body": "…ed stores\n\n- _index_workspace guarded only the parse step ('one repo must not abort the workspace')\n but not _persist; a single repo's write error (NUL byte in a name, over-long path) crashed\n the whole fleet index with an uncaught traceback. Guard _persist the same way -> one repo\n degrades, th\n[…]\nanch, so OK is never a lie.\n- close the store on the _guard_store early-returns (index/embed/wiki) and in\n _canonical_repo_id, which previously leaked a SQLite handle (WAL/lock state) on those paths.",
"is_bot": false,
"headline": "fix(kb): guard fleet-index persist, honest doctor verdict, close leak…",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T08:43:11Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "40b8b3e92d1e33a80c4a8caa59975a94734414fa",
"body": "Two sibling-inconsistent subprocess calls lacked a timeout: safety.stash_changes\n('git stash push', called inside the sync ThreadPool so one hang stalls the whole run)\nand core._fetch_projects_page_glab ('glab api', a network call in a retry loop where a\nhang can't be rescued). Add timeouts matching\n[…]\ntall raises\ninstead of hanging. Also strip per-entry whitespace in is_safe_branch so a natural\n'main, master, develop' config doesn't silently treat all but the first as unsafe.\nRegression test added.",
"is_bot": false,
"headline": "fix: add missing subprocess timeouts + strip whitespace in safe_branches",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T08:40:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "648b989565f64fbaab22295bcbf37ae3b3b3f009",
"body": "A small review model often emits a valid \"score\" but breaks the JSON elsewhere (unescaped\ninner quotes in a later value), so json.loads fails and the score must be recovered from the\nraw text. The labeled-score regex required the separator immediately after the keyword and\nchoked on the JSON form (a\n[…]\nween \"score\" and the colon), so a review\nthat clearly scored 0.95 falsely abstained. Allow an optional quote/space before the separator;\nthe unlabeled-ordinal guard still holds. Regression test added.",
"is_bot": false,
"headline": "fix(wiki): recover a labeled score from the JSON \"score\": form",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T08:23:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3e2c5aac13f58e14f389801fd9838bb6b6d406c7",
"body": null,
"is_bot": false,
"headline": "chore(release): 2.45.0",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T07:28:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "56b98631af3aec1e5a72f9ebbd76a8095e336432",
"body": "Drops helper scripts and a test that only ever ran locally, and simplifies the\ncontributor notes to standard guidance (no hardcoded secrets/credentials/paths; use\nplaceholders). Local pre-publish checks run from developer tooling outside the repo.",
"is_bot": false,
"headline": "chore: remove in-repo dev-only tooling and tidy contributor docs",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T06:58:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "59ef00d6b981f3559e2857d2a047fc2a9bd8c39e",
"body": null,
"is_bot": false,
"headline": "docs(contributing): fix article agreement in the guard description",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T05:45:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "80d9f04da5a04baeb8baf63d5daa566d12ecc025",
"body": "Two gaps let stray identifiers slip through before: the release workflow ran\npytest --ignore=tests/kb, so the publish guard (under tests/kb, no kb deps needed) never\ngated a publish; and there was no local check at commit time. Add a fail-closed release-gate\nstep that runs the guard with the denylis\n[…]\nt -> refuse to publish), and a\n.githooks/pre-commit hook that scans staged changes against the git-ignored denylist and\nblocks the commit on any hit (enable with: git config core.hooksPath .githooks).",
"is_bot": false,
"headline": "ci: enforce the publish guard on every commit and at release",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T05:34:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b77baaf10a31fc002cf40449f915df4198351a86",
"body": "doctor showed a green wiki-LLM whenever the model FILE was present, even if\nllama-cpp-python (the runtime, no prebuilt wheel on some Pythons e.g. 3.14) was not\ninstalled — so a user saw ✓ then wiki failed. Add a tri-state to _check (None -> ⚠) and\nverify the llama_cpp runtime is importable; when it \n[…]\nt, report ⚠ with the exact install\nhint. Stays advisory (doctor still exits 0 — wiki is an optional tier). Found via playground\ntesting where wiki failed despite a green doctor. Regression test added.",
"is_bot": false,
"headline": "fix(doctor): warn when the builtin wiki-LLM runtime is missing",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T01:47:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2e13ca80eb3e9aa0ec42a09b010a753324a8cca8",
"body": "The offline export test rejects any http://; the inline data-URI favicon added to the\ndashboard shell carries the SVG xmlns (http://www.w3.org/2000/svg), a standards identifier\nthe browser never fetches. Strip w3.org namespace URNs before the network-reference check so\nthe boundary still catches real external URLs/CDNs but not xmlns declarations.",
"is_bot": false,
"headline": "test(dashboard): allow W3C namespace URNs in the offline-boundary check",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T01:40:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5600b07e9925bdac63c5defcea90f6281ab063d5",
"body": "The dashboard shell declared no icon, so every browser auto-requested /favicon.ico and\nlogged a 404 console error (and the tab had no icon). Add an offline inline SVG data-URI\nfavicon (pebble-in-lake, brand teal) — no new server route, self-contained. Verified\nheadless: favicon served, 0 console errors across all six routes.",
"is_bot": false,
"headline": "fix(dashboard): add an inline favicon to stop the /favicon.ico 404",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T01:39:54Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "2b65589785ff2c6d651c3d322469a8c140c43a4f",
"body": null,
"is_bot": false,
"headline": "chore: gitignore the local playground/ testing sandbox",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T01:31:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e30196d8a830788802ee9cfa89104d1adf5b0c54",
"body": "The test asserted 'not downloaded' but doctor inspects the machine-global default cache\n(~/.contextlake/models), so any developer who had already fetched the built-in models saw\n'downloaded' and the test failed locally (it only passed in a clean CI). Point cache_dir at\nan empty tmp dir in the test config so the filesystem presence report is deterministic\nregardless of the machine's real model cache.",
"is_bot": false,
"headline": "test(kb): make doctor builtin-model-presence test hermetic",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T01:29:51Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "05fcae2790b41d063d56bb755ca35c35bda7c686",
"body": "gen_search_index.py (since d48cf64) and scan_public.py listed the real private identifiers as\nstring literals to detect them — but those files are git-tracked and published, so the\ndetector WAS the leak (the publish guard correctly flagged both). Load the token list\nfrom outside the repo instead (CO\n[…]\n is configured (an unattended\ndeploy must not publish blind); gen_search_index.py warns and continues (the deploy gate is\nthe backstop). Publish guard now green; zero private tokens in tracked source.",
"is_bot": false,
"headline": "fix(site): stop hardcoding private tokens in the search/deploy detectors",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T01:22:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2c2179581cb8d4c6d7e3f641ffce2987403121c5",
"body": "At 390px, long inline <code> tokens (file paths, identifiers) on the changelog (46px) and\ninternals (146px) pages pushed the body wider than the viewport, causing horizontal scroll.\nAllow inline code to break with overflow-wrap:break-word; it's inert on <pre> code\n(white-space:pre keeps its own scroll). Verified: 0 horizontal overflow across all 30 pages\nat 390px.",
"is_bot": false,
"headline": "fix(site): prevent horizontal overflow from long inline code on mobile",
"author_name": "Sayak Sarkar",
"author_login": "sayak-sarkar",
"committed_at": "2026-07-25T01:14:41Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 96,
"commits_last_year": 604,
"latest_release_at": "2026-07-26T19:36:22Z",
"latest_release_tag": "v2.54.0",
"releases_from_tags": false,
"days_since_last_push": 0,
"active_weeks_last_year": 27,
"days_since_latest_release": 0,
"mean_days_between_releases": 0.1
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": true,
"health_percentage": 100,
"has_issue_template": false,
"has_code_of_conduct": true,
"has_pull_request_template": true
},
"ecosystem": {
"packages": [
{
"name": "contextlake",
"exists": true,
"license": "MIT",
"keywords": [
"context",
"knowledge-graph",
"mcp",
"ai",
"code-search",
"gitlab",
"git",
"mirror",
"cli",
"glab",
"workspace",
"offline-first",
"semantic-search",
"developer-tools",
"Development Status :: 4 - Beta",
"Environment :: Console",
"Intended Audience :: Developers",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.9",
"Topic :: Software Development",
"Topic :: Software Development :: Version Control :: Git"
],
"ecosystem": "pypi",
"matches_repo": true,
"registry_url": "https://pypi.org/project/contextlake/",
"is_deprecated": false,
"latest_version": "2.54.0",
"repository_url": "https://github.com/sayak-sarkar/contextlake",
"versions_count": 69,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": "2026-06-22T14:39:49.345411Z",
"latest_published_at": "2026-07-26T19:36:10.911217Z",
"latest_version_yanked": null,
"days_since_latest_publish": 0
}
]
},
"popularity": {
"forks": 1,
"stars": 2,
"watchers": 0,
"fork_history": {
"days": [
{
"date": "2026-07-24",
"count": 1
}
],
"complete": true,
"collected": 1,
"total_forks": 1
},
"star_history": null,
"open_issues_and_prs": 0
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [
"examples"
],
"has_llms_txt": true,
"has_dockerfile": true,
"has_mcp_signal": false,
"bootstrap_files": [],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [],
"largest_source_bytes": 373304,
"source_files_sampled": 208,
"oversized_source_files": 3,
"agent_instruction_files": [],
"agent_instruction_max_bytes": null
},
"dependencies": {
"manifests": [
"pyproject.toml"
],
"advisories": {
"error": "No resolved dependencies carried a version and a supported ecosystem",
"scope": "repository_graph",
"source": null,
"findings": [],
"collected": false,
"malicious": [],
"truncated": false,
"by_severity": {},
"advisory_count": 0,
"affected_count": 0,
"assessed_count": 0,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 29,
"direct_affected_count": 0
},
"ecosystems": [
"pypi"
],
"dependencies": [],
"all_dependencies": {
"error": null,
"source": "github-sbom",
"packages": [
{
"name": "build",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "fastembed",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "huggingface-hub",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "llama-cpp-python",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "mcp",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "model2vec",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "pydantic",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "pytest",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "pytest-cov",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "ruff",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "setuptools",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "sqlite-vec",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tomlkit",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-c",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-c-sharp",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-cpp",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-go",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-hcl",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-java",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-javascript",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-kotlin",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-php",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-python",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-ruby",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-rust",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-scala",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "tree-sitter-typescript",
"direct": false,
"version": null,
"ecosystem": "pypi"
},
{
"name": "twine",
"direct": false,
"version": null,
"ecosystem": "pypi"
}
],
"collected": true,
"truncated": false,
"total_count": 29,
"direct_count": 0,
"indirect_count": 29
}
},
"maintainership": {
"issues": {
"open_prs": 0,
"merged_prs": 1,
"open_issues": 0,
"closed_ratio": null,
"closed_issues": 0,
"closed_unmerged_prs": 0
},
"bus_factor": 1,
"bot_contributors": 0,
"top_contributors": [
{
"type": "User",
"login": "sayak-sarkar",
"commits": 647,
"avatar_url": "https://avatars.githubusercontent.com/u/1418735?v=4"
}
],
"contributors_sampled": 1,
"top_contributor_share": 1
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"ci.yml",
"release.yml"
],
"has_docs_dir": true,
"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": null,
"reason": "no pull request found",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 0,
"reason": "Found 0/30 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 10,
"reason": "project has 18 contributing companies or organizations",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
},
{
"name": "Dangerous-Workflow",
"score": 10,
"reason": "no dangerous workflow patterns detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
},
{
"name": "Dependency-Update-Tool",
"score": 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": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 0,
"reason": "dependency not pinned by hash detected -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 0,
"reason": "no SAST tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 10,
"reason": "security policy file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
},
{
"name": "Signed-Releases",
"score": 0,
"reason": "Project has not signed or included provenance with any releases.",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
},
{
"name": "Token-Permissions",
"score": 0,
"reason": "detected GitHub workflow tokens with excessive permissions",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
},
{
"name": "Vulnerabilities",
"score": 10,
"reason": "0 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "59f37704ac168d457b742321958b3061af67b94b",
"ran_at": "2026-07-26T19:38:15Z",
"aggregate_score": 3.9,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": true,
"has_dependabot_config": false
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-26T19:36:16Z",
"oldest_open_prs": [],
"last_merged_pr_at": "2026-07-02T04:22:37Z",
"ci_last_conclusion": null,
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/sayak-sarkar/contextlake",
"host": "github.com",
"name": "contextlake",
"owner": "sayak-sarkar"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 61,
"inputs": {
"security": 39,
"vitality": 80,
"community": 43,
"governance": 60,
"engineering": 76
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 80,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 73,
"inputs": {
"commits_last_year": 604,
"human_commit_share": 1,
"days_since_last_push": 0,
"active_weeks_last_year": 27
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 0 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 0
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "27/52 weeks with commits",
"points": 18.7,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 27
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "604 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 604
}
}
],
"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": null,
"notes": [],
"value": 90,
"inputs": {
"releases_count": 96,
"latest_release_tag": "v2.54.0",
"releases_from_tags": false,
"days_since_latest_release": 0,
"mean_days_between_releases": 0.1
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "96 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 96
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 0 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 0
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~0.1 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 0.1
}
}
],
"max_points": 27
},
{
"key": "openssf_scorecard_signed_releases",
"name": "OpenSSF Scorecard: Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "abandonment",
"band": "excellent",
"name": "Abandonment",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"cap": null,
"state": "unverified",
"guards": [],
"signals": [],
"red_flag": false,
"multiplier_pct": 100,
"declared_reason": null,
"unverified_reason": "repository_too_young",
"unanswered_open_prs": null,
"unanswered_open_issues": null,
"days_since_last_merged_pr": null,
"days_since_last_human_commit": null,
"days_since_last_human_commit_is_floor": false
},
"components": [
{
"key": "project_is_still_maintained",
"name": "Project is still maintained",
"detail": "maintenance record not established from the collected data",
"points": 100,
"status": "met",
"details": [
{
"code": "abandonment_unverified",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Is the project alive — is code being written and are releases shipping?"
},
{
"key": "community",
"band": "at_risk",
"name": "Community & Adoption",
"value": 43,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 1,
"stars": 2,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "2 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 2
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "1 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 1
}
}
],
"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": "excellent",
"name": "Community health",
"note": null,
"notes": [],
"value": 92,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": true,
"has_issue_template": false,
"has_code_of_conduct": true,
"has_pull_request_template": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 18,
"status": "met",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 13.5,
"status": "met",
"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": 6.3,
"status": "met",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "moderate",
"name": "Sustainability & Governance",
"value": 60,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 20,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 1,
"top_contributor_share": 1
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 100% of commits",
"points": 0,
"status": "missed",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 100
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "1 contributors",
"points": 1.4,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 1
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 18 contributing companies or organizations",
"points": 10,
"status": "met",
"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": 1,
"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": "1/1 decided PRs merged",
"points": 38.2,
"status": "met",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 1,
"decided": 1
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "moderate",
"name": "Ownership & stewardship",
"note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"verified_domain"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 62,
"inputs": {
"followers": 101,
"owner_type": "User",
"is_verified": null,
"owner_login": "sayak-sarkar",
"public_repos": 108,
"account_age_days": 5282
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "personal (user) account",
"points": 10,
"status": "partial",
"details": [
{
"code": "owner_personal",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": "not applicable to user accounts",
"points": 0,
"status": "excluded",
"details": [
{
"code": "not_applicable_to_user_accounts",
"params": {}
}
],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "101 followers of sayak-sarkar",
"points": 14.4,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 101,
"login": "sayak-sarkar"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "108 public repos, account ~14 yr old",
"points": 25,
"status": "met",
"details": [
{
"code": "public_repos",
"params": {
"count": 108
}
},
{
"code": "account_age_years",
"params": {
"years": 14
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"contextlake"
],
"ecosystems": "pypi",
"any_deprecated": false,
"min_days_since_publish": 0
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "1 package(s) on pypi",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 1,
"ecosystems": "pypi"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 0 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 0
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "69 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 69
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "good",
"name": "Engineering Quality",
"value": 76,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"openssf_scorecard_ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 60,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "2 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 2
}
}
],
"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": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "excellent",
"name": "Documentation",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"topics": [
"ai",
"cli",
"code-search",
"context",
"gitlab",
"knowledge-graph",
"mcp",
"developer-tools",
"git",
"offline-first",
"python",
"semantic-search"
],
"has_wiki": true,
"homepage": "http://sayak.in/contextlake/",
"has_readme": true,
"has_docs_dir": true,
"has_description": true
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 30,
"status": "met",
"details": [],
"max_points": 30
},
{
"key": "documentation_directory",
"name": "Documentation directory",
"detail": null,
"points": 25,
"status": "met",
"details": [],
"max_points": 25
},
{
"key": "documentation_homepage_site",
"name": "Documentation / homepage site",
"detail": "http://sayak.in/contextlake/",
"points": 15,
"status": "met",
"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": "12 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 12
}
}
],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "at_risk",
"name": "Security",
"value": 39,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "at_risk",
"name": "Security posture",
"note": "Excluded from scoring (no data or not applicable): CI-Tests. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"ci_tests"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 39,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 17,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 1,
"scorecard_aggregate": 3.9
},
"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": "no pull request found",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_data",
"params": {}
}
],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 0/30 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 18 contributing companies or organizations",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "dangerous_workflow",
"name": "Dangerous-Workflow",
"detail": "no dangerous workflow patterns detected",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "dependency_update_tool",
"name": "Dependency-Update-Tool",
"detail": "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 detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "no SAST tool detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "signed_releases",
"name": "Signed-Releases",
"detail": "Project has not signed or included provenance with any releases.",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "token_permissions",
"name": "Token-Permissions",
"detail": "detected GitHub workflow tokens with excessive permissions",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "vulnerabilities",
"name": "Vulnerabilities",
"detail": "0 existing vulnerabilities detected",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "high_risk_jurisdiction_exposure",
"band": "excellent",
"name": "High-Risk Jurisdiction Exposure",
"note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
"notes": [
{
"code": "jurisdiction_evidence_limits",
"params": {}
}
],
"value": 100,
"inputs": {
"meaning": "self-published location evidence; not nationality or citizenship",
"red_flag": false,
"exposures": [],
"policy_countries": [
"Russia",
"Iran",
"North Korea"
],
"review_only_matches": 0,
"assessed_self_published_locations": 12
},
"components": [
{
"key": "policy_exposure_multiplier",
"name": "Policy exposure multiplier",
"detail": "no confirmed policy-scope location match",
"points": 100,
"status": "met",
"details": [
{
"code": "jurisdiction_no_match",
"params": {}
}
],
"max_points": 100
}
]
}
],
"description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
},
{
"key": "ai_readiness",
"band": "at_risk",
"name": "AI Readiness",
"value": 43,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "moderate",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 55,
"inputs": {
"has_llms_txt": true,
"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": "llms.txt present",
"points": 15,
"status": "met",
"details": [
{
"code": "llms_txt_present",
"params": {}
}
],
"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": null,
"notes": [],
"value": 32,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [],
"has_dockerfile": true,
"typed_language": false,
"bootstrap_files": [],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [],
"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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "Dockerfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Dockerfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "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": "dependency not pinned by hash detected -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "moderate",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 54,
"inputs": {
"primary_language": "Python",
"largest_source_bytes": 373304,
"source_files_sampled": 208,
"oversized_source_files": 3
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Python without a type-check config",
"points": 0,
"status": "missed",
"details": [
{
"code": "no_typecheck_config_language",
"params": {
"language": "Python"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "3/208 source files over 60KB",
"points": 54.2,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 208,
"oversized": 3
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "at_risk",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 40,
"inputs": {
"example_dirs": [
"examples"
],
"has_mcp_signal": false,
"api_schema_files": []
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 40
},
{
"key": "mcp_server",
"name": "MCP server",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "runnable_examples",
"name": "Runnable examples",
"detail": "examples",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "examples"
}
}
],
"max_points": 40
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
"deps.dev does not index pypi:contextlake@2.54.0; advisories assessed against the repository dependency graph instead",
"No resolved dependencies carried a version and a supported ecosystem"
],
"report_type": "repository",
"generated_at": "2026-07-26T19:38:21.791885Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/s/sayak-sarkar/contextlake.svg",
"full_name": "sayak-sarkar/contextlake",
"license_state": "standard",
"license_spdx": "MIT"
}