Звіт у форматі JSON машиночитний
{
"data": {
"repo": {
"topics": [],
"is_fork": false,
"size_kb": 14090,
"has_wiki": false,
"homepage": "https://msgvault.io",
"languages": {
"Go": 9628635,
"Nix": 2770,
"Shell": 22115,
"Makefile": 9361,
"Dockerfile": 2238,
"PowerShell": 33420,
"Go Template": 11055
},
"pushed_at": "2026-07-22T04:46:41Z",
"created_at": "2026-01-28T10:49:55Z",
"owner_type": "Organization",
"updated_at": "2026-07-21T22:45:40Z",
"description": "Archive a lifetime of email and chat. Offline search, analytics, and AI query over your full message history. Powered by SQLite and DuckDB",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "Go",
"significant_languages": [
"Go"
]
},
"owner": {
"blog": "https://kenn.io",
"name": "Kenn Software",
"type": "Organization",
"login": "kenn-io",
"company": null,
"location": null,
"followers": 133,
"avatar_url": "https://avatars.githubusercontent.com/u/259885253?v=4",
"created_at": "2026-02-06T14:36:48Z",
"is_verified": null,
"public_repos": 12,
"account_age_days": 165
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v0.18.0",
"kind": "minor",
"published_at": "2026-07-16T19:01:21Z"
},
{
"tag": "v0.17.1",
"kind": "patch",
"published_at": "2026-07-07T03:24:37Z"
},
{
"tag": "v0.17.0",
"kind": "minor",
"published_at": "2026-07-05T00:46:57Z"
},
{
"tag": "v0.16.0",
"kind": "minor",
"published_at": "2026-06-18T23:43:00Z"
},
{
"tag": "v0.15.2",
"kind": "patch",
"published_at": "2026-06-10T13:47:04Z"
},
{
"tag": "v0.15.1",
"kind": "patch",
"published_at": "2026-06-04T01:15:52Z"
},
{
"tag": "v0.15.0",
"kind": "minor",
"published_at": "2026-05-29T00:20:27Z"
},
{
"tag": "v0.14.1",
"kind": "patch",
"published_at": "2026-04-22T19:20:31Z"
},
{
"tag": "v0.14.0",
"kind": "minor",
"published_at": "2026-04-21T17:09:50Z"
},
{
"tag": "v0.13.1",
"kind": "patch",
"published_at": "2026-04-15T14:22:53Z"
},
{
"tag": "v0.13.0",
"kind": "minor",
"published_at": "2026-04-15T02:03:41Z"
},
{
"tag": "v0.12.1",
"kind": "patch",
"published_at": "2026-04-10T16:38:19Z"
},
{
"tag": "v0.12.0",
"kind": "minor",
"published_at": "2026-04-09T21:48:04Z"
},
{
"tag": "v0.11.0",
"kind": "minor",
"published_at": "2026-03-25T00:26:46Z"
},
{
"tag": "v0.10.0",
"kind": "minor",
"published_at": "2026-03-18T18:50:31Z"
},
{
"tag": "v0.9.0",
"kind": "minor",
"published_at": "2026-02-26T20:48:02Z"
},
{
"tag": "v0.8.0",
"kind": "minor",
"published_at": "2026-02-25T02:52:20Z"
},
{
"tag": "v0.7.0",
"kind": "minor",
"published_at": "2026-02-09T03:16:18Z"
},
{
"tag": "v0.6.5",
"kind": "patch",
"published_at": "2026-02-07T13:05:32Z"
},
{
"tag": "v0.6.4",
"kind": "patch",
"published_at": "2026-02-06T20:58:35Z"
},
{
"tag": "v0.6.3",
"kind": "patch",
"published_at": "2026-02-06T14:37:10Z"
},
{
"tag": "v0.6.2",
"kind": "patch",
"published_at": "2026-02-06T13:18:25Z"
},
{
"tag": "v0.6.1",
"kind": "patch",
"published_at": "2026-02-06T00:30:38Z"
},
{
"tag": "v0.6.0",
"kind": "minor",
"published_at": "2026-02-05T17:03:15Z"
},
{
"tag": "v0.5.2",
"kind": "patch",
"published_at": "2026-02-05T03:26:54Z"
},
{
"tag": "v0.5.1",
"kind": "patch",
"published_at": "2026-02-05T02:45:29Z"
},
{
"tag": "v0.5.0",
"kind": "minor",
"published_at": "2026-02-05T00:42:29Z"
},
{
"tag": "v0.4.0",
"kind": "minor",
"published_at": "2026-02-03T16:42:06Z"
},
{
"tag": "v0.3.0",
"kind": "minor",
"published_at": "2026-02-03T02:46:20Z"
},
{
"tag": "v0.2.0",
"kind": "minor",
"published_at": "2026-02-02T23:21:36Z"
},
{
"tag": "v0.1.4",
"kind": "patch",
"published_at": "2026-02-02T17:28:07Z"
},
{
"tag": "v0.1.3",
"kind": "patch",
"published_at": "2026-02-02T17:15:27Z"
},
{
"tag": "v0.1.2",
"kind": "patch",
"published_at": "2026-02-02T12:23:55Z"
},
{
"tag": "v0.1.0",
"kind": "minor",
"published_at": "2026-02-02T12:08:12Z"
}
],
"recent_commits": [
{
"oid": "a668365573992cd67c4310fbf23c85462de18ba0",
"body": "A Granola note can contain a bare calendar date where the API normally returns an RFC3339 timestamp. Go's default time decoder rejected that field before archival, leaving the entire note missing and making full syncs report a partial failure.\n\nAccept exact date-only values across note, calendar, an\n[…]\nosts. Other malformed values remain invalid, existing time.Time model interfaces stay unchanged, and raw API bytes are still preserved.\n\nGenerated with Codex\nCo-authored-by: Codex <noreply@openai.com>",
"is_bot": false,
"headline": "fix: accept Granola date-only timestamps (#496)",
"author_name": "Marius van Niekerk",
"author_login": "mariusvniekerk",
"committed_at": "2026-07-21T22:25:57Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "356c4730139c9d9ce9213e131d4113c2fe7f815a",
"body": "Discord guild archives currently require separate tooling and cannot participate in msgvault search, retention, or scheduled synchronization. This adds a native read-only importer so bot-accessible guild history can live alongside existing message providers in the same archive.\n\nEach guild is an ind\n[…]\nn automation, and normalized reactor identities. Raw message payloads and stable reaction summaries remain available for future expansion.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(discord): import guild history (#491)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-20T02:20:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5dbfdabb08f844dd3b6deed03dac31388a43eeda",
"body": "Two granola tests asserted rendered timestamp strings (`CAST(sent_at AS TEXT)` / raw text scan). PostgreSQL renders `timestamptz` in the session timezone, so `make test-pg` fails in `internal/granola` on any non-UTC machine (e.g. Africa/Johannesburg: \"2026-06-01 22:00:00+02\" does not contain \"2026-0\n[…]\ning probes: `15:00:00-05:00` stored **is** `20:00:00Z`.\n\nVerified on SQLite and PostgreSQL from a UTC+2 machine with no TZ/PGTZ pinning.\n\nCo-authored-by: Matt Richmond <m-j-r@users.noreply.github.com>",
"is_bot": false,
"headline": "fix: make granola sent_at assertions timezone-independent (#490)",
"author_name": "Matt Richmond",
"author_login": "m-j-r",
"committed_at": "2026-07-19T13:45:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ace01073fb229518c808d030e75c828b08230fbb",
"body": "The changelog is a primary way returning users discover recent releases, but it was buried below secondary documentation sections. Move it into the initial standalone navigation block after Web Server so release notes are easier to find while keeping the existing URL unchanged.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "docs: promote changelog in navigation (#487)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-16T20:44:37Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bf5912aebff8d42c62d1a9f25fbc842fa144cb6c",
"body": "## Summary\n- Updated `vendorHash` to `sha256-ykrI7CRnfb5jcfaLRXJ0yDrU7GADz2rEJmVq2vUA68E=`\n- Updated version to `0.18.0`\n\nAutomated update via `scripts/update-nix-flake.sh`.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Update nix flake for v0.18.0 (#485)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-16T20:11:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "339c49a34acce0f4764c277fc92331eb45f4a676",
"body": "msgvault 0.18.0 adds several large user-facing surfaces, while the\npublic documentation still described loose-only attachment storage and\nomitted new REST, MCP, agent-skill, provider, and Windows details. That\ndrift could send users to incorrect routes or maintenance workflows and\nleft the release c\n[…]\n\nimplementation. MCP guidance distinguishes archive-wide semantic search\nfrom the literal, keyword-only search available within a single message.\n\n---------\n\nCo-authored-by: Codex <noreply@openai.com>",
"is_bot": false,
"headline": "docs: document the 0.18.0 release (#486)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-16T20:05:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "58c0af0fc2b392acbc8a50deb2f26a2e0ac06231",
"body": "Build and refresh the analytics cache through one explicit publication boundary so readers never open partial Parquet output. The daemon also builds a stale or missing cache before serving and keeps startup progress readable.\n\n## Cache lifecycle\n\n- Export every dataset into a same-filesystem staging\n[…]\nisplayed log lines; complete records remain in the daemon log.\n- PostgreSQL and explicit live-SQL analytics do not use the Parquet cache.\n\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Make analytics cache publication transactional (#483)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-16T14:43:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a723e5dc600ae8ec26efa40a50f479af8f15184d",
"body": "Background daemon lifecycle commands now use one canonical `msgvault daemon start|status|stop|restart` interface, reducing operator friction and keeping the recommended workflow consistent. Existing `msgvault serve` lifecycle forms remain silent hidden aliases so automation continues to work.\n\nUse `\n[…]\nt` is omitted or zero, while an explicit port is honored for remote, container, and direct-HTTP deployments that require a stable mapping.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Normalize daemon lifecycle CLI (#484)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-16T14:43:07Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1a959f99ff47f84c8d86516df623af0b6da7aadb",
"body": "Closes #456.\n\nThis PR archives Granola and Circleback meeting notes and transcripts in msgvault and adds a read-only Meetings mode to the TUI. Meetings use the existing message, search, daemon, and cache infrastructure, so the same archive works locally and through a remote daemon.\n\n## What users ge\n[…]\neetings TUI, identity configuration, retry behavior, and source removal. See `docs/usage/meetings.md` for the end-to-end workflow.\n\n\nCo-authored-by: Matthew Sweeney <sweenzor@users.noreply.github.com>",
"is_bot": false,
"headline": "Add Granola and Circleback meeting sync and TUI browsing (#465)",
"author_name": "Matthew Sweeney",
"author_login": "sweenzor",
"committed_at": "2026-07-15T00:31:47Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6be56846c44e77af3863f775609333d6501c8e66",
"body": "## Summary\n- Fix IMAP fast sync for servers that expose an `\\All` mailbox, including Fastmail.\n- Persist IMAP folder high water marks after each folder is fully ingested or safely acknowledged, instead of requiring the entire account sync to finish first.\n- Update IMAP sync status/help text and test\n[…]\n/msgvault/cmd -run TestSyncCmd_SingleSourceNoAmbiguity -count=1`\n- `go fmt ./...`\n- `go vet -tags \"fts5 sqlite_vec\" ./...`\n- `make test`\n\n\nCo-authored-by: Jesse Vincent <obra@users.noreply.github.com>",
"is_bot": false,
"headline": "Fix IMAP fast sync high water marks (#481)",
"author_name": "Jesse Vincent",
"author_login": "obra",
"committed_at": "2026-07-14T17:32:43Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "451f431c473addd5669025fb1f0d427bb53b59b9",
"body": "msgvault 0.17.0 moved local archive commands behind daemon runtime discovery. The runtime store then rejected an effective home or data directory whose final component was a symlink, breaking layouts supported by earlier releases and preventing both lifecycle and archive commands from running.\n\nReso\n[…]\ne exercises real runtime record write/read behavior through a symlink, and the configuration reference now documents the supported layout.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Fix daemon discovery for symlinked home directories (#480)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-13T19:54:58Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e3333cc6e156c551e0893a9d61405641405d84b2",
"body": "Windows contributors need a native counterpart to the Make build targets, and the existing PowerShell helper only supports AMD64 MinGW assumptions. That prevents Windows-on-ARM developers from building the full application locally without manually recreating release-only setup.\n\nThis makes `.\\script\n[…]\nted from an empty cache, and the resulting executable passed version, database initialization, and full DuckDB cache-rebuild smoke checks.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Support native Windows development builds (#479)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-13T17:44:29Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e3ce469341ae537b770b6b4d0ce4f367a1cfa310",
"body": "Windows CI previously put every package behind one runner. The 652-test CLI package, sync engine, vector backends, and several storage-heavy packages all contain substantial serial work, leaving the Windows check at 13m10s on current main. Adding `t.Parallel()` broadly would be unsafe because many c\n[…]\nws test jobs use about 19m56s instead of 13m10s, an increase of roughly 51%, while the existing packed-restore benchmark job is unchanged.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "ci: shard slow Windows CLI tests (#478)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-13T14:16:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7eca0f1e751aa9f4478947018cd37934dbcbdb3b",
"body": "Updates backup restore to use Kit v0.9.1 and skip SQLite's full integrity scan by default. Page and blob hashes plus manifest statistics remain verified on every restore; pass `--integrity-check` to run the additional SQLite scan.\n\nRestore progress now names `SQLite check` and `database stats` separ\n[…]\n in the final summary.\n\nKit release: https://github.com/kenn-io/kit/releases/tag/v0.9.1\nKit change: https://github.com/kenn-io/kit/pull/45\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Make SQLite restore checks opt-in (#477)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-13T12:53:01Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6e9b6978e7fc4bf5ad5b28a9066e49367aeb450f",
"body": "Kit v0.9.0 restores compatibility with valid legacy packs whose zstd frames declare larger windows, preventing msgvault backup import and maintenance reads from rejecting existing data that remains within configured policy. The release also makes Kit’s portable backup metadata primitives available f\n[…]\ngraph. No configuration or storage migration is required.\n\nThe full Go test suite, lint, vet, and Nix build pass with the upgraded module.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Upgrade Kit to v0.9.0 (#476)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-13T10:31:58Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9c320a28e6093433683e1922c734b2d60aee1b7f",
"body": "Windows-on-ARM users currently receive only the amd64 archive and rely on emulation. This adds a native windows/arm64 release package using a pinned ARM64 llvm-mingw toolchain.\n\nThe ARM64 package retains the full application surface, including DuckDB analytics, Parquet cache operations, and sqlite-v\n[…]\nts standard extensions are statically linked, so the release remains a single self-contained executable and preserves atomic self-updates.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Ship native Windows ARM64 releases (#475)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-13T03:55:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "981fd1eb71bd1723254cb1fad7b8f018c34f065b",
"body": "Splits MCP message search into dedicated metadata, keyword-body, and semantic tools, while retaining `search_messages` as a deprecated compatibility wrapper. It also makes scored semantic chunk excerpts available through the daemon-backed path used by `msgvault mcp`, not only the in-process server.\n\n[…]\nut the request.\n- Updates the OpenAPI schema and the README, changelog, search guide, vector-search guide, and Zensical MCP documentation.\n\nCo-authored-by: endolith <endolith@users.noreply.github.com>",
"is_bot": false,
"headline": "Split MCP search tools and add daemon-backed semantic matches (#470)",
"author_name": "endolith",
"author_login": "endolith",
"committed_at": "2026-07-13T00:14:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ad7df913398f98e33f27c861b62a5f6a38404a8a",
"body": "## Why\n\nKit v0.8.0 adds verified streaming reads for packstore content, but msgvault's sequential attachment paths still used the legacy seekable API. Backup capture, HTTP delivery, and exports therefore retained unnecessary whole-object memory use and could miss terminal verification failures.\n\n## \n[…]\n.2 GiB/s**.\n- Oversized-loose backup/verify, raw, compressed, concurrent, race, same-length corruption, and full-suite validation passed.\n\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Stream attachment reads through Kit packstore (#473)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-13T00:00:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "597c1a67a5639d211b5baeda56308b1533081c41",
"body": "Windows command-package tests have enough runner-dependent variance to cross Go's default ten-minute package deadline, producing false Windows CI failures even when the suite is making progress. The existing in-process timeout override was ineffective because the parent `go test` command still owned\n[…]\nleading workaround. This changes CI tolerance only; investigation and optimization of the underlying Windows test runtime remain separate.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "ci: set Windows test timeout at invocation (#474)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-12T23:59:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6ff5985b1f1ba92e3b17010a6f3cb721806df6fa",
"body": "## Summary\n\n- Adds a \"Restoring to a New Machine\" walkthrough to the backup guide: install msgvault, get the repository onto the machine, list snapshots, and restore straight into the default `~/.msgvault` location without touching config first.\n- Calls out the footgun of restoring `--overwrite` onto a directory that already has content — it merges rather than wiping, so leftover files from an earlier install can survive the restore.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "docs: add new-machine restore workflow to backup guide (#472)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-12T19:17:26Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f891e482cc51fc564690748a0bbe618acbfe5ce1",
"body": "Large archives currently pay the cost of creating one loose CAS file per attachment during restore, even though backup repositories and production attachment storage use the same immutable pack representation. That filesystem amplification is especially costly on Windows and makes restore performanc\n[…]\nre created 2,000 files and took 20.5–25.3 seconds total, while packed restore created one pack and took 245–280 milliseconds.\n\nCloses #466\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Restore attachment packs directly from backups (#471)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-12T01:25:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5464711e086532e8e2a062019f022c39fcbb22ae",
"body": "Archives every chat network bridged through [Beeper Desktop](https://developers.beeper.com/desktop-api) — WhatsApp, Signal, Telegram, Instagram, LinkedIn, X, Facebook, Matrix — via its local REST API. Supersedes #455 as a single consolidated PR.\n\n## Usage\n\n```bash\nmsgvault add-beeper # access \n[…]\nl backfill, incremental re-runs, media download, interrupt/resume.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n\nCo-authored-by: Matthew Sweeney <sweenzor@users.noreply.github.com>",
"is_bot": false,
"headline": "Add Beeper Desktop chat archiving (#458)",
"author_name": "Matthew Sweeney",
"author_login": "sweenzor",
"committed_at": "2026-07-11T23:19:17Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "51f3186abd16bf197bb380dae32a3404fff75f66",
"body": "Packed attachments materially improve archive behavior, especially on Windows, but msgvault currently owns a second physical storage state machine for crash recovery, bounded parsing, reader retirement, and durable loose publication. Kit PR kenn-io/kit#33 makes that lifecycle reusable; this change a\n[…]\nof, legacy unpack, independent SHA-256 comparison, and final repack.\n\nThis PR consumes the released Kit v0.6.0 packed-CAS implementation.\n\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Move attachment storage to Kit packstore (#469)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-11T13:48:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "825bb4b91f6c15dba701f40e91191d4d98255bff",
"body": "Adds an installable pack of agent skills (SKILL.md files per the open agent-skills standard used by Claude Code and Codex) that teach coding agents the msgvault read-only CLI workflows, so agents don't relearn the CLI each session.\n\n## What's new\n\n- `msgvault skills install` — renders three skills f\n[…]\nmsgvault skills install --dir .agents/skills\nmsgvault skills uninstall\n```\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Add agent skills pack with msgvault skills install/uninstall (#446)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-11T11:55:31Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "c262ace414dbb5068c27bc0511e091383bd0cb02",
"body": "## What\n\nAdds `GET /api/v1/attachments/{hash}` — an authenticated endpoint that streams a stored attachment's raw bytes, addressed by its SHA-256 content hash, with the attachment's own `Content-Type` and a download `Content-Disposition` filename.\n\n## Why\n\nThe HTTP API had no way to retrieve file-at\n[…]\n `/api/v1` API-key middleware. `content_hash` is not unique (content-addressed dedup), so any matching row supplies the header metadata.\n\n\nCo-authored-by: Rob Elkin <robelkin@users.noreply.github.com>",
"is_bot": false,
"headline": "feat: serve attachment content via GET /api/v1/attachments/{hash} (#463)",
"author_name": "Rob Elkin",
"author_login": "robelkin",
"committed_at": "2026-07-11T03:03:53Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "362493f2a555ba5c8909f4c83435e1fd0dd9eb3f",
"body": "Store attachment and thumbnail bytes in sealed, immutable kit packs while preserving transparent reads across loose, packed, and mixed storage. Existing vaults remain usable throughout migration; users can migrate explicitly with `pack-attachments` or let bounded daemon maintenance make gradual prog\n[…]\n6. This branch keeps restore fully loose for compatibility while establishing the pack format and lifecycle needed for that optimization.\n\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Store and maintain attachments in sealed CAS packs (#464)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-10T21:54:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1eb67343ca3811d0b8b3f16dd1fe20454b6fd749",
"body": "Split MCP keyword search into explicit metadata and body paths. `search_messages` now searches subjects, snippets, senders, and recipients when mode is omitted while retaining vector and hybrid modes; `search_message_bodies` requires free text and returns up to five bounded, backend-native FTS excer\n[…]\nunsupported or malformed operators before dispatch; add `conversation_id` to MCP `list_messages`; and update the MCP guides and changelog.\n\nCo-authored-by: endolith <endolith@users.noreply.github.com>",
"is_bot": false,
"headline": "Enforce metadata/body search scopes with native contexts (#462)",
"author_name": "endolith",
"author_login": "endolith",
"committed_at": "2026-07-10T15:40:21Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f152bdb6a2e834128fba282575cf21a6aa3a3c00",
"body": "The existing instruction can be read as restricting the roborev CLI generally. Clarify that only the `roborev review` subcommand requires an explicit user request and encourage normal use of every other roborev CLI command; roborev skills remain opt-in.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "docs: clarify roborev review restriction (#468)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-10T15:05:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "24225f6eb6b7c7e4f3378ba8942e52d5b10f4326",
"body": "Automated review runs can consume resources and create persistent review state even when review was not part of the requested task. Make both direct `roborev review` invocation and roborev skill activation explicitly user-directed so agents do not treat either as an automatic completion step.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "docs: require explicit roborev requests (#467)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-10T12:02:04Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "e3ede8c5af629bab16d124f20c72e5d7575b94b3",
"body": "Fixes #457.\n\n- `import-emlx` now discovers and imports `*.partial.emlx` files. Apple Mail uses this form for IMAP/Gmail messages whose attachments are not cached locally; the RFC822 body is complete, so the message imports normally with only the uncached attachment parts absent. Mailboxes containing\n[…]\n identity); `msgvault deduplicate` merges such pairs by RFC822 Message-ID.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "import-emlx: import *.partial.emlx files instead of skipping them (#459)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-09T00:12:18Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "75348424915fccbccec098f79d4040d9a5328560",
"body": "go1.26.5 fixes GO-2026-5856 (crypto/tls) and GO-2026-4970 (os), which govulncheck now flags on every branch — CI's test job fails at the vulnerability gate repo-wide. The nix flake pins the Go source tarball by hash, so it moves together with the go directive.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Matthew Sweeney <sweenzor@users.noreply.github.com>",
"is_bot": false,
"headline": "Bump Go to 1.26.5 (go.mod + nix pin) (#460)",
"author_name": "Matthew Sweeney",
"author_login": "sweenzor",
"committed_at": "2026-07-08T23:55:01Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6dd85c44db7d6f38623f06b47cc206a265dbfd75",
"body": "- Adds the search_in_message MCP tool (keyword search within one message body, returns char_offset + snippet + line)\r\n- Pairs with merged get_message paging via center_at=<char_offset>\r\n\r\nNew tool finds all occurrences of a term in one message body, returning char_offset, line, and a centered snippe\n[…]\nesults in a follow-up PR) with UTF-8-safe windows.\r\n\r\nContinuation of #421 and #388. See also https://github.com/endolith/msgvault/pull/15\n\nCo-authored-by: endolith <endolith@users.noreply.github.com>",
"is_bot": false,
"headline": "MCP: add search_in_message tool (#452)",
"author_name": "endolith",
"author_login": "endolith",
"committed_at": "2026-07-08T12:05:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "40a2d88d6021c14b6a7c168009d61ea3c40ca222",
"body": "Moves the backup engine (pack container + incremental snapshot engine) to the shared go.kenn.io/kit library and rewires msgvault to consume it. No CLI or on-disk format changes: existing backup repositories, manifests, and snapshot IDs are byte-identical.\n\n- `internal/pack` and `internal/backup` are\n[…]\no/kit#26 to merge first (go.mod pins its head commit as a pseudo-version).\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Adopt kit pack/backup engine for msgvault backups (#438)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-08T01:07:32Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "b56b063cc317007158e4bf74381d1e35b500311c",
"body": "## Summary\n- Updated `vendorHash` to `sha256-0O5CZoaQ/R9euikP0L9sRkwDuflosh4PdPjUqXXPr40=`\n- Updated version to `0.17.1`\n\nAutomated update via `scripts/update-nix-flake.sh`.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Update nix flake for v0.17.1 (#453)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-07T15:05:52Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bbc163239d4b01f1cb5e123434363ef465764737",
"body": "0.17.1 needs a dated public release entry now that the tag is cut, and users should be able to find the new HTTP deletion staging workflow and non-blocking full-text index status behavior from the docs site instead of only from release commits. This moves the deletion API note out of Unreleased into\n[…]\nhe generator, and anchors those git queries at the repository root so invoking the script from `scripts/` cannot narrow the release scope.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "docs: document 0.17.1 release (#454)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-07T13:17:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f89dc5babea0941d96d9f4283557229e8149b8ce",
"body": "## Why\n\nmsgvault should use the same Renovate-centered dependency update flow as agentsview. Keeping Dependabot active alongside Renovate would create duplicate update PRs for Go modules and pinned GitHub Actions.\n\n## What changed\n\n- Add Renovate configuration for Go modules, GitHub Actions, and Doc\n[…]\n## Validation\n\n- `npx --yes --package renovate renovate-config-validator renovate.json`\n\n<sup>generated by a clanker</sup>\n\nCo-authored-by: Marius van Niekerk <mariusvniekerk@users.noreply.github.com>",
"is_bot": false,
"headline": "ci: migrate dependency updates to Renovate (#449)",
"author_name": "Marius van Niekerk",
"author_login": "mariusvniekerk",
"committed_at": "2026-07-07T03:20:34Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "af8a882abf411d0da66ec86c23993a86dae6b68d",
"body": "Adds first-class deletion staging endpoints to the daemon HTTP API, so web/HTTP consumers can stage messages for deletion without pre-resolving Gmail IDs client-side (previously only possible via the CLI-proxy route with a fully constructed manifest).\n\n## New endpoints (API schema 1.2.0)\n\n- `POST /a\n[…]\numented in `docs/api-server.md`, with a changelog entry under Unreleased.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Add deletion staging endpoints to the web API (#448)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-07T03:20:16Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "84bbddf9f15c1f91c6f3c6630642a1481a4b62e4",
"body": "Consolidates the following dependabot updates:\n\n- #444 -- bump the minor-and-patch group with 7 updates (go.mod)\n- #443 -- bump docker/build-push-action from 7.2.0 to 7.3.0\n- #442 -- bump docker/setup-buildx-action from 4.1.0 to 4.2.0\n- #441 -- bump docker/setup-qemu-action from 4.1.0 to 4.2.0\n- #44\n[…]\nHash for the Go module changes.\n\nCloses #444, #443, #442, #441, #440, #439\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "deps: batch update 12 dependencies (#450)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-07T02:17:53Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "9c6e0e1f2a4ce8efeeeef6a6252e00c49cecf02b",
"body": "## What changed\n\n- Added two partial SQLite indexes, created idempotently in `InitSchema`: `idx_messages_deleted_from_source_at` on `messages(deleted_from_source_at) WHERE deleted_from_source_at IS NOT NULL` and `idx_messages_deleted_at` on `messages(deleted_at) WHERE deleted_at IS NOT NULL`.\n- Extr\n[…]\n an existing archive runs under `runMaintenance` on the next daemon start.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Index deletion timestamps to unblock daemon cold start (#447)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-06T20:47:52Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "27a0e526d6529d3cd5c5cb03493b659df80450df",
"body": "## What changed\n\n- `msgvault search` no longer waits for the FTS index completeness probe or backfill. The first search after a daemon start used to run a full anti-join over every message inline (30–60s on a large archive, reproducible after every 20-minute idle shutdown); that work now runs in a s\n[…]\ned; the completeness probe (1m04s on that archive) runs in the background.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Stop blocking CLI search on the FTS completeness probe (#437)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-06T18:22:30Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "98c978cb9357ec626f23b1c0c0100615952f56a1",
"body": "## Observed Failures (sanitized)\nBefore this patch, IMAP sync produced large numbers of fetch failures on iCloud IMAP.\n\nError examples:\n- `missing raw message in batch result`\n- `IMAP fetch skipped after earlier chunk failure`\n- `in response-data: in envelope: in env-cc: in address: imapwire: expect\n[…]\n ./...`\n- Isolated sync validation against a 30k email window, changed from 2045 fetch errors before this patch, to 2044 added / 0 errors.\n\n\nCo-authored-by: Tim Kersten <io41@users.noreply.github.com>",
"is_bot": false,
"headline": "Fix IMAP UID enumeration and raw fetch robustness (#436)",
"author_name": "Tim Kersten",
"author_login": "io41",
"committed_at": "2026-07-06T16:36:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "a939980136332fdbcc89922056be73e68b324f51",
"body": "## Why\n\n0.17.0 shipped a broad set of user-facing surfaces, and the existing docs only covered part of the release. The release notes and docs need to match the implementation so users can discover backup, Teams sync, message-type filtering, scoped embeddings, and the daemon/API changes from the pub\n[…]\ndeployment is manual after merge: run `make docs-deploy` (or the project's docs deploy flow) so the public site picks up the release docs.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "docs: document 0.17.0 release (#435)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-05T01:54:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "afcdae47cd91d17285a9bc2e31130a4dcd2fb883",
"body": null,
"is_bot": false,
"headline": "Update nix flake for v0.17.0 (#434)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-05T01:30:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "18bede43b5091c5d8643c5d5cc72bfed60bc220d",
"body": "… (#339) (#428)\n\nImplements the backup and restore side of #339: `msgvault backup init / create / list / verify / restore` against an app-owned backup repository. Restore is included and proves itself before reporting success — see \"Restore\" below.\n\nDocs: [usage guide](https://github.com/kenn-io/msg\n[…]\nore materialization proof against scratch space without writing a target.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Add msgvault backup: init, create, list, verify, and restore commands…",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-05T00:41:50Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "452a3e4a1fa57493ae1af7aa055cc4a3ab65b720",
"body": "Every IMAP sync re-enumerated every mailbox (SELECT + UID SEARCH per folder) because the client kept no state between sessions, so a resync of a large archive walked every historical folder again.\n\n## What changed\n\n- New `imap_folder_state` table stores each mailbox's UIDVALIDITY/UIDNEXT as of the l\n[…]\nper-folder state; subsequent resyncs skip unchanged folders automatically.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Skip unchanged IMAP folders on resync via UIDVALIDITY/UIDNEXT (#432)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-04T22:19:16Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "e64bcb9e45bbe8386ca6918f0cd40edaa9f506fd",
"body": "`msgvault serve stop` used to poll silently for up to ~31 minutes while the daemon drained a long archive operation (e.g. an embeddings rebuild), looking like a hang with no indication why.\n\n## What changed\n\n- `/health` now includes an `operation` block (`label`, `started_at`) populated from the ope\n[…]\n specs and the generated client were regenerated for the new health field.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Explain serve stop waits and report the daemon's active operation (#429)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-04T21:42:41Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "4b278505cbd36d8e99b0614ac74944ee30c8921a",
"body": "## Summary\n\n- Move the remaining Charm prompt dependency to Huh v2 so msgvault no longer links Bubble Tea v1.\n- Use Bubble Tea v2 background reporting with Lip Gloss `LightDark` for TUI adaptive styles instead of the Lip Gloss compat probe.\n\n## Why\n\nNon-TUI commands could still inherit the old impor\n[…]\n the running TUI program, where Bubble Tea v2 owns the terminal lifecycle.\n\nCloses #427\n\n<sup>generated by a clanker</sup>\n\nCo-authored-by: Marius van Niekerk <mariusvniekerk@users.noreply.github.com>",
"is_bot": false,
"headline": "chore(tui): finish Bubble Tea v2 migration (#431)",
"author_name": "Marius van Niekerk",
"author_login": "mariusvniekerk",
"committed_at": "2026-07-04T16:11:16Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cb355824586b579a539546f3e8d83eca807ce157",
"body": "Bubble Tea v2 changes the core model/view/key contracts and moves the Charm modules to their canonical charm.land import paths. Keeping msgvault on v1 leaves the TUI pinned to the old imperative option model and makes future Charm updates harder to take safely.\n\nThis migrates the TUI stack together \n[…]\nendering behavior, so this was checked with the normal Go suite and by launching the real TUI in tmux against an empty temporary archive.\n\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "chore(tui): migrate to Bubble Tea v2 (#430)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-04T13:05:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1c6dec7f93e98f02ea51f1d67fd8462f9977479d",
"body": "… HTTP (#426)\n\n## Summary\n\nThis PR changes how the msgvault CLI reaches your archive. Before, every command opened the SQLite database directly in its own process; now, every archive-access command talks to a msgvault daemon over HTTP — either the remote server configured under `[remote]`, or a loca\n[…]\non; testing against a copied archive or backup is the right rollout path.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Migrate to daemon-only model, route CLI archive access through daemon…",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-07-03T21:25:41Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "460721a194b3d1ef1ed2cdd18a2b7fec39a259bc",
"body": "MCP search previously accepted Gmail-only list syntax as plain text because the local parser had no way to mark unsupported operators. That made agent-side validation look successful even when `List-ID` was never evaluated by msgvault.\n\nThis rejects known Gmail-only list operators in MCP search and \n[…]\ncs and MCP tool descriptions now call this a local subset of Gmail-like syntax and point List-ID validation back to Gmail-side evaluation.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(mcp): reject Gmail-only list search operators (#425)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-30T23:10:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "14c4c97bef75d3a216fc24277e9ffad651185807",
"body": "Bumps the minor-and-patch group with 2 updates: [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go) and [golang.org/x/tools](https://github.com/golang/tools).\n\nUpdates `github.com/mark3labs/mcp-go` from 0.55.0 to 0.55.1\n<details>\n<summary>Commits</summary>\n<ul>\n<li><a href=\"https://gi\n[…]\ncy name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions\n\n\n</details>\n\nCo-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump the minor-and-patch group with 2 updates (#424)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-29T23:01:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cab0211a1f7eacd9a1f416b1be55fcf20888f277",
"body": "Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.4.0 to 6.5.0.\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/actions/setup-go/releases\">actions/setup-go's releases</a>.</em></p>\n<blockquote>\n<h2>v6.5.0</h2>\n<h2>What's Changed</h2>\n<h3>\n[…]\n and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n</details>\n\nCo-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump actions/setup-go from 6.4.0 to 6.5.0 (#423)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-29T20:41:29Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2c8a118aca78b39a1fb1971d58995188cd0e8171",
"body": "## Summary\n- add read-only Google Calendar sync with CLI commands, daemon scheduling, and [[gcal]] config\n- store calendar events as searchable messages with message_type filtering and scoped vector refresh support\n- update README, setup, OAuth, CLI, config, search, and changelog docs for PR readiness\n\n## Testing\n- timeout 45m env GOMAXPROCS=2 GOFLAGS=-p=1 make test\n- timeout 10m make docs-check\n\nCo-authored-by: danshapiro <danshapiro@users.noreply.github.com>",
"is_bot": false,
"headline": "Add Google Calendar sync support (#418)",
"author_name": "danshapiro",
"author_login": "danshapiro",
"committed_at": "2026-06-29T02:30:07Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "80e46a835ac2da099c48824045d6ba4b84818d17",
"body": "Return `body_text` as a paginated slice instead of the full message body. Adds `offset`, `center_at`, `max_chars` (default 2000, max 4000), `body_length`, `body_returned`, and `has_more` so agents can page through long messages or jump to a match via `center_at` (byte offset from `search_in_message`\n[…]\n changes are meant to make the MCP tools return more narrowly-focused content to avoid wasting money and tokens and overwhelming the LLM.)\n\nCo-authored-by: endolith <endolith@users.noreply.github.com>",
"is_bot": false,
"headline": "MCP: windowed get_message body reading (#421)",
"author_name": "endolith",
"author_login": "endolith",
"committed_at": "2026-06-28T15:14:12Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1bf706cdaf1139ae24e69d1fea616888fab391e4",
"body": "## What\n\nSync your own Microsoft Teams 1:1/group/meeting chats and channel messages into msgvault via **delegated** Microsoft Graph, searchable alongside mail through the existing TUI / FTS / Parquet analytics.\n\n## Highlights\n\n- New `add-teams` (delegated Graph OAuth) and `sync-teams` (full + increm\n[…]\ndeparting user's shared SharePoint/OneDrive files before account removal.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Nat Torkington <njt@users.noreply.github.com>",
"is_bot": false,
"headline": "feat: Microsoft Teams ingestion (delegated Graph sync) (#398)",
"author_name": "Nat Torkington",
"author_login": "njt",
"committed_at": "2026-06-28T02:11:09Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a120738c8b4d312943a4ad00bf0929c12a78478c",
"body": "…unning engine (#422)\n\n## What\n\nThe DuckDB query engine probes each Parquet table's optional columns once at construction and trusts that snapshot for the rest of the process lifetime. A long-running process (the `serve` daemon, the MCP server) goes stale when `build-cache`/`sync` rewrites the analy\n[…]\na live engine and asserts the query recovers instead of crashing.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Lazare Rossillon <Lazare-42@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(query): re-probe Parquet schema when cache changes underneath a r…",
"author_name": "Lazare Rossillon",
"author_login": "Lazare-42",
"committed_at": "2026-06-27T18:56:22Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "dde948844b37eddeb510def28a8becafb57d404f",
"body": "Depends on #412. This branch is stacked on the message_type filter PR until that lands.\n\n- Adds vector embedding build scope configuration for selected message types.\n- Applies the scope when seeding pending work for SQLite and PostgreSQL vector backends.\n- Enqueues embeddings for messages imported by Synctech SMS local/Drive syncs.\n\nCo-authored-by: danshapiro <danshapiro@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(vector): support scoped embedding builds (#413)",
"author_name": "danshapiro",
"author_login": "danshapiro",
"committed_at": "2026-06-26T12:51:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1141a6c0bf053a81b47c11b0292aac6ad249be5f",
"body": "…en (scan-and-fill) (#411)\n\nImplements the embedding-queue redesign proposed in #387.\n\nReplaces the separate `pending_embeddings` work queue with a per-message `embed_gen` column plus a scan-and-fill worker, a per-generation `embed_watermark`, and a full-scan backstop. Backend-agnostic (SQLite and P\n[…]\ns is included — happy to keep `pending_embeddings_total` as a deprecated alias if you'd prefer to preserve the existing field name.\n\n\nCo-authored-by: Yuriy Grinberg <webgress@users.noreply.github.com>",
"is_bot": false,
"headline": "embeddings: replace pending_embeddings queue with per-message embed_g…",
"author_name": "Yuriy Grinberg",
"author_login": "webgress",
"committed_at": "2026-06-25T21:31:58Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "ac49fe26e4bb9d5cbeff02ad8e3b5308a038b502",
"body": "Adds first-class message_type filtering across text, API, vector, and hybrid search.\n\n- Parses message_type/type search filters into structured queries.\n- Applies message-type filters in store/API search and vector/hybrid backends.\n- Documents the filter in command quickstart search help.\n\nCo-authored-by: danshapiro <danshapiro@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(search): support message_type filters (#412)",
"author_name": "danshapiro",
"author_login": "danshapiro",
"committed_at": "2026-06-25T20:56:38Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bcec734b429d707ff240b647e993138dc50be4cd",
"body": "Facebook Messenger messages that carry multiple attachments without downloaded bytes (files missing from the DYI export, or no attachments dir configured) were recording only **one** attachment row — the rest were silently dropped.\n\n`UpsertAttachment` dedupes rows with an empty `content_hash` to one\n[…]\nays empty, so no bytes are implied and file-cleanup paths are unaffected.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Nat Torkington <njt@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(fbmessenger): don't collapse multiple attachments to one row (#406)",
"author_name": "Nat Torkington",
"author_login": "njt",
"committed_at": "2026-06-25T14:32:05Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "94d80def88d69ff70e6821277e9626fb683929ea",
"body": "Issue #401 exposed a TUI startup crash while `msgvault sync` was active: the process could rebuild the Parquet cache through DuckDB while also holding go-sqlite3 connections and starting background FTS maintenance. That repeats the same mixed-SQLite-library risk already documented for daemon cache r\n[…]\nin that TUI DuckDB options keep `sqlite_scanner` disabled by default. Standard Go formatting, vetting, and full tagged tests pass locally.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Avoid mixed SQLite access during TUI startup (#417)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-25T03:19:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "377baca8b211f00cd3993c84278fc45fd88f1061",
"body": "The API server reference used literal endpoint paths as heading text, which Zensical copied into the sidebar TOC. A long inline-image endpoint also rendered malformed TOC HTML around the <content-id> placeholder, causing the sidebar to expand into the article on the published page.\\n\\nUse short desc\n[…]\nn bash scripts/check-docs.sh, and inspected a rebuilt local /api-server/ screenshot showing separated article and TOC columns.\\n\\nGenerated with Codex (GPT-5)\\nCo-authored-by: Codex <codex@openai.com>",
"is_bot": false,
"headline": "Fix API server docs sidebar overflow (#416)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-24T20:48:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c543bd2ecebcf0a51236275b867856ad5ff4c3b8",
"body": "Bumps the minor-and-patch group with 4 updates: [github.com/coreos/go-oidc/v3](https://github.com/coreos/go-oidc), [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go), [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) and [google.golang.org/api](https://github.com/goo\n[…]\ncy name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions\n\n\n</details>\n\nCo-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump the minor-and-patch group with 4 updates (#410)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-22T22:43:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "98b982dff35a5435e309671113eb4c655f849c42",
"body": "Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 3.0.0 to 3.0.1.\n- [Release notes](https://github.com/softprops/action-gh-release/releases)\n- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)\n- [Commits](https://github.com/so\n[…]\nirect:production\n update-type: version-update:semver-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump softprops/action-gh-release from 3.0.0 to 3.0.1 (#408)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-22T20:57:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9022e81e152a4f6ecaa8b6925380ae3764f1a832",
"body": "Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.2 to 7.0.0.\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/actions/checkout/releases\">actions/checkout's releases</a>.</em></p>\n<blockquote>\n<h2>v7.0.0</h2>\n<h2>What's Changed</h2>\n<ul>\n[…]\n and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n</details>\n\nCo-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump actions/checkout from 6.0.2 to 7.0.0 (#409)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-22T20:56:37Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f9b7ee9a817ae3e9deb9298cf183299ba4a0d5a0",
"body": "…407)\n\nAn empty search term produced `LIKE '%%'`, which matched **every** message instead of nothing. Two cases:\n\n- **Free-text terms on the LIKE fallback path** (used when FTS errors at runtime, or the binary is built without the `fts5` tag): a tokenless term (empty or punctuation-only) became `LIK\n[…]\nel:` handlers); `subject:\"!!!\"` remains a valid literal substring search.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Nat Torkington <njt@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(search): empty text/subject terms must not match every message (#…",
"author_name": "Nat Torkington",
"author_login": "njt",
"committed_at": "2026-06-22T15:41:38Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "7a73f393b149109d4be015138562bdc241ae1617",
"body": "## What\n\nSeveral importers built `time.Time` values from epoch timestamps with `time.Unix`/`time.UnixMilli` but **without `.UTC()`**, leaving them in the runner's local zone — while the rest of each importer stores dates in UTC. Any code reading the calendar day (or the Parquet year partition) is th\n[…]\ns can decide.\n\n## Scope\n\nIndependent of the Teams PR (#398) — branched from `main`, touches only `internal/sync` and `internal/whatsapp`.\n\nCo-authored-by: Nat Torkington <njt@users.noreply.github.com>",
"is_bot": false,
"headline": "fix: normalize importer message/reaction dates to UTC (#399)",
"author_name": "Nat Torkington",
"author_login": "njt",
"committed_at": "2026-06-22T13:13:55Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f2664e92cf07d3ae5f30545387de44a501e3f96f",
"body": "The existing fake-TDD guidance already discouraged stub-only shell tests, but it did not explicitly cover content-grep assertions over scripts, workflows, config, and docs.\n\nThis extends the guidance so future shell workflow tests prove behavior through real execution, parser-backed checks, tool-native validation, or explicit manual release checks instead of matching implementation strings.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Forbid tautological bash content checks (#405)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-22T01:50:56Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5d88ee7dc56d056143b70416d593d66bc2c96b50",
"body": "The docs integration accidentally merged the superpowers planning/spec files that were used to execute the migration. They are internal implementation artifacts, not public documentation source or maintainer reference material.\n\nLeaving them under `docs/superpowers` makes the docs tree noisier and c\n[…]\n shipped msgvault documentation. This PR removes only those merged planning artifacts.\n\nValidation: `make docs-check`; `git diff --check`.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Remove docs superpowers planning artifacts (#404)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-22T00:46:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6e39c04738a9847647acb13a25f1e64091bede83",
"body": "* Design msgvault docs integration\n\nThe docs migration has enough moving pieces that implementation needs a committed design before file movement starts: a Zensical port, Vercel rooted at docs/, orphan asset branches, preserved internal references, and asset hydration checks all need to align.\n\nThe \n[…]\nd confirmed check_built_site.py failed with \"forbidden public site dotfile\".\n\nGenerated with Codex (GPT-5)\nCo-authored-by: Codex <codex@openai.com>\n\n---------\n\nCo-authored-by: Codex <codex@openai.com>",
"is_bot": false,
"headline": "Integrate docs into msgvault (#403)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-21T20:46:46Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fa24f72c18027687a86639789f0ca10f933f811c",
"body": "Added installation instructions for macOS using https://github.com/Homebrew/homebrew-core/pull/288747\n\nCo-authored-by: Matthew Sweeney <sweenzor@users.noreply.github.com>",
"is_bot": false,
"headline": "Add macOS installation instructions via Homebrew (#400)",
"author_name": "Matthew Sweeney",
"author_login": "sweenzor",
"committed_at": "2026-06-20T17:41:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0cfc8b7147bbab8fda2dd560ec15ac6afc266df3",
"body": "Persist the sync checkpoint before failing a full sync when a whole batch fetch fails, so recorded per-item errors stay consistent with sync_runs.errors_count.\n\nAdds a regression covering the failed full-sync batch-fetch path.\n\nCo-authored-by: danshapiro <danshapiro@users.noreply.github.com>",
"is_bot": false,
"headline": "Persist full-sync batch error counts (#396)",
"author_name": "danshapiro",
"author_login": "danshapiro",
"committed_at": "2026-06-19T17:33:26Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "83bdfee7d9cf3ae13ec6c0572c3f777c7e271b05",
"body": "## Summary\n- Move the Docker runtime stage from cgr.dev Wolfi to pinned Debian bookworm-slim to avoid release publishes depending on Chainguard token availability.\n- Update the Nix package version to 0.16.0 using the existing vendorHash.\n- Run format/lint fixers and stage all resulting changes before the Nix update script commits.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Fix release publish and Nix update flow (#394)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-19T13:14:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "345738c940a9504d2ae7112998f309534eb75be8",
"body": "* ci: fix Linux release DuckDB link\n\n* ci: smoke test Linux release build",
"is_bot": false,
"headline": "Fix Linux release DuckDB link (#393)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-18T23:38:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "37f8eb2f6db1eb9e011d9e16f3cc25d6a7e92fe4",
"body": "The repository was renamed `wesm` → `kenn-io`; GitHub still serves the old path via redirect, so several hardcoded `wesm/msgvault` URLs lingered in the tree. This points them at the canonical owner.\n\n**Updated:** `README.md` (releases link + clone URLs), `docs/` (integration, PG issue draft, account\n[…]\nroborev`, and test fixtures — none of which refer to the old repo.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n\nCo-authored-by: Matthew Sweeney <sweenzor@users.noreply.github.com>",
"is_bot": false,
"headline": "chore: update stale wesm/msgvault URLs to kenn-io (#391)",
"author_name": "Matthew Sweeney",
"author_login": "sweenzor",
"committed_at": "2026-06-18T21:21:41Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "5538fa0d72ecd66e871a1f2d56550ee6303f3c1a",
"body": "Currently the MCP tool retrieves huge amounts of data with each call, which can overwhelm the context window and crash the conversation in a single response. I've been using vibe-coded improvements in my local copy that greatly narrow what is fed back to the LLM, so it can find things more efficien\n[…]\nore` vocabulary established here, so LLM clients can read and search large messages without the full body ever filling the context window.\n\nCo-authored-by: endolith <endolith@users.noreply.github.com>",
"is_bot": false,
"headline": "MCP: paginate search_messages and list_messages (#388)",
"author_name": "endolith",
"author_login": "endolith",
"committed_at": "2026-06-18T16:06:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "851e2ab973db717677b636cb45b834e5a1e00d1f",
"body": "## Summary\n- record per-item sync outcomes so completed syncs with partial failures are diagnosable\n- treat Gmail messages deleted before raw fetch as skipped instead of actionable errors\n- expose skipped counts and recent item errors in source status responses\n\n## Notes\nThis keeps `errors_count` focused on actionable item failures while preserving expected Gmail churn for diagnostics.\n\nCo-authored-by: danshapiro <danshapiro@users.noreply.github.com>",
"is_bot": false,
"headline": "Record per-item sync errors (#389)",
"author_name": "danshapiro",
"author_login": "danshapiro",
"committed_at": "2026-06-18T15:22:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "099871c9b5a6089ca4908cb7774eab2bfb875c2a",
"body": "Swaps the DuckDB `database/sql` driver from the deprecated `github.com/marcboeker/go-duckdb` to its canonical successor `github.com/duckdb/duckdb-go/v2`.\n\n### Why — Homebrew distribution\n\nThe goal is to make msgvault installable via `brew install` from **homebrew-core**. homebrew-core won't accept a\n[…]\nthe blank imports plus `go.mod`/`go.sum` and the Nix `vendorHash`.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n\nCo-authored-by: Matthew Sweeney <sweenzor@users.noreply.github.com>",
"is_bot": false,
"headline": "feat: migrate DuckDB driver to duckdb-go/v2 (DuckDB 1.5.4) (#390)",
"author_name": "Matthew Sweeney",
"author_login": "sweenzor",
"committed_at": "2026-06-18T15:08:37Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "6d816c791ff2ce324538278768f05b56aa1c653b",
"body": "This is the **fourth and final PR** in the series that adds a PostgreSQL storage backend to msgvault. The prior three staged the groundwork behind a dialect abstraction; this one makes PostgreSQL a **fully working backend at parity with SQLite** across every command — with a single exception: there \n[…]\nd PostgreSQL search paths).\r\n\r\n---\r\n\r\nThe series is organized as 10 logical commits and is intended to be reviewed commit-by-commit.\n\nCo-authored-by: Yuriy Grinberg <webgress@users.noreply.github.com>",
"is_bot": false,
"headline": "feat: add PostgreSQL backend and pgvector search support (#385)",
"author_name": "Yuriy Grinberg",
"author_login": "webgress",
"committed_at": "2026-06-17T12:09:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "cd33710d203f4a5d1a829d7dfeb8691bb4d4303e",
"body": "## What changed\n- Scheduled Synctech SMS Drive syncs now use the daemon's already-open store when run from `serve`.\n- Drive polls create one outer source-level `sync_runs` row, including zero-selected polls, and fail that run on list/checksum/stability/download/import/checkpoint errors.\n- Drive impo\n[…]\nec\" ./cmd/msgvault/cmd ./internal/synctechsms ./internal/store`\n- `make testify-helper-check`\n- `go vet -tags \"fts5 sqlite_vec\" ./...`\n\nCo-authored-by: danshapiro <danshapiro@users.noreply.github.com>",
"is_bot": false,
"headline": "fix: harden Synctech Drive sync lifecycle (#383)",
"author_name": "danshapiro",
"author_login": "danshapiro",
"committed_at": "2026-06-16T00:48:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1c543239960d32159319513f41a3cdfa65a94c9b",
"body": "Bumps the minor-and-patch group with 3 updates: [golang.org/x/net](https://github.com/golang/net), [golang.org/x/tools](https://github.com/golang/tools) and [google.golang.org/api](https://github.com/googleapis/google-api-go-client).\n\nUpdates `golang.org/x/net` from 0.55.0 to 0.56.0\n<details>\n<summa\n[…]\ncy name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions\n\n\n</details>\n\nCo-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump the minor-and-patch group with 3 updates (#386)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-15T20:29:33Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c78aaad0c6060167d889e5db35433557fe8c4968",
"body": "## What changed\n- Added read-only `GET /api/v1/sources/status` with optional `source_type` filtering.\n- Returns source identity metadata plus active, latest, and last successful sync-run details.\n- Added `Store.GetLatestSync` for latest sync-run lookup and tests for empty status handling.\n\n## Why\n- \n[…]\nsqlite_vec\" ./internal/api ./internal/store ./cmd/msgvault/cmd`\n- `make testify-helper-check`\n- `go vet -tags \"fts5 sqlite_vec\" ./...`\n\nCo-authored-by: danshapiro <danshapiro@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(api): expose source sync status (#382)",
"author_name": "danshapiro",
"author_login": "danshapiro",
"committed_at": "2026-06-15T17:13:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9f1f8e015582da6067392da1718b1ddbc4612494",
"body": "## What changed\n- Scan source import item checksums through sql.NullString in GetSourceImportItem and ListImportedSourceItemChecksums.\n- Surface an empty checksum string when legacy/imported rows contain NULL.\n- Add focused store coverage for NULL checksum rows.\n\n## Why\nSome source_import_items rows\n[…]\ntouched Go files\n- go test -tags \"fts5 sqlite_vec\" ./internal/store\n- make testify-helper-check\n- go vet -tags \"fts5 sqlite_vec\" ./...\n\nCo-authored-by: danshapiro <danshapiro@users.noreply.github.com>",
"is_bot": false,
"headline": "fix: tolerate null source import checksums (#381)",
"author_name": "danshapiro",
"author_login": "danshapiro",
"committed_at": "2026-06-15T14:42:46Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "89760ad7117f0df173bc5c070103eb85b293c95a",
"body": "…ption (#384)\n\nFixes #379.\n\n## Why\n\nAfter ~2 days of `msgvault serve` uptime, every post-sync analytics cache rebuild starts failing with `disk I/O error: no such file or directory` and keeps failing on every 15-minute sync until the daemon is restarted. Gmail sync itself is unaffected — only the Pa\n[…]\nValidation\n\n`go build/vet/test ./cmd/...` pass. Added `TestGlobalConfigFlagArgs` covering the subprocess flag passthrough.\n\nCo-authored-by: Marius van Niekerk <mariusvniekerk@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(serve): isolate DuckDB's SQLite from the daemon to stop WAL corru…",
"author_name": "Marius van Niekerk",
"author_login": "mariusvniekerk",
"committed_at": "2026-06-15T02:08:29Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4cb43434c46acfca3ed7f6ce4784f568e24bd395",
"body": "## Summary\n- Updated `vendorHash` to `sha256-Apa8gmFItEj62FxWS1Hfk0d8bGjvewkq4uZ+ftVcAEc=`\n- Updated version to `0.15.2`\n\nAutomated update via `scripts/update-nix-flake.sh`.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Update nix flake for v0.15.2 (#377)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-10T15:09:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "c65314db8bc1c383d1d7768c5317ab539ece6bc0",
"body": "…#376)\n\nIn --mode hybrid the engine bound the raw FreeText straight into the\nfused CTE's `messages_fts MATCH`, so FTS5 metacharacters in a natural-\nlanguage query — e.g. the \"?\" and \",\" in `what's the budget, roughly?`\n— reached the FTS5 parser unescaped and raised \"fts5: syntax error\nnear ...\". --m\n[…]\nhe metacharacter query both\nsucceeds and still matches on its real terms.\n\nCo-authored-by: Frederic Masi <894368+fmasi@users.noreply.github.com>\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(search): escape FTS5 metacharacters in hybrid query path (#366) (…",
"author_name": "Frederic Masi",
"author_login": "fmasi",
"committed_at": "2026-06-10T13:40:04Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "1883bb5f1e6d266adce666ac97adcbb59955edd3",
"body": "Bumps the minor-and-patch group with 5 updates:\n\n| Package | From | To |\n| --- | --- | --- |\n| [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) | `1.14.44` | `1.14.45` |\n| [golang.org/x/mod](https://github.com/golang/mod) | `0.36.0` | `0.37.0` |\n| [golang.org/x/sync](https://github\n[…]\ncy name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions\n\n\n</details>\n\nCo-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump the minor-and-patch group with 5 updates (#373)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-10T00:40:31Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "bccd4129f31930d7d6fd317b4bfc92c2a0ad78a6",
"body": "Adds `--json` to `msgvault verify` so tools can consume the Gmail/archive verification summary without scraping human output.\n\nThe JSON output includes archive count, Gmail profile total, signed difference, raw MIME coverage, DB integrity status, and sample summary. Human output is unchanged.\n\nFixes #371\n\nCo-authored-by: Carlos de la Lama-Noriega <cdelalama@users.noreply.github.com>",
"is_bot": false,
"headline": "feat(verify): add --json output for machine-readable results (#372)",
"author_name": "Carlos de la Lama-Noriega",
"author_login": "cdelalama",
"committed_at": "2026-06-09T21:42:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "128aac17f4838ffae523e03f1ffcaf86df8553c7",
"body": "Fixes the Windows installer (`irm https://msgvault.io/install.ps1 | iex`), reported in #374.\n\n## PowerShell 5.x: \"maximum redirection count exceeded\"\n\n`Get-LatestVersion` requested `/releases/latest` with `MaximumRedirection = 0` and read the `Location` header off the redirect. That works in PowerSh\n[…]\ny.\n\nPorts the `install.ps1` fixes from agentsview `b328d24f`.\n\nCloses #374\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "fix(install): Windows PowerShell 5.x redirect + arm64 fallback (#375)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-08T22:13:53Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "a34c50d2e5eadc28e26f57c1c92ccd89bfdfbd2b",
"body": "Updates the Nix package version to v0.15.1.\n\nAlso scopes the golangci-lint cache to the current git worktree so local commit hooks do not replay diagnostics from deleted sibling worktrees.\n\nCo-authored-by: Wes McKinney <wesm@users.noreply.github.com>",
"is_bot": false,
"headline": "Update Nix package to v0.15.1 (#369)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-04T03:13:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "512aa234137e57e747542486c7ad01fde9f51f5a",
"body": "The TUI's Texts-mode **Contacts** and **Contact Names** aggregate views came up empty because the DuckDB engine resolved each message's sender with a correlated scalar subquery inside the JOIN ON clause, which DuckDB couldn't push the message-type filter through — so it scanned the entire email-domi\n[…]\negate` test coverage (Contacts + Contact Names), extending the fixture builder with MessageType/SenderID so text messages can be modeled.\n\nCo-authored-by: Boris Jabes <bjabes@users.noreply.github.com>",
"is_bot": false,
"headline": "query: fix empty Contacts view in TUI Texts mode (DuckDB OOM) (#361)",
"author_name": "Boris Jabes",
"author_login": "bjabes",
"committed_at": "2026-06-04T00:46:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1aaee79b214ad56b95457e5b1645eaf64631b017",
"body": "After the repository moved from the `wesm` org to `kenn-io`, two\nhardcoded\nreferences to the old org broke at runtime.\n\n- `msgvault update` failed with `unexpected redirect target`. The\nupdater's\n release URLs still pointed at `github.com/wesm/msgvault`, so GitHub's\nrepo-rename redirect was rejecte\n[…]\ndeploys from `setup` now\nreference the\n current image.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Fix update check and setup image after wesm -> kenn-io rename (#368)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-06-04T00:18:30Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "d9303c909e86845ccf3bebd0cae6c3350a94817b",
"body": "Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 4.0.0 to 4.1.0.\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/docker/setup-qemu-action/releases\">docker/setup-qemu-action's releases</a>.</em></p>\n<blockquote>\n<h2>v4.1.0</\n[…]\n and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n</details>\n\nCo-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump docker/setup-qemu-action from 4.0.0 to 4.1.0 (#364)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-03T16:22:34Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3d3dbeb608b0b7d5ea7d1b2f3a5250998ead8805",
"body": "Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.2 to 6.0.3.\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/actions/checkout/releases\">actions/checkout's releases</a>.</em></p>\n<blockquote>\n<h2>v6.0.3</h2>\n<h2>What's Changed</h2>\n<ul>\n[…]\n and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)\n\n\n</details>\n\nCo-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump actions/checkout from 6.0.2 to 6.0.3 (#363)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-03T16:11:29Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fd5db525a6f8a068d84f32320f1624457ce1adfa",
"body": "Bumps the minor-and-patch group with 4 updates: [github.com/jackc/pgx/v5](https://github.com/jackc/pgx), [github.com/mattn/go-runewidth](https://github.com/mattn/go-runewidth), [golang.org/x/tools](https://github.com/golang/tools) and [google.golang.org/api](https://github.com/googleapis/google-api-\n[…]\ncy name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions\n\n\n</details>\n\nCo-authored-by: dependabot[bot] <dependabot[bot]@users.noreply.github.com>",
"is_bot": true,
"headline": "chore(deps): bump the minor-and-patch group with 4 updates (#365)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-03T16:10:58Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6bb5f118e70a66c2559f45ffeb29362830c5d56d",
"body": "Co-authored-by: Matthew Sweeney <sweenzor@users.noreply.github.com>",
"is_bot": false,
"headline": "Change repository name from wesm to kenn-io (#360)",
"author_name": "Matthew Sweeney",
"author_login": "sweenzor",
"committed_at": "2026-05-31T20:46:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4548afa9f4098992dbe5ba74aa63681cec4fdcf3",
"body": "## Summary\n- Bump `nix/package.nix` from 0.14.1 to 0.15.0 for the v0.15.0 release.\n- `vendorHash` unchanged — no dependency changes since v0.14.1.\n\nCompletes the `scripts/update-nix-flake.sh` run for the v0.15.0 tag.\n\n🤖 Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
"is_bot": false,
"headline": "Update nix flake for v0.15.0 (#359)",
"author_name": "Wes McKinney",
"author_login": "wesm",
"committed_at": "2026-05-29T01:05:46Z",
"body_truncated": false,
"is_coding_agent": true
},
{
"oid": "6bc642a0d56ad23432fd0ddc9355f27709c79aee",
"body": "## Why\nIssue #357 exposed a bad operational state in the vector embedding\nworkflow: a rebuild can be interrupted or left building under one\nembedding fingerprint, and a later run with a different configured\nfingerprint refuses to continue until that existing generation is either\nactivated or retired\n[…]\n test ./...` was also run during development and still\nfails in existing `internal/store` FTS/tokenless query tests unrelated\nto this command work.\n\n---------\n\nCo-authored-by: Codex <codex@openai.com>",
"is_bot": false,
"headline": "cmd: manage embedding generations (#358)",
"author_name": "Marius van Niekerk",
"author_login": "mariusvniekerk",
"committed_at": "2026-05-28T20:33:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e7e8593c8f273bfa074e7a65e122040768bd3334",
"body": "## Summary\nRemoves the broad `_test.go` linter exemption from `.golangci.yml` and\nbrings test files up to the same standard as production code. Addresses\n#348.\n\nFindings fixed: forcetypeassert (comma-ok form, plus an `asModel` helper\nfor the TUI `.(Model)` assertions), testifylint (require-error, fl\n[…]\nolint` on intentional skip-on-error callbacks).\nThe mbox cancel-on-log test keeps an enabled slog handler, since a\n`DiscardHandler` would never fire the cancel.\n\nNo production (non-test) code changed.",
"is_bot": false,
"headline": "test: re-enable test-suite linters (#348) (#355)",
"author_name": "Phillip Cloud",
"author_login": "cpcloud",
"committed_at": "2026-05-27T20:35:18Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "eabf33ebcfdf45235a0b30c0ea5d679150c089c4",
"body": "## Summary\n- Re-enables `sqlclosecheck` and `recvcheck`.\n- `sqlclosecheck`: extracts per-query scan helpers (repair-encoding\ntables, WhatsApp media/reaction/quoted chunk loads, store FK\nverification) so each `*sql.Rows` is closed via a correctly-scoped\n`defer` instead of a manual close — no defer ac\n[…]\nivers. The Bubble Tea `Model` keeps its\nintentional value/pointer split (value receivers drive the tea.Model\nupdate flow; pointer receivers mutate the local copy) behind a scoped\n`//nolint:recvcheck`.",
"is_bot": false,
"headline": "lint: enable sqlclosecheck and recvcheck (#352)",
"author_name": "Phillip Cloud",
"author_login": "cpcloud",
"committed_at": "2026-05-27T20:08:38Z",
"body_truncated": true,
"is_coding_agent": false
}
],
"releases_count": 34,
"commits_last_year": 442,
"latest_release_at": "2026-07-16T19:01:21Z",
"latest_release_tag": "v0.18.0",
"releases_from_tags": false,
"days_since_last_push": 0,
"active_weeks_last_year": 24,
"days_since_latest_release": 5,
"mean_days_between_releases": 10.2
},
"community": {
"has_readme": true,
"has_license": true,
"has_description": true,
"has_contributing": false,
"health_percentage": 50,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"ecosystem": {
"packages": [
{
"name": "go.kenn.io/msgvault",
"exists": true,
"license": null,
"keywords": [],
"ecosystem": "go",
"matches_repo": null,
"registry_url": "https://pkg.go.dev/go.kenn.io/msgvault",
"is_deprecated": false,
"latest_version": "v0.18.0",
"repository_url": null,
"versions_count": 36,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": null,
"latest_published_at": "2026-07-15T00:31:47Z",
"latest_version_yanked": null,
"days_since_latest_publish": 7
}
]
},
"popularity": {
"forks": 125,
"stars": 1942,
"watchers": 15,
"fork_history": {
"days": [
{
"date": "2026-02-02",
"count": 16
},
{
"date": "2026-02-03",
"count": 19
},
{
"date": "2026-02-04",
"count": 5
},
{
"date": "2026-02-05",
"count": 3
},
{
"date": "2026-02-06",
"count": 6
},
{
"date": "2026-02-07",
"count": 2
},
{
"date": "2026-02-08",
"count": 1
},
{
"date": "2026-02-09",
"count": 3
},
{
"date": "2026-02-10",
"count": 1
},
{
"date": "2026-02-11",
"count": 3
},
{
"date": "2026-02-12",
"count": 1
},
{
"date": "2026-02-13",
"count": 1
},
{
"date": "2026-02-15",
"count": 2
},
{
"date": "2026-02-18",
"count": 1
},
{
"date": "2026-02-23",
"count": 2
},
{
"date": "2026-02-24",
"count": 1
},
{
"date": "2026-02-26",
"count": 1
},
{
"date": "2026-02-28",
"count": 1
},
{
"date": "2026-03-02",
"count": 2
},
{
"date": "2026-03-08",
"count": 1
},
{
"date": "2026-03-10",
"count": 1
},
{
"date": "2026-03-11",
"count": 1
},
{
"date": "2026-03-16",
"count": 1
},
{
"date": "2026-03-20",
"count": 1
},
{
"date": "2026-03-21",
"count": 1
},
{
"date": "2026-03-23",
"count": 2
},
{
"date": "2026-03-25",
"count": 1
},
{
"date": "2026-03-26",
"count": 2
},
{
"date": "2026-03-30",
"count": 2
},
{
"date": "2026-03-31",
"count": 2
},
{
"date": "2026-04-01",
"count": 1
},
{
"date": "2026-04-02",
"count": 2
},
{
"date": "2026-04-03",
"count": 1
},
{
"date": "2026-04-06",
"count": 1
},
{
"date": "2026-04-07",
"count": 1
},
{
"date": "2026-04-08",
"count": 1
},
{
"date": "2026-04-11",
"count": 1
},
{
"date": "2026-04-12",
"count": 1
},
{
"date": "2026-04-13",
"count": 2
},
{
"date": "2026-04-18",
"count": 1
},
{
"date": "2026-04-20",
"count": 1
},
{
"date": "2026-04-25",
"count": 2
},
{
"date": "2026-04-29",
"count": 1
},
{
"date": "2026-05-04",
"count": 1
},
{
"date": "2026-05-06",
"count": 1
},
{
"date": "2026-05-09",
"count": 1
},
{
"date": "2026-05-10",
"count": 1
},
{
"date": "2026-05-14",
"count": 1
},
{
"date": "2026-05-21",
"count": 2
},
{
"date": "2026-05-31",
"count": 1
},
{
"date": "2026-06-06",
"count": 1
},
{
"date": "2026-06-08",
"count": 2
},
{
"date": "2026-06-10",
"count": 1
},
{
"date": "2026-06-20",
"count": 1
},
{
"date": "2026-06-21",
"count": 1
},
{
"date": "2026-07-06",
"count": 1
},
{
"date": "2026-07-14",
"count": 2
},
{
"date": "2026-07-15",
"count": 1
},
{
"date": "2026-07-16",
"count": 1
},
{
"date": "2026-07-19",
"count": 2
}
],
"complete": true,
"collected": 123,
"total_forks": 125
},
"star_history": {
"days": [
{
"date": "2026-02-09",
"count": 10
},
{
"date": "2026-02-10",
"count": 24
},
{
"date": "2026-02-11",
"count": 12
},
{
"date": "2026-02-12",
"count": 55
},
{
"date": "2026-02-13",
"count": 15
},
{
"date": "2026-02-14",
"count": 11
},
{
"date": "2026-02-15",
"count": 8
},
{
"date": "2026-02-16",
"count": 17
},
{
"date": "2026-02-17",
"count": 9
},
{
"date": "2026-02-18",
"count": 15
},
{
"date": "2026-02-19",
"count": 5
},
{
"date": "2026-02-20",
"count": 5
},
{
"date": "2026-02-21",
"count": 3
},
{
"date": "2026-02-22",
"count": 6
},
{
"date": "2026-02-23",
"count": 14
},
{
"date": "2026-02-24",
"count": 12
},
{
"date": "2026-02-25",
"count": 8
},
{
"date": "2026-02-26",
"count": 8
},
{
"date": "2026-02-27",
"count": 3
},
{
"date": "2026-02-28",
"count": 6
},
{
"date": "2026-03-01",
"count": 9
},
{
"date": "2026-03-02",
"count": 9
},
{
"date": "2026-03-03",
"count": 23
},
{
"date": "2026-03-04",
"count": 27
},
{
"date": "2026-03-05",
"count": 13
},
{
"date": "2026-03-06",
"count": 3
},
{
"date": "2026-03-07",
"count": 7
},
{
"date": "2026-03-08",
"count": 4
},
{
"date": "2026-03-09",
"count": 8
},
{
"date": "2026-03-10",
"count": 10
},
{
"date": "2026-03-11",
"count": 8
},
{
"date": "2026-03-12",
"count": 3
},
{
"date": "2026-03-13",
"count": 1
},
{
"date": "2026-03-14",
"count": 2
},
{
"date": "2026-03-15",
"count": 2
},
{
"date": "2026-03-16",
"count": 3
},
{
"date": "2026-03-17",
"count": 2
},
{
"date": "2026-03-18",
"count": 1
},
{
"date": "2026-03-19",
"count": 20
},
{
"date": "2026-03-20",
"count": 69
},
{
"date": "2026-03-21",
"count": 15
},
{
"date": "2026-03-22",
"count": 10
},
{
"date": "2026-03-23",
"count": 4
},
{
"date": "2026-03-24",
"count": 3
},
{
"date": "2026-03-25",
"count": 16
},
{
"date": "2026-03-26",
"count": 5
},
{
"date": "2026-03-27",
"count": 5
},
{
"date": "2026-03-28",
"count": 1
},
{
"date": "2026-03-29",
"count": 2
},
{
"date": "2026-03-30",
"count": 78
},
{
"date": "2026-03-31",
"count": 26
},
{
"date": "2026-04-01",
"count": 12
},
{
"date": "2026-04-02",
"count": 4
},
{
"date": "2026-04-03",
"count": 4
},
{
"date": "2026-04-04",
"count": 5
},
{
"date": "2026-04-05",
"count": 8
},
{
"date": "2026-04-06",
"count": 10
},
{
"date": "2026-04-07",
"count": 3
},
{
"date": "2026-04-08",
"count": 4
},
{
"date": "2026-04-09",
"count": 3
},
{
"date": "2026-04-10",
"count": 9
},
{
"date": "2026-04-11",
"count": 4
},
{
"date": "2026-04-12",
"count": 7
},
{
"date": "2026-04-13",
"count": 5
},
{
"date": "2026-04-14",
"count": 2
},
{
"date": "2026-04-15",
"count": 1
},
{
"date": "2026-04-16",
"count": 4
},
{
"date": "2026-04-17",
"count": 3
},
{
"date": "2026-04-18",
"count": 2
},
{
"date": "2026-04-19",
"count": 7
},
{
"date": "2026-04-20",
"count": 2
},
{
"date": "2026-04-21",
"count": 2
},
{
"date": "2026-04-23",
"count": 4
},
{
"date": "2026-04-24",
"count": 1
},
{
"date": "2026-04-25",
"count": 3
},
{
"date": "2026-04-26",
"count": 2
},
{
"date": "2026-04-27",
"count": 1
},
{
"date": "2026-04-28",
"count": 2
},
{
"date": "2026-04-29",
"count": 5
},
{
"date": "2026-04-30",
"count": 11
},
{
"date": "2026-05-01",
"count": 12
},
{
"date": "2026-05-03",
"count": 3
},
{
"date": "2026-05-04",
"count": 4
},
{
"date": "2026-05-05",
"count": 2
},
{
"date": "2026-05-07",
"count": 2
},
{
"date": "2026-05-08",
"count": 1
},
{
"date": "2026-05-09",
"count": 1
},
{
"date": "2026-05-10",
"count": 4
},
{
"date": "2026-05-12",
"count": 1
},
{
"date": "2026-05-13",
"count": 2
},
{
"date": "2026-05-14",
"count": 4
},
{
"date": "2026-05-15",
"count": 3
},
{
"date": "2026-05-16",
"count": 1
},
{
"date": "2026-05-17",
"count": 3
},
{
"date": "2026-05-18",
"count": 6
},
{
"date": "2026-05-19",
"count": 4
},
{
"date": "2026-05-20",
"count": 2
},
{
"date": "2026-05-21",
"count": 3
},
{
"date": "2026-05-22",
"count": 3
},
{
"date": "2026-05-23",
"count": 2
},
{
"date": "2026-05-24",
"count": 1
},
{
"date": "2026-05-25",
"count": 1
},
{
"date": "2026-05-26",
"count": 3
},
{
"date": "2026-05-27",
"count": 3
},
{
"date": "2026-05-28",
"count": 2
},
{
"date": "2026-05-29",
"count": 1
},
{
"date": "2026-05-30",
"count": 2
},
{
"date": "2026-05-31",
"count": 5
},
{
"date": "2026-06-01",
"count": 1
},
{
"date": "2026-06-02",
"count": 3
},
{
"date": "2026-06-04",
"count": 1
},
{
"date": "2026-06-05",
"count": 2
},
{
"date": "2026-06-06",
"count": 1
},
{
"date": "2026-06-07",
"count": 5
},
{
"date": "2026-06-08",
"count": 3
},
{
"date": "2026-06-09",
"count": 3
},
{
"date": "2026-06-10",
"count": 4
},
{
"date": "2026-06-11",
"count": 2
},
{
"date": "2026-06-12",
"count": 3
},
{
"date": "2026-06-13",
"count": 3
},
{
"date": "2026-06-14",
"count": 1
},
{
"date": "2026-06-15",
"count": 1
},
{
"date": "2026-06-16",
"count": 2
},
{
"date": "2026-06-17",
"count": 2
},
{
"date": "2026-06-18",
"count": 3
},
{
"date": "2026-06-19",
"count": 2
},
{
"date": "2026-06-20",
"count": 9
},
{
"date": "2026-06-21",
"count": 14
},
{
"date": "2026-06-22",
"count": 17
},
{
"date": "2026-06-23",
"count": 6
},
{
"date": "2026-06-24",
"count": 3
},
{
"date": "2026-06-25",
"count": 1
},
{
"date": "2026-06-26",
"count": 3
},
{
"date": "2026-06-27",
"count": 2
},
{
"date": "2026-06-28",
"count": 1
},
{
"date": "2026-06-29",
"count": 4
},
{
"date": "2026-06-30",
"count": 1
},
{
"date": "2026-07-01",
"count": 1
},
{
"date": "2026-07-02",
"count": 3
},
{
"date": "2026-07-03",
"count": 4
},
{
"date": "2026-07-04",
"count": 5
},
{
"date": "2026-07-05",
"count": 2
},
{
"date": "2026-07-06",
"count": 2
},
{
"date": "2026-07-07",
"count": 5
},
{
"date": "2026-07-08",
"count": 2
},
{
"date": "2026-07-11",
"count": 1
},
{
"date": "2026-07-12",
"count": 2
},
{
"date": "2026-07-14",
"count": 2
},
{
"date": "2026-07-15",
"count": 4
},
{
"date": "2026-07-16",
"count": 3
},
{
"date": "2026-07-17",
"count": 5
},
{
"date": "2026-07-18",
"count": 1
},
{
"date": "2026-07-19",
"count": 3
},
{
"date": "2026-07-20",
"count": 3
},
{
"date": "2026-07-21",
"count": 3
}
],
"complete": false,
"collected": 1000,
"total_stars": 1942
},
"open_issues_and_prs": 69
},
"ai_readiness": {
"has_nix": true,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": true,
"has_mcp_signal": true,
"bootstrap_files": [
"Makefile"
],
"api_schema_files": [
"api/openapi.yaml",
"pkg/client/openapi.yaml"
],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [
"go.mod"
],
"largest_source_bytes": 237397,
"source_files_sampled": 823,
"oversized_source_files": 20,
"agent_instruction_files": [
"AGENTS.md",
"CLAUDE.md"
],
"agent_instruction_max_bytes": 15076
},
"dependencies": {
"manifests": [
"docs/pyproject.toml",
"go.mod"
],
"advisories": {
"error": null,
"scope": "repository_graph",
"source": "osv",
"findings": [
{
"name": "google.golang.org/grpc",
"direct": false,
"version": "v1.81.1",
"severity": "critical",
"ecosystem": "go",
"cvss_score": 9.1,
"advisory_ids": [
"GHSA-hrxh-6v49-42gf"
],
"fixed_version": "1.82.1",
"advisory_count": 1,
"oldest_advisory_days": 0
},
{
"name": "golang.org/x/crypto",
"direct": true,
"version": "v0.53.0",
"severity": "unknown",
"ecosystem": "go",
"cvss_score": null,
"advisory_ids": [
"GO-2026-5932"
],
"fixed_version": null,
"advisory_count": 1,
"oldest_advisory_days": 14
}
],
"collected": true,
"malicious": [],
"truncated": false,
"by_severity": {
"unknown": 1,
"critical": 1
},
"advisory_count": 2,
"affected_count": 2,
"assessed_count": 155,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 1
},
"ecosystems": [
"go",
"pypi"
],
"dependencies": [
{
"name": "charm.land/bubbles/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.1.1"
},
{
"name": "charm.land/bubbletea/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.8"
},
{
"name": "charm.land/glamour/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.1"
},
{
"name": "charm.land/huh/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.3"
},
{
"name": "charm.land/lipgloss/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.5"
},
{
"name": "github.com/BurntSushi/toml",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.6.0"
},
{
"name": "github.com/asg017/sqlite-vec-go-bindings",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.1.6"
},
{
"name": "github.com/charmbracelet/x/ansi",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.11.7"
},
{
"name": "github.com/coreos/go-oidc/v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.19.0"
},
{
"name": "github.com/danielgtaylor/huma/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.38.0"
},
{
"name": "github.com/doordash-oss/oapi-codegen-dd/v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.75.7"
},
{
"name": "github.com/duckdb/duckdb-go/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.10504.0"
},
{
"name": "github.com/emersion/go-imap/v2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v2.0.0-beta.8"
},
{
"name": "github.com/emersion/go-message",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.18.2"
},
{
"name": "github.com/emersion/go-sasl",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20241020182733-b788ff22d5a6"
},
{
"name": "github.com/go-playground/validator/v10",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v10.30.3"
},
{
"name": "github.com/gofrs/flock",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.13.0"
},
{
"name": "github.com/gogs/chardet",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20211120154057-b7413eaefb8f"
},
{
"name": "github.com/google/go-cmp",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.7.0"
},
{
"name": "github.com/jackc/pgx/v5",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v5.10.0"
},
{
"name": "github.com/jhillyerd/enmime",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.0"
},
{
"name": "github.com/mark3labs/mcp-go",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.55.1"
},
{
"name": "github.com/mattn/go-isatty",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.22"
},
{
"name": "github.com/mattn/go-runewidth",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.24"
},
{
"name": "github.com/mattn/go-sqlite3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.14.47"
},
{
"name": "github.com/modelcontextprotocol/go-sdk",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.6.1"
},
{
"name": "github.com/mooijtech/go-pst/v6",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v6.0.2"
},
{
"name": "github.com/robfig/cron/v3",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v3.0.1"
},
{
"name": "github.com/rotisserie/eris",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.5.4"
},
{
"name": "github.com/shirou/gopsutil/v4",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v4.26.6"
},
{
"name": "github.com/spf13/cobra",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.10.2"
},
{
"name": "github.com/spf13/pflag",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.10"
},
{
"name": "github.com/stretchr/testify",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.11.1"
},
{
"name": "go.kenn.io/kit",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.9.1"
},
{
"name": "golang.org/x/crypto",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.53.0"
},
{
"name": "golang.org/x/net",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.56.0"
},
{
"name": "golang.org/x/oauth2",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.36.0"
},
{
"name": "golang.org/x/sync",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.21.0"
},
{
"name": "golang.org/x/sys",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.46.0"
},
{
"name": "golang.org/x/text",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.39.0"
},
{
"name": "golang.org/x/time",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.15.0"
},
{
"name": "golang.org/x/tools",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.47.0"
},
{
"name": "google.golang.org/api",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.287.0"
},
{
"name": "howett.net/plist",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.1"
}
],
"all_dependencies": {
"error": null,
"source": "github-sbom",
"packages": [
{
"name": "charm.land/bubbles/v2",
"direct": true,
"version": "v2.1.1",
"ecosystem": "go"
},
{
"name": "charm.land/bubbletea/v2",
"direct": true,
"version": "v2.0.8",
"ecosystem": "go"
},
{
"name": "charm.land/glamour/v2",
"direct": true,
"version": "v2.0.1",
"ecosystem": "go"
},
{
"name": "charm.land/huh/v2",
"direct": true,
"version": "v2.0.3",
"ecosystem": "go"
},
{
"name": "charm.land/lipgloss/v2",
"direct": true,
"version": "v2.0.5",
"ecosystem": "go"
},
{
"name": "github.com/asg017/sqlite-vec-go-bindings",
"direct": true,
"version": "v0.1.6",
"ecosystem": "go"
},
{
"name": "github.com/burntsushi/toml",
"direct": true,
"version": "v1.6.0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/ansi",
"direct": true,
"version": "v0.11.7",
"ecosystem": "go"
},
{
"name": "github.com/coreos/go-oidc/v3",
"direct": true,
"version": "v3.19.0",
"ecosystem": "go"
},
{
"name": "github.com/danielgtaylor/huma/v2",
"direct": true,
"version": "v2.38.0",
"ecosystem": "go"
},
{
"name": "github.com/doordash-oss/oapi-codegen-dd/v3",
"direct": true,
"version": "v3.75.7",
"ecosystem": "go"
},
{
"name": "github.com/duckdb/duckdb-go/v2",
"direct": true,
"version": "v2.10504.0",
"ecosystem": "go"
},
{
"name": "github.com/emersion/go-imap/v2",
"direct": true,
"version": "v2.0.0-beta.8",
"ecosystem": "go"
},
{
"name": "github.com/emersion/go-message",
"direct": true,
"version": "v0.18.2",
"ecosystem": "go"
},
{
"name": "github.com/emersion/go-sasl",
"direct": true,
"version": "v0.0.0-20241020182733-b788ff22d5a6",
"ecosystem": "go"
},
{
"name": "github.com/go-playground/validator/v10",
"direct": true,
"version": "v10.30.3",
"ecosystem": "go"
},
{
"name": "github.com/gofrs/flock",
"direct": true,
"version": "v0.13.0",
"ecosystem": "go"
},
{
"name": "github.com/gogs/chardet",
"direct": true,
"version": "v0.0.0-20211120154057-b7413eaefb8f",
"ecosystem": "go"
},
{
"name": "github.com/google/go-cmp",
"direct": true,
"version": "v0.7.0",
"ecosystem": "go"
},
{
"name": "github.com/jackc/pgx/v5",
"direct": true,
"version": "v5.10.0",
"ecosystem": "go"
},
{
"name": "github.com/jhillyerd/enmime",
"direct": true,
"version": "v1.3.0",
"ecosystem": "go"
},
{
"name": "github.com/mark3labs/mcp-go",
"direct": true,
"version": "v0.55.1",
"ecosystem": "go"
},
{
"name": "github.com/mattn/go-isatty",
"direct": true,
"version": "v0.0.22",
"ecosystem": "go"
},
{
"name": "github.com/mattn/go-runewidth",
"direct": true,
"version": "v0.0.24",
"ecosystem": "go"
},
{
"name": "github.com/mattn/go-sqlite3",
"direct": true,
"version": "v1.14.47",
"ecosystem": "go"
},
{
"name": "github.com/modelcontextprotocol/go-sdk",
"direct": true,
"version": "v1.6.1",
"ecosystem": "go"
},
{
"name": "github.com/mooijtech/go-pst/v6",
"direct": true,
"version": "v6.0.2",
"ecosystem": "go"
},
{
"name": "github.com/robfig/cron/v3",
"direct": true,
"version": "v3.0.1",
"ecosystem": "go"
},
{
"name": "github.com/rotisserie/eris",
"direct": true,
"version": "v0.5.4",
"ecosystem": "go"
},
{
"name": "github.com/shirou/gopsutil/v4",
"direct": true,
"version": "v4.26.6",
"ecosystem": "go"
},
{
"name": "github.com/spf13/cobra",
"direct": true,
"version": "v1.10.2",
"ecosystem": "go"
},
{
"name": "github.com/spf13/pflag",
"direct": true,
"version": "v1.0.10",
"ecosystem": "go"
},
{
"name": "github.com/stretchr/testify",
"direct": true,
"version": "v1.11.1",
"ecosystem": "go"
},
{
"name": "go.kenn.io/kit",
"direct": true,
"version": "v0.9.1",
"ecosystem": "go"
},
{
"name": "golang.org/x/crypto",
"direct": true,
"version": "v0.53.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/net",
"direct": true,
"version": "v0.56.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/oauth2",
"direct": true,
"version": "v0.36.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/sync",
"direct": true,
"version": "v0.21.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/sys",
"direct": true,
"version": "v0.46.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/text",
"direct": true,
"version": "v0.39.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/time",
"direct": true,
"version": "v0.15.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/tools",
"direct": true,
"version": "v0.47.0",
"ecosystem": "go"
},
{
"name": "google.golang.org/api",
"direct": true,
"version": "v0.287.0",
"ecosystem": "go"
},
{
"name": "howett.net/plist",
"direct": true,
"version": "v1.0.1",
"ecosystem": "go"
},
{
"name": "cloud.google.com/go/auth",
"direct": false,
"version": "v0.20.0",
"ecosystem": "go"
},
{
"name": "cloud.google.com/go/auth/oauth2adapt",
"direct": false,
"version": "v0.2.8",
"ecosystem": "go"
},
{
"name": "cloud.google.com/go/compute/metadata",
"direct": false,
"version": "v0.9.0",
"ecosystem": "go"
},
{
"name": "github.com/alecthomas/chroma/v2",
"direct": false,
"version": "v2.14.0",
"ecosystem": "go"
},
{
"name": "github.com/apache/arrow-go/v18",
"direct": false,
"version": "v18.5.1",
"ecosystem": "go"
},
{
"name": "github.com/atotto/clipboard",
"direct": false,
"version": "v0.1.4",
"ecosystem": "go"
},
{
"name": "github.com/aymerick/douceur",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/catppuccin/go",
"direct": false,
"version": "v0.3.0",
"ecosystem": "go"
},
{
"name": "github.com/cention-sany/utf7",
"direct": false,
"version": "v0.0.0-20170124080048-26cad61bd60a",
"ecosystem": "go"
},
{
"name": "github.com/cespare/xxhash/v2",
"direct": false,
"version": "v2.3.0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/colorprofile",
"direct": false,
"version": "v0.4.3",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/ultraviolet",
"direct": false,
"version": "v0.0.0-20260703014108-f5a850f9c2b7",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/exp/ordered",
"direct": false,
"version": "v0.1.0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/exp/slice",
"direct": false,
"version": "v0.0.0-20250327172914-2fdc97757edf",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/exp/strings",
"direct": false,
"version": "v0.0.0-20240722160745-212f7b056ed0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/term",
"direct": false,
"version": "v0.2.2",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/termios",
"direct": false,
"version": "v0.1.1",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/windows",
"direct": false,
"version": "v0.2.2",
"ecosystem": "go"
},
{
"name": "github.com/clipperhouse/displaywidth",
"direct": false,
"version": "v0.11.0",
"ecosystem": "go"
},
{
"name": "github.com/clipperhouse/uax29/v2",
"direct": false,
"version": "v2.7.0",
"ecosystem": "go"
},
{
"name": "github.com/davecgh/go-spew",
"direct": false,
"version": "v1.1.2-0.20180830191138-d8f796af33cc",
"ecosystem": "go"
},
{
"name": "github.com/dlclark/regexp2",
"direct": false,
"version": "v1.11.0",
"ecosystem": "go"
},
{
"name": "github.com/duckdb/duckdb-go-bindings",
"direct": false,
"version": "v0.10504.0",
"ecosystem": "go"
},
{
"name": "github.com/duckdb/duckdb-go-bindings/lib/darwin-amd64",
"direct": false,
"version": "v0.10504.0",
"ecosystem": "go"
},
{
"name": "github.com/duckdb/duckdb-go-bindings/lib/darwin-arm64",
"direct": false,
"version": "v0.10504.0",
"ecosystem": "go"
},
{
"name": "github.com/duckdb/duckdb-go-bindings/lib/linux-amd64",
"direct": false,
"version": "v0.10504.0",
"ecosystem": "go"
},
{
"name": "github.com/duckdb/duckdb-go-bindings/lib/linux-arm64",
"direct": false,
"version": "v0.10504.0",
"ecosystem": "go"
},
{
"name": "github.com/duckdb/duckdb-go-bindings/lib/windows-amd64",
"direct": false,
"version": "v0.10504.0",
"ecosystem": "go"
},
{
"name": "github.com/dustin/go-humanize",
"direct": false,
"version": "v1.0.1",
"ecosystem": "go"
},
{
"name": "github.com/ebitengine/purego",
"direct": false,
"version": "v0.10.0",
"ecosystem": "go"
},
{
"name": "github.com/felixge/httpsnoop",
"direct": false,
"version": "v1.0.4",
"ecosystem": "go"
},
{
"name": "github.com/gabriel-vasile/mimetype",
"direct": false,
"version": "v1.4.13",
"ecosystem": "go"
},
{
"name": "github.com/go-jose/go-jose/v4",
"direct": false,
"version": "v4.1.4",
"ecosystem": "go"
},
{
"name": "github.com/go-logr/logr",
"direct": false,
"version": "v1.4.3",
"ecosystem": "go"
},
{
"name": "github.com/go-logr/stdr",
"direct": false,
"version": "v1.2.2",
"ecosystem": "go"
},
{
"name": "github.com/go-ole/go-ole",
"direct": false,
"version": "v1.2.6",
"ecosystem": "go"
},
{
"name": "github.com/go-playground/locales",
"direct": false,
"version": "v0.14.1",
"ecosystem": "go"
},
{
"name": "github.com/go-playground/universal-translator",
"direct": false,
"version": "v0.18.1",
"ecosystem": "go"
},
{
"name": "github.com/go-viper/mapstructure/v2",
"direct": false,
"version": "v2.5.0",
"ecosystem": "go"
},
{
"name": "github.com/goccy/go-json",
"direct": false,
"version": "v0.10.6",
"ecosystem": "go"
},
{
"name": "github.com/godzie44/go-uring",
"direct": false,
"version": "v0.0.0-20220926161041-69611e8b13d5",
"ecosystem": "go"
},
{
"name": "github.com/google/flatbuffers",
"direct": false,
"version": "v25.12.19+incompatible",
"ecosystem": "go"
},
{
"name": "github.com/google/jsonschema-go",
"direct": false,
"version": "v0.4.3",
"ecosystem": "go"
},
{
"name": "github.com/google/s2a-go",
"direct": false,
"version": "v0.1.9",
"ecosystem": "go"
},
{
"name": "github.com/google/uuid",
"direct": false,
"version": "v1.6.0",
"ecosystem": "go"
},
{
"name": "github.com/googleapis/enterprise-certificate-proxy",
"direct": false,
"version": "v0.3.17",
"ecosystem": "go"
},
{
"name": "github.com/googleapis/gax-go/v2",
"direct": false,
"version": "v2.22.0",
"ecosystem": "go"
},
{
"name": "github.com/gorilla/css",
"direct": false,
"version": "v1.0.1",
"ecosystem": "go"
},
{
"name": "github.com/inconshreveable/mousetrap",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "github.com/jackc/pgpassfile",
"direct": false,
"version": "v1.0.0",
"ecosystem": "go"
},
{
"name": "github.com/jackc/pgservicefile",
"direct": false,
"version": "v0.0.0-20240606120523-5a60cdf6a761",
"ecosystem": "go"
},
{
"name": "github.com/jackc/puddle/v2",
"direct": false,
"version": "v2.2.2",
"ecosystem": "go"
},
{
"name": "github.com/jaytaylor/html2text",
"direct": false,
"version": "v0.0.0-20230321000545-74c2419ad056",
"ecosystem": "go"
},
{
"name": "github.com/klauspost/compress",
"direct": false,
"version": "v1.19.0",
"ecosystem": "go"
},
{
"name": "github.com/klauspost/cpuid/v2",
"direct": false,
"version": "v2.3.0",
"ecosystem": "go"
},
{
"name": "github.com/leodido/go-urn",
"direct": false,
"version": "v1.4.0",
"ecosystem": "go"
},
{
"name": "github.com/libp2p/go-sockaddr",
"direct": false,
"version": "v0.1.1",
"ecosystem": "go"
},
{
"name": "github.com/lucasb-eyer/go-colorful",
"direct": false,
"version": "v1.4.0",
"ecosystem": "go"
},
{
"name": "github.com/lufia/plan9stats",
"direct": false,
"version": "v0.0.0-20211012122336-39d0f177ccd0",
"ecosystem": "go"
},
{
"name": "github.com/microcosm-cc/bluemonday",
"direct": false,
"version": "v1.0.27",
"ecosystem": "go"
},
{
"name": "github.com/mitchellh/hashstructure/v2",
"direct": false,
"version": "v2.0.2",
"ecosystem": "go"
},
{
"name": "github.com/muesli/cancelreader",
"direct": false,
"version": "v0.2.2",
"ecosystem": "go"
},
{
"name": "github.com/oklog/ulid/v2",
"direct": false,
"version": "v2.1.1",
"ecosystem": "go"
},
{
"name": "github.com/olekukonko/tablewriter",
"direct": false,
"version": "v0.0.5",
"ecosystem": "go"
},
{
"name": "github.com/philhofer/fwd",
"direct": false,
"version": "v1.2.0",
"ecosystem": "go"
},
{
"name": "github.com/pierrec/lz4/v4",
"direct": false,
"version": "v4.1.25",
"ecosystem": "go"
},
{
"name": "github.com/pkg/errors",
"direct": false,
"version": "v0.9.1",
"ecosystem": "go"
},
{
"name": "github.com/pmezard/go-difflib",
"direct": false,
"version": "v1.0.1-0.20181226105442-5d4384ee4fb2",
"ecosystem": "go"
},
{
"name": "github.com/power-devops/perfstat",
"direct": false,
"version": "v0.0.0-20240221224432-82ca36839d55",
"ecosystem": "go"
},
{
"name": "github.com/rivo/uniseg",
"direct": false,
"version": "v0.4.7",
"ecosystem": "go"
},
{
"name": "github.com/santhosh-tekuri/jsonschema/v6",
"direct": false,
"version": "v6.0.2",
"ecosystem": "go"
},
{
"name": "github.com/segmentio/asm",
"direct": false,
"version": "v1.1.3",
"ecosystem": "go"
},
{
"name": "github.com/segmentio/encoding",
"direct": false,
"version": "v0.5.4",
"ecosystem": "go"
},
{
"name": "github.com/spf13/cast",
"direct": false,
"version": "v1.7.1",
"ecosystem": "go"
},
{
"name": "github.com/ssor/bom",
"direct": false,
"version": "v0.0.0-20170718123548-6386211fdfcf",
"ecosystem": "go"
},
{
"name": "github.com/tidwall/btree",
"direct": false,
"version": "v1.6.0",
"ecosystem": "go"
},
{
"name": "github.com/tinylib/msgp",
"direct": false,
"version": "v1.6.4",
"ecosystem": "go"
},
{
"name": "github.com/tklauser/go-sysconf",
"direct": false,
"version": "v0.3.16",
"ecosystem": "go"
},
{
"name": "github.com/tklauser/numcpus",
"direct": false,
"version": "v0.11.0",
"ecosystem": "go"
},
{
"name": "github.com/xo/terminfo",
"direct": false,
"version": "v0.0.0-20220910002029-abceb7e1c41e",
"ecosystem": "go"
},
{
"name": "github.com/yosida95/uritemplate/v3",
"direct": false,
"version": "v3.0.2",
"ecosystem": "go"
},
{
"name": "github.com/yuin/goldmark",
"direct": false,
"version": "v1.7.17",
"ecosystem": "go"
},
{
"name": "github.com/yuin/goldmark-emoji",
"direct": false,
"version": "v1.0.5",
"ecosystem": "go"
},
{
"name": "github.com/yusufpapurcu/wmi",
"direct": false,
"version": "v1.2.4",
"ecosystem": "go"
},
{
"name": "github.com/zeebo/xxh3",
"direct": false,
"version": "v1.1.0",
"ecosystem": "go"
},
{
"name": "go.opentelemetry.io/auto/sdk",
"direct": false,
"version": "v1.2.1",
"ecosystem": "go"
},
{
"name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
"direct": false,
"version": "v0.67.0",
"ecosystem": "go"
},
{
"name": "go.opentelemetry.io/otel",
"direct": false,
"version": "v1.44.0",
"ecosystem": "go"
},
{
"name": "go.opentelemetry.io/otel/metric",
"direct": false,
"version": "v1.44.0",
"ecosystem": "go"
},
{
"name": "go.opentelemetry.io/otel/trace",
"direct": false,
"version": "v1.44.0",
"ecosystem": "go"
},
{
"name": "go.yaml.in/yaml/v4",
"direct": false,
"version": "v4.0.0-rc.4",
"ecosystem": "go"
},
{
"name": "golang.org/x/exp",
"direct": false,
"version": "v0.0.0-20260112195511-716be5621a96",
"ecosystem": "go"
},
{
"name": "golang.org/x/mod",
"direct": false,
"version": "v0.37.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/telemetry",
"direct": false,
"version": "v0.0.0-20260625142307-59b4966ccb57",
"ecosystem": "go"
},
{
"name": "golang.org/x/xerrors",
"direct": false,
"version": "v0.0.0-20240903120638-7835f813f4da",
"ecosystem": "go"
},
{
"name": "google.golang.org/genproto/googleapis/rpc",
"direct": false,
"version": "v0.0.0-20260706201446-f0a921348800",
"ecosystem": "go"
},
{
"name": "google.golang.org/grpc",
"direct": false,
"version": "v1.81.1",
"ecosystem": "go"
},
{
"name": "google.golang.org/protobuf",
"direct": false,
"version": "v1.36.11",
"ecosystem": "go"
},
{
"name": "gopkg.in/yaml.v3",
"direct": false,
"version": "v3.0.1",
"ecosystem": "go"
},
{
"name": "click",
"direct": false,
"version": "8.4.1",
"ecosystem": "pypi"
},
{
"name": "colorama",
"direct": false,
"version": "0.4.6",
"ecosystem": "pypi"
},
{
"name": "deepmerge",
"direct": false,
"version": "2.0",
"ecosystem": "pypi"
},
{
"name": "jinja2",
"direct": false,
"version": "3.1.6",
"ecosystem": "pypi"
},
{
"name": "markdown",
"direct": false,
"version": "3.10.2",
"ecosystem": "pypi"
},
{
"name": "markupsafe",
"direct": false,
"version": "3.0.3",
"ecosystem": "pypi"
},
{
"name": "msgvault-docs",
"direct": false,
"version": "0.0.0",
"ecosystem": "pypi"
},
{
"name": "pygments",
"direct": false,
"version": "2.20.0",
"ecosystem": "pypi"
},
{
"name": "pymdown-extensions",
"direct": false,
"version": "10.21.3",
"ecosystem": "pypi"
},
{
"name": "pyyaml",
"direct": false,
"version": "6.0.3",
"ecosystem": "pypi"
},
{
"name": "tomli",
"direct": false,
"version": "2.4.1",
"ecosystem": "pypi"
},
{
"name": "zensical",
"direct": false,
"version": "0.0.45",
"ecosystem": "pypi"
}
],
"collected": true,
"truncated": false,
"total_count": 155,
"direct_count": 44,
"indirect_count": 111
}
},
"maintainership": {
"issues": {
"open_prs": 4,
"merged_prs": 279,
"open_issues": 65,
"closed_ratio": 0.549,
"closed_issues": 79,
"closed_unmerged_prs": 69
},
"bus_factor": 1,
"bot_contributors": 1,
"top_contributors": [
{
"type": "User",
"login": "wesm",
"commits": 291,
"avatar_url": "https://avatars.githubusercontent.com/u/329591?v=4"
},
{
"type": "User",
"login": "hughdbrown",
"commits": 14,
"avatar_url": "https://avatars.githubusercontent.com/u/90322?v=4"
},
{
"type": "User",
"login": "cpcloud",
"commits": 10,
"avatar_url": "https://avatars.githubusercontent.com/u/417981?v=4"
},
{
"type": "User",
"login": "danshapiro",
"commits": 10,
"avatar_url": "https://avatars.githubusercontent.com/u/3732858?v=4"
},
{
"type": "User",
"login": "jesserobbins",
"commits": 8,
"avatar_url": "https://avatars.githubusercontent.com/u/25235?v=4"
},
{
"type": "User",
"login": "mariusvniekerk",
"commits": 7,
"avatar_url": "https://avatars.githubusercontent.com/u/73973?v=4"
},
{
"type": "User",
"login": "sweenzor",
"commits": 7,
"avatar_url": "https://avatars.githubusercontent.com/u/212338?v=4"
},
{
"type": "User",
"login": "robelkin",
"commits": 6,
"avatar_url": "https://avatars.githubusercontent.com/u/187335?v=4"
},
{
"type": "User",
"login": "webgress",
"commits": 6,
"avatar_url": "https://avatars.githubusercontent.com/u/6012552?v=4"
},
{
"type": "User",
"login": "endolith",
"commits": 6,
"avatar_url": "https://avatars.githubusercontent.com/u/58611?v=4"
}
],
"contributors_sampled": 35,
"top_contributor_share": 0.717
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"ci.yml",
"docker.yml",
"release.yml"
],
"has_docs_dir": true,
"linter_configs": [
".golangci.yml"
],
"has_editorconfig": false,
"has_linter_config": true,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"go.sum",
"uv.lock"
],
"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": 3,
"reason": "branch protection is not maximal on development and all release branches",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
},
{
"name": "CI-Tests",
"score": 10,
"reason": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
},
{
"name": "CII-Best-Practices",
"score": 0,
"reason": "no effort to earn an OpenSSF best practices badge detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
},
{
"name": "Code-Review",
"score": 2,
"reason": "Found 7/30 approved changesets -- score normalized to 2",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 10,
"reason": "project has 14 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": 10,
"reason": "update tool detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
},
{
"name": "Fuzzing",
"score": 0,
"reason": "project is not fuzzed",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
},
{
"name": "License",
"score": 10,
"reason": "license file detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
},
{
"name": "Maintained",
"score": 10,
"reason": "30 commit(s) and 9 issue activity found in the last 90 days -- score normalized to 10",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
},
{
"name": "Packaging",
"score": 10,
"reason": "packaging workflow detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
},
{
"name": "Pinned-Dependencies",
"score": 8,
"reason": "dependency not pinned by hash detected -- score normalized to 8",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 7,
"reason": "SAST tool is not run on all commits -- score normalized to 7",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
},
{
"name": "Security-Policy",
"score": 4,
"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": 8,
"reason": "2 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "a668365573992cd67c4310fbf23c85462de18ba0",
"ran_at": "2026-07-22T05:05:08Z",
"aggregate_score": 6.1,
"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-21T22:31:59Z",
"oldest_open_prs": [
{
"number": 332,
"created_at": "2026-05-21T16:03:41Z",
"last_comment_at": "2026-07-05T20:53:23Z",
"last_comment_author": "wesm"
},
{
"number": 492,
"created_at": "2026-07-20T16:38:55Z",
"last_comment_at": "2026-07-22T05:00:49Z",
"last_comment_author": "roborev-ci"
},
{
"number": 493,
"created_at": "2026-07-20T19:20:15Z",
"last_comment_at": "2026-07-20T21:44:50Z",
"last_comment_author": "roborev-ci"
},
{
"number": 494,
"created_at": "2026-07-20T21:12:25Z",
"last_comment_at": "2026-07-21T11:41:24Z",
"last_comment_author": "roborev-ci"
}
],
"last_merged_pr_at": "2026-07-21T22:25:57Z",
"ci_last_conclusion": "SUCCESS",
"oldest_open_issues": [
{
"number": 40,
"created_at": "2026-02-03T17:47:14Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 41,
"created_at": "2026-02-03T17:59:57Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 44,
"created_at": "2026-02-03T21:57:49Z",
"last_comment_at": "2026-02-05T18:20:30Z",
"last_comment_author": "larray"
},
{
"number": 72,
"created_at": "2026-02-05T15:57:48Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 88,
"created_at": "2026-02-05T23:02:32Z",
"last_comment_at": "2026-02-05T23:08:08Z",
"last_comment_author": "eliluong"
},
{
"number": 89,
"created_at": "2026-02-06T03:25:46Z",
"last_comment_at": "2026-02-06T14:40:03Z",
"last_comment_author": "wesm"
},
{
"number": 92,
"created_at": "2026-02-06T20:04:35Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 96,
"created_at": "2026-02-06T21:42:53Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 100,
"created_at": "2026-02-07T17:25:05Z",
"last_comment_at": "2026-02-07T18:27:15Z",
"last_comment_author": "hughdbrown"
},
{
"number": 107,
"created_at": "2026-02-08T03:57:24Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 116,
"created_at": "2026-02-09T18:47:47Z",
"last_comment_at": "2026-03-02T20:45:12Z",
"last_comment_author": "EconoBen"
},
{
"number": 122,
"created_at": "2026-02-10T03:05:55Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 129,
"created_at": "2026-02-13T12:44:35Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 134,
"created_at": "2026-02-15T13:16:10Z",
"last_comment_at": "2026-02-25T21:12:44Z",
"last_comment_author": "robince"
},
{
"number": 136,
"created_at": "2026-02-15T21:50:59Z",
"last_comment_at": "2026-04-04T23:52:58Z",
"last_comment_author": "m13v"
},
{
"number": 147,
"created_at": "2026-02-17T17:08:45Z",
"last_comment_at": "2026-02-24T11:43:40Z",
"last_comment_author": "jkleske"
},
{
"number": 154,
"created_at": "2026-02-25T00:28:23Z",
"last_comment_at": null,
"last_comment_author": null
},
{
"number": 156,
"created_at": "2026-02-25T12:52:50Z",
"last_comment_at": "2026-05-01T00:32:39Z",
"last_comment_author": "hightowe"
},
{
"number": 158,
"created_at": "2026-02-26T11:01:04Z",
"last_comment_at": "2026-02-27T10:51:07Z",
"last_comment_author": "tekumara"
},
{
"number": 175,
"created_at": "2026-03-07T18:19:30Z",
"last_comment_at": null,
"last_comment_author": null
}
]
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/kenn-io/msgvault",
"host": "github.com",
"name": "msgvault",
"owner": "kenn-io"
},
"metrics": {
"overall": {
"key": "overall",
"band": "good",
"name": "Overall health",
"note": null,
"notes": [],
"value": 72,
"inputs": {
"security": 67,
"vitality": 85,
"community": 64,
"governance": 60,
"engineering": 82
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "excellent",
"name": "Vitality",
"value": 85,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 81,
"inputs": {
"commits_last_year": 442,
"human_commit_share": 0.9,
"days_since_last_push": 0,
"active_weeks_last_year": 24
},
"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": "24/52 weeks with commits",
"points": 16.6,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 24
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "442 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 442
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "30 commit(s) and 9 issue activity found in the last 90 days -- score normalized to 10",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "release_discipline",
"band": "excellent",
"name": "Release discipline",
"note": null,
"notes": [],
"value": 90,
"inputs": {
"releases_count": 34,
"latest_release_tag": "v0.18.0",
"releases_from_tags": false,
"days_since_latest_release": 5,
"mean_days_between_releases": 10.2
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "34 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 34
}
}
],
"max_points": 27
},
{
"key": "release_recency",
"name": "Release recency",
"detail": "latest release 5 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "release_recency",
"params": {
"days": 5
}
}
],
"max_points": 36
},
{
"key": "release_cadence",
"name": "Release cadence",
"detail": "a release every ~10.2 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 10.2
}
}
],
"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": "moderate",
"name": "Community & Adoption",
"value": 64,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "good",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 77,
"inputs": {
"forks": 125,
"stars": 1942,
"watchers": 15,
"growth_state": "organic",
"growth_factor_pct": 100
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "1,942 stars",
"points": 53.3,
"status": "partial",
"details": [
{
"code": "stars",
"params": {
"count": 1942
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "125 forks",
"points": 17.4,
"status": "partial",
"details": [
{
"code": "forks",
"params": {
"count": 125
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "15 watchers",
"points": 6.4,
"status": "partial",
"details": [
{
"code": "watchers",
"params": {
"count": 15
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "moderate",
"name": "Sustainability & Governance",
"value": 60,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "at_risk",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 39,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 35,
"top_contributor_share": 0.717
},
"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 72% of commits",
"points": 6.4,
"status": "partial",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 72
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "35 contributors",
"points": 13.5,
"status": "met",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 35
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 14 contributing companies or organizations",
"points": 10,
"status": "met",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "moderate",
"name": "Issue & PR responsiveness",
"note": null,
"notes": [],
"value": 59,
"inputs": {
"merged_prs": 279,
"open_issues": 65,
"closed_issues": 79,
"issue_closed_ratio": 0.549,
"closed_unmerged_prs": 69
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "55% of issues closed",
"points": 25.7,
"status": "partial",
"details": [
{
"code": "issues_closed_share",
"params": {
"share": 55
}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "279/348 decided PRs merged",
"points": 30.7,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 279,
"decided": 348
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 7/30 approved changesets -- score normalized to 2",
"points": 3,
"status": "partial",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "moderate",
"name": "Ownership & stewardship",
"note": null,
"notes": [],
"value": 54,
"inputs": {
"followers": 133,
"owner_type": "Organization",
"is_verified": null,
"owner_login": "kenn-io",
"public_repos": 12,
"account_age_days": 165
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "organization-owned",
"points": 30,
"status": "met",
"details": [
{
"code": "owner_organization",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "133 followers of kenn-io",
"points": 15.3,
"status": "partial",
"details": [
{
"code": "owner_followers",
"params": {
"count": 133,
"login": "kenn-io"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "12 public repos, account ~0 yr old",
"points": 9,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 12
}
},
{
"code": "account_age_years",
"params": {
"years": 0
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"go.kenn.io/msgvault"
],
"ecosystems": "go",
"any_deprecated": false,
"min_days_since_publish": 7
},
"components": [
{
"key": "published_resolvable",
"name": "Published & resolvable",
"detail": "1 package(s) on go",
"points": 25,
"status": "met",
"details": [
{
"code": "packages_published",
"params": {
"count": 1,
"ecosystems": "go"
}
}
],
"max_points": 25
},
{
"key": "publish_recency",
"name": "Publish recency",
"detail": "latest publish 7 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 7
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "36 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 36
}
}
],
"max_points": 20
},
{
"key": "not_deprecated",
"name": "Not deprecated",
"detail": "active, not deprecated or yanked",
"points": 20,
"status": "met",
"details": [
{
"code": "package_not_deprecated",
"params": {}
}
],
"max_points": 20
}
]
}
],
"description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
},
{
"key": "engineering",
"band": "good",
"name": "Engineering Quality",
"value": 82,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "good",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 84,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": true,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "3 workflow(s)",
"points": 24,
"status": "met",
"details": [
{
"code": "ci_workflows",
"params": {
"count": 3
}
}
],
"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": ".golangci.yml",
"points": 16,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".golangci.yml"
}
}
],
"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": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
"points": 20,
"status": "met",
"details": [],
"max_points": 20
}
]
},
{
"key": "documentation",
"band": "good",
"name": "Documentation",
"note": null,
"notes": [],
"value": 80,
"inputs": {
"topics": [],
"has_wiki": false,
"homepage": "https://msgvault.io",
"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": "https://msgvault.io",
"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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
},
{
"key": "wiki",
"name": "Wiki",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 10
}
]
}
],
"description": "Are baseline engineering and documentation practices in place?"
},
{
"key": "security",
"band": "moderate",
"name": "Security",
"value": 67,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "moderate",
"name": "Security posture",
"note": null,
"notes": [],
"value": 61,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 18,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 0,
"scorecard_aggregate": 6.1
},
"components": [
{
"key": "binary_artifacts",
"name": "Binary-Artifacts",
"detail": "no binaries found in the repo",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "branch_protection",
"name": "Branch-Protection",
"detail": "branch protection is not maximal on development and all release branches",
"points": 2.2,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "ci_tests",
"name": "CI-Tests",
"detail": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "cii_best_practices",
"name": "CII-Best-Practices",
"detail": "no effort to earn an OpenSSF best practices badge detected",
"points": 0,
"status": "missed",
"details": [],
"max_points": 2.5
},
{
"key": "code_review",
"name": "Code-Review",
"detail": "Found 7/30 approved changesets -- score normalized to 2",
"points": 1.5,
"status": "partial",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 14 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": "update tool detected",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "fuzzing",
"name": "Fuzzing",
"detail": "project is not fuzzed",
"points": 0,
"status": "missed",
"details": [],
"max_points": 5
},
{
"key": "license",
"name": "License",
"detail": "license file detected",
"points": 2.5,
"status": "met",
"details": [],
"max_points": 2.5
},
{
"key": "maintained",
"name": "Maintained",
"detail": "30 commit(s) and 9 issue activity found in the last 90 days -- score normalized to 10",
"points": 7.5,
"status": "met",
"details": [],
"max_points": 7.5
},
{
"key": "packaging",
"name": "Packaging",
"detail": "packaging workflow detected",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "pinned_dependencies",
"name": "Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 8",
"points": 4,
"status": "partial",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is not run on all commits -- score normalized to 7",
"points": 3.5,
"status": "partial",
"details": [],
"max_points": 5
},
{
"key": "security_policy",
"name": "Security-Policy",
"detail": "security policy file detected",
"points": 2,
"status": "partial",
"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": "2 existing vulnerabilities detected",
"points": 6,
"status": "partial",
"details": [],
"max_points": 7.5
}
]
},
{
"key": "dependency_advisories",
"band": "excellent",
"name": "Dependency advisories",
"note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories. Remaining weights renormalized. Matched 155 resolved dependencies against OSV. This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"indirect_dependencies_free_of_known_advisories"
]
}
},
{
"code": "weights_renormalized",
"params": {}
},
{
"code": "advisories_scope_repository",
"params": {
"assessed": 155
}
},
{
"code": "advisories_repo_graph_caveat",
"params": {}
},
{
"code": "advisories_reachability",
"params": {}
}
],
"value": 89,
"inputs": {
"source": "osv",
"advisories": 2,
"affected_packages": 2,
"assessed_packages": 155,
"unassessed_packages": 0,
"affected_by_severity": "critical 1, unknown 1",
"direct_affected_packages": 1
},
"components": [
{
"key": "direct_dependencies_free_of_known_advisories",
"name": "Direct dependencies free of known advisories",
"detail": "1 affected: golang.org/x/crypto v0.53.0 (unknown)",
"points": 26.6,
"status": "partial",
"details": [
{
"code": "advisories_affected",
"params": {
"count": 1,
"packages": "golang.org/x/crypto v0.53.0 (unknown)"
}
}
],
"max_points": 35
},
{
"key": "indirect_dependencies_free_of_known_advisories",
"name": "Indirect dependencies free of known advisories",
"detail": "transitive set not separable from development and test dependencies in this scope",
"points": 0,
"status": "excluded",
"details": [
{
"code": "advisories_scope_not_separable",
"params": {}
}
],
"max_points": 25
},
{
"key": "no_advisories_left_outstanding",
"name": "No advisories left outstanding",
"detail": "no advisory has been public longer than 90 days",
"points": 40,
"status": "met",
"details": [
{
"code": "advisories_none_stale",
"params": {
"days": 90
}
}
],
"max_points": 40
}
]
},
{
"key": "malicious_dependencies",
"band": "excellent",
"name": "Malicious dependencies",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"source": "osv",
"meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
"packages": [],
"red_flag": false,
"assessed_packages": 155,
"malicious_packages": 0,
"direct_malicious_packages": 0,
"withdrawn_malicious_packages": 0,
"installable_malicious_packages": 0
},
"components": [
{
"key": "no_dependency_reported_as_a_malicious_package",
"name": "No dependency reported as a malicious package",
"detail": "no dependency is reported as a malicious package",
"points": 100,
"status": "met",
"details": [
{
"code": "no_malicious_dependencies",
"params": {}
}
],
"max_points": 100
}
]
},
{
"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": 7
},
"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": "excellent",
"name": "AI Readiness",
"value": 89,
"weight": 0,
"metrics": [
{
"key": "ai_agent_context",
"band": "excellent",
"name": "Agent context & guidance",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"has_llms_txt": false,
"legible_history_share": 1,
"agent_instruction_files": [
"AGENTS.md",
"CLAUDE.md"
],
"agent_instruction_max_bytes": 15076
},
"components": [
{
"key": "agent_instructions",
"name": "Agent instructions",
"detail": "AGENTS.md, CLAUDE.md",
"points": 45,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "AGENTS.md, CLAUDE.md"
}
}
],
"max_points": 45
},
{
"key": "machine_readable_docs_llms_txt",
"name": "Machine-readable docs (llms.txt)",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "legible_commit_history",
"name": "Legible commit history",
"detail": "90 of 90 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 90,
"sampled": 90
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "excellent",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 98,
"inputs": {
"has_nix": true,
"has_tests": true,
"lockfiles": [
"go.sum",
"uv.lock"
],
"has_dockerfile": true,
"typed_language": true,
"bootstrap_files": [
"Makefile"
],
"has_devcontainer": false,
"has_linter_config": true,
"typecheck_configs": [],
"agent_commit_share": 0.24,
"toolchain_manifests": [
"go.mod"
],
"dependency_bot_commit_share": 0.1
},
"components": [
{
"key": "one_command_bootstrap",
"name": "One-command bootstrap",
"detail": "Makefile",
"points": 18,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Makefile"
}
}
],
"max_points": 18
},
{
"key": "automated_tests",
"name": "Automated tests",
"detail": null,
"points": 22,
"status": "met",
"details": [],
"max_points": 22
},
{
"key": "lint_format_config",
"name": "Lint / format config",
"detail": ".golangci.yml",
"points": 11,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": ".golangci.yml"
}
}
],
"max_points": 11
},
{
"key": "static_type_checking",
"name": "Static type checking",
"detail": "Go (statically typed)",
"points": 11,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Go"
}
}
],
"max_points": 11
},
{
"key": "reproducible_environment",
"name": "Reproducible environment",
"detail": "Dockerfile, Nix, lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "Dockerfile, Nix, lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "24 of the last 100 commits agent-authored or agent-credited",
"points": 10,
"status": "met",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 24,
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "10 of the last 100 commits are automated dependency updates",
"points": 8,
"status": "met",
"details": [
{
"code": "dependency_bot_commits",
"params": {
"count": 10,
"sampled": 100
}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "dependency not pinned by hash detected -- score normalized to 8",
"points": 8,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "ai_code_legibility",
"band": "excellent",
"name": "Code legibility for models",
"note": null,
"notes": [],
"value": 99,
"inputs": {
"primary_language": "Go",
"largest_source_bytes": 237397,
"source_files_sampled": 823,
"oversized_source_files": 20
},
"components": [
{
"key": "type_checkable_code",
"name": "Type-checkable code",
"detail": "Go (statically typed)",
"points": 45,
"status": "met",
"details": [
{
"code": "statically_typed_language",
"params": {
"language": "Go"
}
}
],
"max_points": 45
},
{
"key": "manageable_file_sizes",
"name": "Manageable file sizes",
"detail": "20/823 source files over 60KB",
"points": 53.7,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 823,
"oversized": 20
}
}
],
"max_points": 55
}
]
},
{
"key": "ai_interfaces",
"band": "moderate",
"name": "Machine-readable interfaces",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"example_dirs": [],
"has_mcp_signal": true,
"api_schema_files": [
"api/openapi.yaml",
"pkg/client/openapi.yaml"
]
},
"components": [
{
"key": "api_schema_openapi_graphql_proto",
"name": "API schema (OpenAPI/GraphQL/proto)",
"detail": "api/openapi.yaml, pkg/client/openapi.yaml",
"points": 40,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "api/openapi.yaml, pkg/client/openapi.yaml"
}
}
],
"max_points": 40
},
{
"key": "mcp_server",
"name": "MCP server",
"detail": null,
"points": 20,
"status": "met",
"details": [],
"max_points": 20
},
{
"key": "runnable_examples",
"name": "Runnable examples",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 40
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [],
"report_type": "repository",
"generated_at": "2026-07-22T05:05:37.675945Z",
"schema_version": "0.26.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/k/kenn-io/msgvault.svg",
"full_name": "kenn-io/msgvault",
"license_state": "standard",
"license_spdx": "MIT"
}