原始 JSON 报告 机器可读
{
"data": {
"repo": {
"topics": [
"cli",
"spotify",
"tui",
"bubbletea",
"charmbracelet",
"golang"
],
"is_fork": false,
"size_kb": 11571,
"has_wiki": false,
"homepage": null,
"languages": {
"Go": 3323478,
"Shell": 20639,
"Makefile": 5351,
"JavaScript": 1246,
"PowerShell": 10394
},
"pushed_at": "2026-07-20T04:18:36Z",
"created_at": "2026-03-22T20:56:01Z",
"owner_type": "Organization",
"updated_at": "2026-07-18T19:55:46Z",
"description": "A terminal client for Spotify",
"is_archived": false,
"is_disabled": false,
"license_spdx": "MIT",
"default_branch": "main",
"license_spdx_raw": "MIT",
"primary_language": "Go",
"significant_languages": [
"Go"
]
},
"owner": {
"blog": null,
"name": null,
"type": "Organization",
"login": "initgrep-apps",
"company": null,
"location": null,
"followers": 0,
"avatar_url": "https://avatars.githubusercontent.com/u/137073662?v=4",
"created_at": "2023-06-19T12:50:41Z",
"is_verified": null,
"public_repos": 4,
"account_age_days": 1129
},
"license": {
"state": "standard",
"spdx_id": "MIT",
"raw_spdx": "MIT",
"file_present": true,
"scorecard_found": true,
"profile_has_license": true
},
"activity": {
"releases": [
{
"tag": "v0.1.1",
"kind": "patch",
"published_at": "2026-07-17T11:28:11Z"
},
{
"tag": "v0.1.0",
"kind": "minor",
"published_at": "2026-07-16T17:55:08Z"
},
{
"tag": "v0.1.0-rc6",
"kind": "prerelease",
"published_at": "2026-07-16T16:59:54Z"
},
{
"tag": "v0.1.0-rc5",
"kind": "prerelease",
"published_at": "2026-07-02T13:06:21Z"
},
{
"tag": "v0.1.0-rc4",
"kind": "prerelease",
"published_at": "2026-05-20T22:32:08Z"
},
{
"tag": "v0.1.0-rc3",
"kind": "prerelease",
"published_at": "2026-05-08T13:12:49Z"
},
{
"tag": "v0.1.0-rc2",
"kind": "prerelease",
"published_at": "2026-05-07T11:33:36Z"
},
{
"tag": "v0.1.0-rc1",
"kind": "prerelease",
"published_at": "2026-05-01T23:02:42Z"
}
],
"recent_commits": [
{
"oid": "26a4b7ed7ee567ba4fa12118fda9e1c6714fc441",
"body": "…debase (#419)\n\nAudit docs/system/ against current codebase + git history. Rewrite all\n3 docs in caveman-tight style. Verified via parallel explore subagents\nwith file:line refs throughout.\n\narchitecture.md (928→923 lines):\n- Replace viewAuth with viewOnboarding + 3 sub-steps\n- Fix EventKind 13→12 c\n[…]\nprotocol block with helper signatures\n- Add LC_ALL/LC_CTYPE to Unicode Mode precondition\n- Update footer: 17→19 categories, 100+→130+ test cases\n\n3 files changed, 1856 insertions(+), 1524 deletions(-)",
"is_bot": false,
"headline": "docs(system): audit + sync architecture, design, sanity-tests with co…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-18T19:55:41Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "94e2b7c570861642ba547040e0f64bfe55464ffb",
"body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>\nCo-authored-by: Irshad sheikh <irshsheik@gmail.com>",
"is_bot": true,
"headline": "chore(main): release 0.1.1 (#417)",
"author_name": "github-actions[bot]",
"author_login": "github-actions[bot]",
"committed_at": "2026-07-17T11:27:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "007336df6beed4a59269558c3d0659e106ddfe3c",
"body": "…#418)\n\n* docs(spec): add story 276 to feature 11 — CI workflow GITHUB_TOKEN permissions\n\n* fix(ci): add explicit GITHUB_TOKEN permissions to resolve CodeQL alert\n\n* chore(docs): mark story 276 as done",
"is_bot": false,
"headline": "docs(spec): add story 276 — CI workflow least-privilege permissions (…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-17T11:24:41Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "15d99fc539ee17d9eb01b6ace3da2452f2e471be",
"body": "* fix(api): html-escape OAuth callback error parameter\n\n* docs(09-auth-and-profile): mark story 275 as done\n\n* fix(api): address PR review round 1 feedback on callback XSS\n\n- Set text/plain; charset=utf-8 Content-Type before WriteHeader on error branches\n\n- Add charset to success text/html Content-Type\n\n- Make XSS regression test table-driven with full body equality and metacharacter coverage\n\n- Assert result.Err != nil when draining callback channel in test",
"is_bot": false,
"headline": "fix(api): html-escape OAuth callback error parameter",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-17T09:37:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1b7bc77044ef19dc133ebbf66eec87b8cdc4eb56",
"body": "… response",
"is_bot": false,
"headline": "docs(spec): add story 275 — fix reflected XSS in OAuth callback error…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-17T09:29:18Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "098f7ab088f15b3f2e3e3f209075d932f1374191",
"body": "…y with 2 updates (#414)\n\n---\nupdated-dependencies:\n- dependency-name: actions/attest\n dependency-version: 4.2.0\n dependency-type: direct:production\n update-type: version-update:semver-minor\n dependency-group: actions-minor-patch\n- dependency-name: goreleaser/goreleaser-action\n dependency-versi\n[…]\nr-patch\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>\nCo-authored-by: Irshad sheikh <irshsheik@gmail.com>",
"is_bot": true,
"headline": "chore(ci)(deps): bump the actions-minor-patch group across 1 director…",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-07-17T09:20:48Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "90c26988de2bd1aba91c463a056923ee16024ae9",
"body": "Bumps [golang.org/x/net](https://github.com/golang/net) from 0.38.0 to 0.55.0.\n- [Commits](https://github.com/golang/net/compare/v0.38.0...v0.55.0)\n\n---\nupdated-dependencies:\n- dependency-name: golang.org/x/net\n dependency-version: 0.55.0\n dependency-type: indirect\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>\nCo-authored-by: Irshad sheikh <irshsheik@gmail.com>",
"is_bot": true,
"headline": "chore(deps)(deps): bump golang.org/x/net from 0.38.0 to 0.55.0 (#401)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-07-16T18:32:23Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "41035bada63857e5ba684a95814f472e4e033d40",
"body": "Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.3 to 7.0.0.\n- [Release notes](https://github.com/actions/checkout/releases)\n- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b43\n[…]\nirect:production\n update-type: version-update:semver-major\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(ci)(deps): bump actions/checkout from 6.0.3 to 7.0.0 (#364)",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-07-16T18:28:03Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6d63fa9746ef9a7b093f5bb33e3c4fc05fd90689",
"body": null,
"is_bot": false,
"headline": "chore(ci): enable release-please automation for v0.1.1+",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-16T17:53:39Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "abc22bf042f17f56492b9272c27780de29065ff6",
"body": null,
"is_bot": false,
"headline": "chore(release): add v0.1.0 stable changelog entry",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-16T17:50:44Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4fdb3e0b0d127a53c6534475f76bc19800f14dc4",
"body": "…er color (#411)\n\n* fix(theme): wire textinput styles in search overlay, fix overlay border color\n\n- Add TextStyle (TextPrimary) and Cursor.Style (Accent) to search\n overlay textinput, matching Filter and FormField conventions.\n Typed text and cursor now use theme tokens instead of terminal\n defa\n[…]\n TestSetTheme_UpdatesTextStyle and TestSetTheme_UpdatesCursorStyle\n tests following existing PlaceholderStyle/CompletionStyle pattern.\n\n- Fix overlay_chrome.go doc comment: Accent() → ActiveBorder().",
"is_bot": false,
"headline": "fix(theme): wire textinput styles in search overlay, fix overlay bord…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-16T16:29:39Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "32507ffb9e221a52330d77f936c06fc7757ba057",
"body": "* fix(gateway): resolve 8 review follow-ups from PR #409\n\n1. Remove dead lastDispatchedTick field from pollState\n2. Close resp.Body defensively on (resp, err) from transport\n3. Emit EventRequestBlocked on all ctx.Done cancellation paths\n4. Gate EventRequestAllowed to success; add EventRequestFailed \n[…]\nder switch\n- gateway_test: add tests for RequestFailed on 429 and RequestAllowed on 200\n- gateway_test: add test for setRate rejecting non-positive rates\n\nAddresses round-1 review findings on PR #410.",
"is_bot": false,
"headline": "fix(gateway): resolve 8 review follow-ups from PR #409 (#410)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-15T16:55:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "4bd793b94d2026b292396e3aef773761e2b6b631",
"body": "* docs(spec): add feature 22 — rate limit resilience & empty state context\n\n* feat(uikit): add EmptyStatus type, status-driven rendering, and PaneEmptyStatus helper\n\n- Add EmptyStatus enum (None, NeverFetched, Fetching, Error, RateLimited)\n- Add Status field to EmptyState; Render() derives text from\n[…]\nround-2 review follow-ups (observability, pre-existing leaks) to issues.md\n\n* chore(docs): restore round-2 review follow-ups after main merge\n\n* chore(docs): mark feature 22 done after story 273 merge",
"is_bot": false,
"headline": "feat(api-gateway): gateway proactive traffic shaping (#409)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-15T16:33:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "230ad5fd1e1f56bf677be86ca2deb5c9096e8cb3",
"body": "Rework story to address real root cause: default rate too high, no\nlong-idle pause, and reactive instead of proactive shaping.\n\nKey changes:\n- Lower default Background rate to 2 req/s, burst 5.\n- Replace consecutive-429 counter with last429Time + stepwise recovery.\n- Add CanAdmit pre-flight admissio\n[…]\nanAdmit.\n- Track lastSuccessTick for overdue calculation.\n- Add BackgroundRate/BurstCapacity/Last429AgoSecs to snapshot.\n\nLock ordering, deterministic preset iteration, and golden-file\ncoverage noted.",
"is_bot": false,
"headline": "docs(spec): revise F22-S273 gateway traffic shaping spec (#408)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-08T11:06:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "55fa240dd1ed896c9d6b91f5d0b083ed1b6bf93f",
"body": "…and follow-up fixes (#407)\n\n* chore(docs): add story 274 empty-state follow-ups spec\n\n* fix(uikit): add Category field to EmptyState, PaneFetchState struct, and follow-up fixes\n\n- Add Category field to EmptyState; Render() uses it instead of TrimPrefix\n- Add PaneFetchState struct; PaneEmptyStatus u\n[…]\ntyState_StatusError_EmptyCategory and TestEmptyState_StatusFetching_EmptyCategory\n- Fix PaneEmptyStatus Text field to match actual rendered text for all statuses\n\n* chore(docs): mark story 274 as done",
"is_bot": false,
"headline": "fix(uikit): add Category field to EmptyState, PaneFetchState struct, …",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-07T16:30:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "335d881312d0f5f47396cf54ca270b60b98e9fca",
"body": "* docs(spec): add feature 22 — rate limit resilience & empty state context\n\n* feat(uikit): add EmptyStatus type, status-driven rendering, and PaneEmptyStatus helper\n\n- Add EmptyStatus enum (None, NeverFetched, Fetching, Error, RateLimited)\n- Add Status field to EmptyState; Render() derives text from\n[…]\nerFetched. Add\nTestPaneEmptyStatus_ErrorOverridesNeverFetched. Remove FetchedAt stamps\nfrom 5 pane error tests so they test the real first-fetch-failed scenario.\n\n* chore(docs): mark story 272 as done",
"is_bot": false,
"headline": "feat(panes): context-aware empty states for all 8 table panes (#406)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-06T21:05:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2a6698dd135ae2eb34e62773fbb685e60959b246",
"body": "…ext (#405)",
"is_bot": false,
"headline": "docs(spec): add feature 22 — rate limit resilience & empty state cont…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-06T15:47:32Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ce663f17efaebfddeed541f75972fab0884d3cfc",
"body": "…s fix, pagination improvements (#404)\n\n- Tab switch now clears stale results and shows loading spinner, then fires\n new API call with correct type filter instead of re-filtering old results\n- Tab switch with empty query no longer shows stuck loading spinner\n- List cursor resets to 0 after SetItems\n[…]\npagination bar (spinner frame only,\n no text, left of brackets)\n- Added generation counter (gen) to staleness check — prevents stale\n responses from previous tab from overwriting current tab's total",
"is_bot": false,
"headline": "fix(search): tab switch triggers new API call, cursor reset, follower…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-06T14:41:16Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e578fa7c328e07962e8d6787df17f710a2fe6d39",
"body": "…(#400)\n\nThe fix was a glue-code guess without understanding the root cause.\nQueue still empties on pause, and play still fails with toast.",
"is_bot": false,
"headline": "revert(playback): revert device selection and queue pause fix (#399) …",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-03T09:38:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ea8f17431556898fe882a5d971c108c9a21f66af",
"body": "Bug 1: Device lost on resume after pause. buildPlaybackAPICmd sent\nempty PlayOptions{} on play — Spotify forgot device after idle pause,\nreturning 404. Fix: add DeviceID field to PlayOptions, populate from\nActiveDevice() in play command.\n\nBug 2: Queue cleared on pause. fetchQueueCmd returned QueueLoadedMsg{}\n(nil Items) on 204 — handler called SetQueue(nil), wiping queue. Fix:\nguard SetQueue with nil check on Items.",
"is_bot": false,
"headline": "fix(playback): preserve device selection and queue on pause (#399)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-03T08:44:59Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "79d1722f597f72aa577c693ef14f9bb7f347c9fc",
"body": null,
"is_bot": false,
"headline": "chore(release): add CHANGELOG entries for v0.1.0-rc5 (#398)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-02T13:04:12Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7a93e22c25b077deb17d3b36e8088dc519633c87",
"body": "…-down names (#397)\n\nThree changes:\n1. Now-playing border: remove episode info (⏵ Podcast notch, compact-mode\n details). Episode details belong in content area + 'i' overlay, not border.\n2. Drill-down panes (playlists, albums, followed shows): truncate selected\n item name to 20 runes, remove '(N\n[…]\nt suffix. Long names\n were pushing filter/action hints out of the border.\n3. Remove 'i details' action from now-playing border — handled at app level.\n4. Export TruncateRunes() from uikit for reuse.",
"is_bot": false,
"headline": "fix(ui): clean up border titles — remove episode info, truncate drill…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-02T12:27:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1e8f78c7cae38ad637a614e3f11f07fde5b2433c",
"body": "Two bugs fixed:\n\n1. Token expiry after idle: StaticTokenProvider never checked expiry.\n After ~1h idle, token expired, next API call got 401, toast appeared.\n Fix: RefreshableTokenProvider checks expiry on every AccessToken()\n call, proactively refreshes within 5min threshold. Mutex prevents\n \n[…]\n Spotify returns 404 on PUT /me/player/play when no active device.\n Fix: NotFoundError type + error mapper priority 5 with clear message:\n 'No active device. Open Spotify or select a device (d).'",
"is_bot": false,
"headline": "fix(auth): proactive token refresh + clear 404 device error (#396)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-02T10:10:35Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "555da14627e4f2ba772c4b8ff31fe55c634ed6fa",
"body": "* revert(search): remove like functionality from search overlay\n\n* chore: gofmt search.go\n\n* chore: remove unused handleToggleLike",
"is_bot": false,
"headline": "revert(search): remove like functionality from search overlay (#395)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-02T07:15:43Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8bad9204d7cf45d9a466db684a63448338f014db",
"body": "…verlay store (#394)",
"is_bot": false,
"headline": "fix(library): improve like/unlike toast messages and re-wire search o…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-01T19:08:15Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5d73edd9832b22c5426bfce54e9ba89674e002ed",
"body": "* fix(api): switch LikeTrack/UnlikeTrack to /v1/me/library endpoint\n\nReplace deprecated PUT/DELETE /v1/me/tracks with JSON body with\nPUT/DELETE /v1/me/library?uris=spotify:track:<id> (no body).\n\n- Remove bytes, encoding/json imports (no longer needed)\n- Add net/url import for url.QueryEscape\n- Update library_test.go: verify /me/library path, query param, no body, no Content-Type\n- Update like_commands_test.go: verify new endpoint format\n\n* chore(docs): mark story 271 as done, feature 05 complete",
"is_bot": false,
"headline": "fix(api): switch LikeTrack/UnlikeTrack to /v1/me/library endpoint (#393)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-01T18:49:14Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4630a4e3250b597e97cf50e532130d1e8f8a79ee",
"body": "…ch overlay (#392)",
"is_bot": false,
"headline": "docs(spec): add story 271 to feature 05 — fix library endpoint + sear…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-01T18:40:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7f669e0335025c8db787827e986ff26313c802c6",
"body": "* fix(panes): restrict 'l like' border hint to focused pane only\n\nBug 1: Remove 'l' key handler from NowPlayingPane — it's a playback\ncontrol pane, not a track list pane. Remove 'l like' from Actions().\n\nBug 2: Add IsFocused() guard to Actions() in all 6 track-list panes\n(LikedSongs, Queue, TopTrack\n[…]\nfocused, only base actions shown — 'l like'\nis a focus-only action. SearchOverlay always focused when visible,\nno change needed.\n\nStory 270.\n\n* chore(docs): mark story 270 as done, feature 05 complete",
"is_bot": false,
"headline": "fix(panes): restrict 'l like' border hint to focused pane only (#391)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-07-01T17:51:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d98f6202874440c323db3f55962f9ff784a72101",
"body": "… (#390)",
"is_bot": false,
"headline": "docs(spec): add story 270 to feature 05 — fix like focus + nowplaying…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-30T22:05:57Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a4a125b07cce68ff29e166e02f74bdaf1f8e81bb",
"body": "…toast (#389)\n\n* fix(library): revert heart prefix, add l like border action, fix 403 toast\n\nStory 269 — three UX fixes for the like/unlike feature shipped in stories 267/268:\n\nBug 1: Revert the ♥ prefix from track names in all 8 track-displaying panes\n(nowplaying, likedsongs, queue, toptracks, rece\n[…]\nks operation\nwith title 'Like track failed' and forbidden body 'Premium required to like\ntracks.', and switch the routing handler to use it.\n\n* chore(docs): mark story 269 as done, feature 05 complete",
"is_bot": false,
"headline": "fix(library): revert heart prefix, add l like border action, fix 403 …",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-30T21:42:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e6cc1b05e1583a5c6ecd9d6fb30191fcd06c0975",
"body": null,
"is_bot": false,
"headline": "docs(spec): add story 269 to feature 05 — fix like/unlike UX (#388)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-30T21:05:55Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1a2abc43529ea1fe9a007f5eb28d210672bc613d",
"body": "* chore(graph): commit knowledge graph for team map\n\n- graph.json: 6,242 nodes, 15,292 edges (AST + semantic)\n- manifest.json: portable relative-path file index\n- GRAPH_REPORT.md: god nodes, surprising connections, questions\n- graph.html: interactive community view (344 communities)\n- .gitignore: ex\n[…]\n on commit (free, no API)\n- merge driver: union-merge graph.json, no conflict markers\n- opencode plugin: graphify is default search tool, grep fallback\n- .gitignore: exclude cost.json, cache/ optional",
"is_bot": false,
"headline": "feat(graph): graphify knowledge graph + team workflow setup (#387)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-30T20:30:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "44c70bcc075bf140fc2ba5c695f6ef2ba3b68062",
"body": "* feat(queue): like/unlike keybinding + heart indicator (story 268)\n\n* feat(toptracks): like/unlike keybinding + heart indicator (story 268)\n\n* feat(recentlyplayed): like/unlike keybinding + heart indicator (story 268)\n\n* feat(playlists): like/unlike in track sub-view + heart indicator (story 268)\n\n\n[…]\neLikeRequestMsg.Track.Artists is non-empty with correct names and\nAlbum.Name is carried through.\n\nAddresses PR #385 review round 1 feedback.\n\n* chore(docs): mark story 268 as done, feature 05 complete",
"is_bot": false,
"headline": "feat(library): like/unlike tracks across all panes (story 268) (#385)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-29T00:31:23Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "283c91cdda41851e4b9319f78e71499cf51513d1",
"body": "* feat(state): add IsTrackLiked, AddLikedTrack, RemoveLikedTrack for like/unlike toggle\n\nStory 267 Task 1 & 2: Store infrastructure for O(1) liked-status lookup\nand optimistic insert/remove.\n\n- Add likedSet map[string]bool field to Store, initialized in New()\n- SetLikedTracks rebuilds likedSet from \n[…]\nthe 429 test.\n- Add 429 single-toast assertion (exactly zero routing-level ratelimit\n toasts; global handler owns it). Expose UnauthorizedMsgForTest type alias.\n\n* chore(docs): mark story 267 as done",
"is_bot": false,
"headline": "feat(library): like/unlike tracks core infrastructure (story 267) (#384)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-28T21:04:49Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "51be351489e21701f3224bb85a977ac971e50109",
"body": "…ture (#383)",
"is_bot": false,
"headline": "docs(spec): add story 267 to feature 05 — like/unlike core infrastruc…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-28T19:39:48Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4476aeaca2af0d7314418b0de4f348293a2a9ba3",
"body": "…o-small screens (#382)\n\n* test(app,panes): add golden snapshots for onboarding, splash, and too-small screens\n\n- Splash: 2 golden snapshots (default 120x40, narrow 40x10)\n- Registration: 3 golden snapshots (empty, with input, validation error)\n- OAuth: 2 golden snapshots (spinner running, permissio\n[…]\nssions overlay on stepError\n- Add 'v' key routing for permissions overlay on stepError screen\n- 13 golden files committed to testdata/ directories\n\n* chore(docs): mark story 266 and feature 21 as done",
"is_bot": false,
"headline": "feat(test-infra): add golden snapshots for onboarding, splash, and to…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T10:26:04Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0a048cb8f22b1282e27084d1d03d0613f435e7e0",
"body": "* docs(ci): add golden test protocol, ASCII target, and cross-references\n\n- Add test-golden-ascii target to Makefile for ASCII glyph mode golden files\n- Document golden file protocol in AGENTS.md (Reading Order, Testing Rules, Never Do, Quick Commands)\n- Add golden test cross-references to sanity-tests.md (section 18)\n- Regenerate golden files: go test ./internal/ui/panes/ -update\n\n* chore(docs): mark story 265 as done",
"is_bot": false,
"headline": "feat(test-infra): CI enforcement + golden test docs (#381)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T10:19:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "374649af8a112b1919dd9e8ba74d1c8fbb2780b8",
"body": "* feat(app,panes): export test accessors for overlays, queue, preset, page\n\nStory 264: add exported accessors used by the cross-cutting integration\ntests so they can inspect pane/overlay state through the App model\nwithout reaching into unexported fields.\n\n- App: DevicePane, ThemeOverlay, HelpOverla\n[…]\n API mocks (no mock libs) per\nAGENTS.md. activateAlertCmd drives batched toast commands without\nticking the alert into auto-dismissal or blocking on real timers.\n\n* chore(docs): mark story 264 as done",
"is_bot": false,
"headline": "test(app): cross-cutting integration flows (story 264) (#380)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T10:13:32Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "9b460cb2f93d0add54ff6a99f711fa3abbc3dad5",
"body": "* test(panes): add DevTools golden snapshots for story 263\n\n* chore(docs): mark story 263 as done\n\n* fix: gofmt golden test files",
"is_bot": false,
"headline": "test(panes): add DevTools golden snapshots for story 263 (#379)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T08:19:31Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3cf0d419ae757595674815e9f7198ecf75b54388",
"body": "…overlays (#378)\n\n* test(panes): add golden snapshots for Theme, Help, Profile, Devices overlays\n\n- ThemeOverlay: 2 snapshots (theme list 80x24, narrow 40x24)\n- HelpOverlay: 2 snapshots (keybindings 80x24, narrow 40x24)\n- ProfileOverlay: 6 snapshots (premium, free, loading, error, logout confirm, forget confirm)\n- DevicesPane: 3 snapshots (3 devices, empty, narrow 40x24)\n- 13 golden files in testdata/\n- make ci passes, 87.8% coverage\n\n* chore(docs): mark story 262 as done",
"is_bot": false,
"headline": "feat(test-infra): golden snapshots for Theme, Help, Profile, Devices …",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T08:07:31Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "7c4720fdad24b293a44018d9000a0c90baff82ed",
"body": "…ory 261) (#377)\n\n* test(panes): add FollowedShowsPane golden snapshots\n\n5 golden snapshots at 80x24 and 40x24: shows, empty state,\nepisode sub-view (drill-down), narrow, and filter active.\n\n* test(panes): add SavedEpisodesPane golden snapshots\n\n4 golden snapshots at 80x24 and 40x24: episodes, empty\n[…]\npp,\nFollowedShowsPane drill-down (Enter/Esc), and Enter-plays-episode\nfor both SavedEpisodes and FollowedShows episode sub-view.\n\n* style: gofmt formatting fixes\n\n* chore(docs): mark story 261 as done",
"is_bot": false,
"headline": "test(panes,app): add podcast component golden + integration tests (St…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T07:57:40Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d100af3a86041e01ecfbe0b76bc7466fedafb77c",
"body": "…0) (#376)\n\n* test(search): add 7 golden snapshots for search overlay\n\n- Idle, WithQuery, WithResults, PrefixLocked, Page2,\n NoResults, Narrow (40x24)\n- 80x24 terminal dimensions for main snapshots\n- Use goldentest.NewPaneTest + WaitAndReadOutput\n\n* test(search): add integration flow tests for sear\n[…]\nI types filtering\n- Ctrl+A AddToQueue, Tab/Shift+Tab tab cycling\n- Stale request cancellation (context.Canceled)\n- Ctrl+U no-op (clearing handled via Esc+reopen)\n\n* chore(docs): mark story 260 as done",
"is_bot": false,
"headline": "test(search): add search overlay golden + integration tests (Story 26…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T07:33:50Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "39df55f83af65fe36a0a5f5d5cc4ec3c57d966bc",
"body": "…egration (#375)\n\n* test(nowplaying): add golden snapshots for NowPlayingPane\n\nTasks 1-5: 12 golden snapshots covering:\n- Track mode: playing, paused, empty state (80x24)\n- Episode mode: playing, paused (80x24)\n- Adaptive layout: compact strip (<8 height), narrow (40 cols), wide (120 cols)\n- Seek ba\n[…]\nITICAL)\n- Add require.NotNil(msg) after cmd() call in assertPlaybackRequestMsg (MEDIUM)\n- Remove redundant require.NotNil and dead _=req in PauseThenResume (LOW)\n\n* chore(docs): mark story 259 as done",
"is_bot": false,
"headline": "test(nowplaying): add NowPlaying golden snapshots + playback flow int…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T07:07:08Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "651ffbcd65ee6ca74c3089c97896715e3fc65c81",
"body": "…8) (#374)\n\n* test(panes): add TopTracksPane golden snapshots (6 scenarios)\n\n- tracks loaded at 80x24, short_term\n- empty state\n- medium_term time range label\n- narrow 40x24 with column hiding\n- filter active with matching results\n- filter active with no matches\n\n* test(panes): add TopArtistsPane go\n[…]\nort_term, updating View()\n- TestStatsEnterPlaysContextOrTrackList: verifies Enter on TopTracks\n emits PlayTrackListMsg, Enter on TopArtists emits PlayContextMsg\n\n* chore(docs): mark story 258 as done",
"is_bot": false,
"headline": "test(panes): add Stats component golden + integration tests (Story 25…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T06:44:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ac4f6212a77137576e6a1ab0b3aff0a21882a6ff",
"body": "…#373)\n\n* test(panes): add Library component golden tests + integration flows\n\n- PlaylistsPane: 7 golden snapshots (list, empty, track sub-view,\n track sub-view filter, spotify-owned locked, narrow, filter active)\n- AlbumsPane: 6 golden snapshots (list, empty, track sub-view,\n track sub-view filte\n[…]\nentinel on Esc (leave track view) so user can press\n x again after switching playlists.\n- Update test to expect PlaylistRemoveResultMsg with api.RateLimitError.\n\n* chore(docs): mark story 257 as done",
"is_bot": false,
"headline": "test(panes): add Library component golden tests + integration flows (…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-26T06:32:20Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "aa60573f051226842f2c7bc579375c9c5a018c26",
"body": "…QueuePane golden tests (#372)\n\n* feat(goldentest): add teatest dependency and golden file helper package\n\n- Add github.com/charmbracelet/x/exp/teatest dependency\n- Create internal/goldentest/golden.go with NewPaneTest, AssertGolden, ReadOutput\n- AssertGolden supports -update flag for golden file re\n[…]\nion denied, I/O errors)\n- ReadOutput: return (string, error) instead of discarding io.ReadAll error\n- WaitAndReadOutput: propagate ReadOutput error with t.Fatalf\n\n* chore(docs): mark story 256 as done",
"is_bot": false,
"headline": "feat(golden): add teatest dependency, goldentest helper package, and …",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-25T23:31:15Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "83dabaf3883ec24ddd92d0cac90d636f079a07ca",
"body": "* docs(spec): consolidate features — 20 → 16\n\nMerge absorbed features into parent domains:\n- 16 (mono themes, 2 stories) → 08 (theming)\n- 14 (page B redesign, 12 stories) → 10 (developer tools)\n- 19 (player unification, 11 stories) → 18 (podcasts)\n- 15 (error resilience, 7 stories) → 02 (API infrast\n[…]\nnown/ad_type NowPlaying (259),\n stale search cancellation + Ctrl+U (260), ASCII golden protocol (265)\nLOW: Esc scroll-to-top (264)\n\n333 insertions across 12 files. 11 stories expanded, 1 new created.",
"is_bot": false,
"headline": "docs(spec): add feature 21 — End-to-End Test Infrastructure",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-25T22:40:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "57f78e5f8b434db03cb1c998be89d1bd68ea4719",
"body": "Merge absorbed features into parent domains:\n- 16 (mono themes) → 08 (theming)\n- 14 (page B redesign) → 10 (developer tools)\n- 19 (player unification) → 18 (podcasts)\n- 15 (error resilience) → 02 (API infrastructure)",
"is_bot": false,
"headline": "docs(spec): consolidate features — 20 → 16 (#370)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-25T21:45:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "bcfecf94f258c666ee1cf154010a4085ff78571a",
"body": "…ch (#369)\n\nemptyBorder with empty chars causes bubble-table generateMultiStyles\nto create first-column header styles without top/bottom borders (height=1)\nwhile other columns get explicit .BorderTop(true)/.BorderBottom(true)\n(height=3). JoinHorizontal staggers mismatched-height columns onto\nseparat\n[…]\nll emptyBorder fields. Space chars are\ninvisible but auto-enable all borders via BorderStyle, giving every\ncell identical height.\n\nAlso remove unused TableChrome wrapper (0 callers, 33+29 dead lines).",
"is_bot": false,
"headline": "fix(ui): fix table column misalignment from emptyBorder height mismat…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-25T21:28:42Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6a3dca5d80fe7439b3933d9d3c752fd5c848b099",
"body": "… pagination (#368)",
"is_bot": false,
"headline": "fix(ui): remove WithMinimumHeight — causes blank row between data and…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-24T20:29:09Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "9333da93e34a74e3f04c4f83404e9d1dde9f097c",
"body": "…ter always fits (#367)",
"is_bot": false,
"headline": "fix(ui): fix pageSize overflow — revert to height-6 so pagination foo…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-24T18:54:06Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "75ae3040266b52050d7c24865096412bfc95409d",
"body": "* fix(ui): fix pagination footer positioning with WithMinimumHeight\n\n* chore(docs): mark story 255 as done — feature 20 complete",
"is_bot": false,
"headline": "chore(docs): mark story 255 as done — feature 20 complete",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-24T17:47:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "58f3318cb947112b780e11bb1d0a33562be77e26",
"body": "…ght (#365)",
"is_bot": false,
"headline": "docs(spec): add story 255 — fix pagination footer with WithMinimumHei…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-24T17:33:46Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a94f373e4d22272173a8471c8cc1f7a312cbe482",
"body": "* refactor(ui): tune flex factors to give primary columns more width\n\n* chore(docs): mark story 254 as done — feature 20 complete",
"is_bot": false,
"headline": "refactor(ui): tune flex factors for primary column dominance (#363)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-19T21:38:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "ab9d0c2a49c5ad6e0bd9b44c5fb40b695e01e059",
"body": "…(#362)\n\n* fix(ui): revert # column removal — restore index column to all panes\n\n* chore(docs): mark story 253 as done",
"is_bot": false,
"headline": "fix(ui): revert # column removal — restore index column to all panes …",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-19T21:33:00Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "1968f5964f13e7897b0ae9e2740a1421ff43aa80",
"body": "…, tune flex (#361)",
"is_bot": false,
"headline": "docs(spec): add fix stories 253, 254 for feature 20 — revert # column…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-19T21:18:35Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0351a6e624950aa8df04ff122c533106d91116f0",
"body": "…e (#360)\n\n* docs: update design.md and tui.md for pane content design language\n\n- Remove # column from all pane column tables in design.md §9\n- Add Column Ordering rule, Priority Thresholds, Header Guidelines to §9\n- Add no-blank-rows and EmptyState consistency rules to §6\n- Remove all PlayingIndex\n[…]\n4\n- Add Responsive Columns section (§3.4a) documenting priority-based column hiding\n- Remove ▶ playing row references from TableChrome spec\n\n* chore(docs): mark story 252 as done — feature 20 complete",
"is_bot": false,
"headline": "docs(20): update design.md and tui.md for pane content design languag…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T22:19:21Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6e30f120ac36adc153018a886bdd0b5d4fc12559",
"body": null,
"is_bot": false,
"headline": "feat(ui): add consistent empty states to all panes (#359)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T22:12:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8ce1fcd804aaec22cfba874c61bc05fb83dcb3d4",
"body": "* refactor(ui): shorten column headers for space efficiency\n\nDuration → Dur, Popularity → Pop, Publisher → Pub\nUpdated tests to match new header strings\n\n* chore(docs): mark story 250 as done",
"is_bot": false,
"headline": "feat(pane-content): optimize column headers for space efficiency",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T22:07:12Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "a5193cbd912ba12d7dfc87c77fb6252f0194dc09",
"body": "* feat(ui): add priority-based responsive column hiding\n\n* fix(ui): add default case for unknown priorities, add 5 boundary/fallback/compat tests (story 249-review-fix)\n\n- Add default case to filterColumnsByPriority switch: Priority >3 treated as always-visible\n- Add TestTable_PriorityFiltering_Zero\n[…]\ntering_ViewExcludesHiddenHeaders (View() output at narrow width)\n- Add TestTable_PriorityFiltering_DefaultCaseUnknownPriorityVisible (Priority 4+ always-visible)\n\n* chore(docs): mark story 249 as done",
"is_bot": false,
"headline": "feat(ui): add priority-based responsive column hiding (#357)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T21:59:57Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0fe5de23c153c4f6bafa4b735babb5880d803fac",
"body": "…ueue (#356)\n\n* fix(ui): move icon columns to first position, drop trailing icon column from queue, drop saved column from episodes\n\n* chore(docs): mark story 248 as done",
"is_bot": false,
"headline": "fix(ui): fix icon column positions in SavedEpisodes, FollowedShows, Q…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T21:40:53Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f491ca3630d1a784bd34c96e2033c9afaf21d8fd",
"body": "* refactor(ui): remove # column from all table panes\n\nRemove {Key: \"index\", Header: \"#\", FlexFactor: 1, Color: th.ColumnIndex()}\nfrom column definitions and \"index\": fmt.Sprintf(\"%d\", i+1) from row data\nin all 9 table panes (queue, likedsongs, recentlyplayed, toptracks,\ntopartists, playlists, albums\n[…]\ngo fixtures.\n\nNetworkLogPane and GatewayLivePane already correct (no index column).\n\nStory: 247\n\n* fix(panes): update stale comments referencing removed # column\n\n* chore(docs): mark story 247 as done",
"is_bot": false,
"headline": "feat(ui): remove # column from all table panes (story 247) (#355)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T21:32:46Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b8e4b4febbd76b984712bdc11ec796455d0558b2",
"body": "…354)\n\n* fix(ui): fix table page size calc and add width threshold crossing\n\n* chore(docs): mark story 246 as done",
"is_bot": false,
"headline": "fix(ui): fix table page size calc and add width threshold crossing (#…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T21:02:49Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4f95141f0bdb536d703a726cd25a7ea23d94bb9c",
"body": "* refactor(ui): remove PlayingIndex dead code from table and panes\n\n* test(queue): remove misleading PlayingIndicator tests after PlayingIndex removal\n\nDelete TestQueuePane_Table_PlayingIndicator and\nTestQueuePane_PlayingIndicatorPersists — both became\nredundant with no unique coverage after removing\nSetPlayingIndex/PlayingIndex from the queue pane.\n\n* chore(docs): mark story 245 as done",
"is_bot": false,
"headline": "refactor(ui): remove PlayingIndex dead code from table and panes (#353)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T20:52:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "3023af0afaf031a4d75b74697d4bac1a592443d0",
"body": "…5-252) (#352)",
"is_bot": false,
"headline": "docs(spec): add feature 20 — Pane Content Design Language (stories 24…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T20:38:19Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f02edafd04b403ad1dacae65f143113cfc1aef74",
"body": "* docs(system): add future features analysis with active API audit\n\n- Cross-reference all Spotify Web API endpoints against OpenAPI schema v1.0.0\n- Identify 48 active vs 48 deprecated endpoints\n- Categorize 26 viable features into 3 effort tiers\n- Document 18 blocked-by-deprecation features\n- Flag migration needed from deprecated /me/tracks to /me/library\n\n* docs(system): remove deprecated API sections, focus on active endpoints only",
"is_bot": false,
"headline": "docs(system): add future features analysis with active API audit (#351)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-18T15:46:34Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "85f4075e5f6ede50d7a678503a5629ea2624e2f1",
"body": "…n borders (#350)\n\n- Remove 12 per-pane PaneBorder*() tokens from Theme interface and all 13 TOMLs\n- Rewrite PaneBorderColor() to be focus-driven (ActiveBorder vs InactiveBorder)\n- Remove Faint() usage — colour controlled by theme tokens directly\n- Remove Bold from focused pane titles — focus convey\n[…]\n)\n- Tighten action notch spacing: ╮ f filter ╭ → ╮f filter╭\n- Remove dead Top/Bottom rows from table emptyBorder — saves 2 lines per pane\n- Status bar border uses InactiveBorder() token (always muted)",
"is_bot": false,
"headline": "feat(theme): transition to state-driven semantic colour model, tighte…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-17T22:25:09Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "6703d1fad1f928c576913c1549f000b5aeead5ab",
"body": "…eybar, right-align scroll percent (#349)\n\n* Revert \"fix(episode-details): use viewport width for markdown wrapping (#347)\"\n\nThis reverts commit 1199ef1d4dc3b120cabba16739e22b6f903574c0.\n\n* fix(episode-details): fix text wrapping truncation, remove Esc from keybar, right-align scroll percent\n\n- Matc\n[…]\nipsis\n- Remove Esc hint from keybar (Esc is global, documented in help overlay)\n- Right-align scroll percentage on keybar bottom-right corner\n- Add wrapText helper for fallback plain text descriptions",
"is_bot": false,
"headline": "fix(episode-details): fix text wrapping truncation, remove Esc from k…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-17T21:05:00Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "1199ef1d4dc3b120cabba16739e22b6f903574c0",
"body": "renderMarkdown was called with overlayWidth()-6 (old manual scroll padding\noffset). This produced markdown lines slightly wider than the viewport's\ncontent area, causing the viewport to render '…' overflow indicators on\nthe right side which distorted the overlay border.\n\nFix: pass viewport.Width directly so markdown wraps at the exact viewport\ncontent width, eliminating overflow indicators.",
"is_bot": false,
"headline": "fix(episode-details): use viewport width for markdown wrapping (#347)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-17T20:05:24Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5ed2f28e8432b59b92016de99ba80f14581e5bd8",
"body": "* feat(episode-details): replace manual scroll with viewport.Model\n\n- Add viewport.Model field, remove scrollY/maxScroll/clampScroll\n- SetSize initializes/resizes viewport dimensions\n- View() composes header + viewport.View() + keybar with scroll percent\n- Update() intercepts Esc/q/Home/End, delegat\n[…]\ne 3)\n- Add tiny terminal test (3x10) covering clamp branches (Issue 4)\n- Adjust viewport height to account for lipgloss padding overhead (Issue 5)\n\n* chore(docs): mark story 244 and feature 19 as done",
"is_bot": false,
"headline": "feat(episode-details): replace manual scroll with viewport.Model (#346)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-17T19:52:57Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "d6365e097e48ecb9a57179076de5492e6c5849dc",
"body": "…to feature 19 (#345)\n\nReplace manual scroll implementation with bubbles/viewport component.\nRemoves scrollY/maxScroll/clampScroll dead zones, adds pgup/pgdn/\nhome/end/mouse wheel support. Feature 19 reopened.",
"is_bot": false,
"headline": "docs(spec): add story 244 — viewport-based Episode Details scrolling …",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-17T19:33:33Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "60c73c85427142fab489c1e7ac6c62228b802bb9",
"body": "… (#344)\n\n* docs(spec): add feature 19 — Player Page Unification with stories 233–243\n\n* docs(spec): add Tasks sections to feature 19 stories, add story template\n\n- All 9 stories (233-236, 238-243) now have ## Tasks sections with\n specific test function names per task\n- Created docs/spec/TEMPLATE-s\n[…]\ne.Actions. Episode mode now passes {Key: i, Label: details}\nto renderEpisodeSideBySide -> infoBox.Render -> PaneChrome. Track mode\ndoes not pass actions, so its 'Track Info' InfoBox remains unchanged.",
"is_bot": false,
"headline": "fix(nowplaying): add [i:details] notch to Episode Info InfoBox border…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-17T14:51:36Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "55d6da8a454af267687fa18202ed18a512bd6bdc",
"body": "…pisodeCmd (#343)\n\n* docs(spec): add feature 19 — Player Page Unification with stories 233–243\n\n* docs(spec): add Tasks sections to feature 19 stories, add story template\n\n- All 9 stories (233-236, 238-243) now have ## Tasks sections with\n specific test function names per task\n- Created docs/spec/T\n[…]\n the starting episode within the show\ncontext. The prior fix added Offset but incorrectly removed the\nURIs = nil line, causing all episode plays from drill-down to fail\nwith 'playback command failed'.",
"is_bot": false,
"headline": "fix(playback): restore opts.URIs = nil alongside Offset in buildPlayE…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-17T14:11:26Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "c7ccd35e8ad08ab3edf7c85a95cf2b2bc34dffd9",
"body": "* fix(app): episode play from drill-down keeps URIs and sets Offset\n\nWhen playlistURI is non-empty, buildPlayEpisodeCmd was discarding the\nepisode-specific URIs by setting opts.URIs = nil. Spotify Play API with\nonly context_uri set plays from the show's default starting position,\nignoring which epis\n[…]\n Queue first.\nSwap cell order in both podcast presets so Queue is the first\ncell in the second row, consistent with the Listening preset.\n\nUpdated tests to verify Queue is now Cell[0] in both presets.",
"is_bot": false,
"headline": "fix(19): episode play offset and queue layout order (#342)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-17T13:51:13Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2115e11060925bf42c88adf0bd5d91e75650005a",
"body": "* docs(architecture): update for player-page-unification feature\n\n- Replace 3-page model with 2-page (Player/Stats) in architecture.md\n- Add Visibility-Gated Polling subsection with rules and table\n- Update pane list: NowPlaying content-aware, FollowedShows drill-down,\n PodcastPlayback/ShowEpisodes\n[…]\n to NowPlaying\n- §2: Change Stats page NowPlaying toggle key from 1 to — (always\n visible, non-toggleable) to resolve contradiction with §4 prose\n\n* chore(docs): mark story 243 and feature 19 as done",
"is_bot": false,
"headline": "docs(architecture): update for player-page-unification feature (#341)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-15T22:09:57Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "e17ec0aea69f187e409eaa5efa06b7259fe61a0e",
"body": "…340)\n\n* feat(keybinding): update for 2-page Player/Stats model (story 242)\n\n- 0 key: Cycle Player / Stats (was Music / Podcasts / Stats)\n- p key: Cycle preset on Player page\n- i key: conditional display when playing episode\n- Remove Podcasts page toggle keys from all 3 locations\n- Update toggle key descriptions for contextual behavior\n\nThree-location update per AGENTS.md rule #17:\nREADME.md, docs/system/design.md, help_overlay.go\n\n* chore(docs): mark story 242 as done",
"is_bot": false,
"headline": "feat(keybinding): update for 2-page Player/Stats model (story 242) (#…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-15T21:58:27Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "8f27e59bb0ddcbae9b950390142e963341a38490",
"body": "…rchResultSelectedMsg (#339)\n\n* feat(search): replace TogglePage cycling with autoSwitchPreset in SearchResultSelectedMsg\n\nReplace manual preset switching and TogglePage() cycling in the\nSearchResultSelectedMsg handler with autoSwitchPreset() calls.\n\n- Show/episode selection: autoSwitchPreset(\"episo\n[…]\nD before dispatching the fetch cmd.\nAdded TestSearchResultSelectedMsg_Show_SetsShowEpisodesID verifying\nthe staleness key is set and responses are not discarded.\n\n* chore(docs): mark story 241 as done",
"is_bot": false,
"headline": "feat(search): replace TogglePage cycling with autoSwitchPreset in Sea…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-15T21:50:05Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "2e1af3fa7f3ecc438093cfee1decedca4801e895",
"body": "* feat(polling): skip invisible panes in library polling loop\n\nAdd paneID field to polling entries and IsPaneVisible() check at top\nof library polling loop. Invisible panes are skipped entirely — no\nstaleness check, no sentinel check, no API dispatch.\n\nImplement checkNewlyVisiblePanes() for preset s\n[…]\newlyVisiblePanes batch\n- Add CyclePreset ('p') stale-check integration test\n- Add checkNewlyVisiblePanes fetching() gate test (sentinel skips newly visible pane)\n\n* chore(docs): mark story 240 as done",
"is_bot": false,
"headline": "feat(polling): skip invisible panes in library polling loop (#338)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-15T21:33:22Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "128432ba3f6280c8b03abb65fc222463afbd7fd6",
"body": "…239) (#337)\n\n* feat(playback): auto-switch preset on user-initiated playback\n\nWhen user initiates playback of content that doesn't match current preset\norientation, auto-switch to appropriate preset:\n- Playing track on podcast preset → switch to Listening (1)\n- Playing episode on music preset → swi\n[…]\ng_AlbumURI_OnMusicPreset_NoSwitch test.\nIssue 5: Add table-driven ActivePreset() unit test with valid indices\nand out-of-bounds zero-value guard clause coverage.\n\n* chore(docs): mark story 239 as done",
"is_bot": false,
"headline": "feat(playback): auto-switch preset on user-initiated playback (story …",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-15T21:07:24Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "f4d5e0aed72341ba62a2f8c0f19647cd238aecc3",
"body": "…olumn (story 238) (#336)\n\n* feat(queue): add mixed content support with QueueItem type and type column\n\n- Add QueueItemType/QueueItem types to domain with custom UnmarshalJSON\n- Update QueueResponse.Queue from []Track to []QueueItem\n- Change store.Queue()/SetQueue() to []QueueItem\n- Update QueueLoa\n[…]\nnd 429 rate-limit test cases to TestGetQueue\n- Handle null items in QueueItem.UnmarshalJSON\n- Add TestQueueItem_NullItem and TestQueueResponse_MixedAndNull tests\n\n* chore(docs): mark story 238 as done",
"is_bot": false,
"headline": "feat(queue): add mixed content support with QueueItem type and type c…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-15T20:16:22Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "7c28f9749afefcee7f6353263c5c0d69c8fdb637",
"body": "…335)\n\n* feat(followedshows): add two-level drill-down for episode sub-view\n\nConvert FollowedShowsPane from flat show list to two-level drill-down:\n- Level 1: show list (existing columns: index, show, publisher, episodes, media)\n- Level 2: episode sub-view (title, released, duration, icon columns)\n-\n[…]\n-level tests: FetchShowEpisodesRequestMsg handler, ViewClosedMsg handler,\n StaleLoadedMsg discard, MatchingID clears sentinel, Error toast, context cancellation\n\n* chore(docs): mark story 236 as done",
"is_bot": false,
"headline": "feat(followedshows): add two-level drill-down for episode sub-view (#…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-15T19:50:14Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0ee05912e69fd32f3cb265da8aab549429486515",
"body": "* feat(episode-details): add Episode Details overlay (i key, story 235)\n\n- Create EpisodeDetailsOverlay with centered overlay, scrollable description\n- Esc/q close, j/k/arrow keys scroll description\n- Uses html_description (preferred) or description (fallback)\n- i key handler checks CurrentlyPlaying\n[…]\nrollClampAfterResize (resize clamp)\n- Add TestEpisodeDetailsOverlay_View_NarrowTerminal (50×40 border check)\n- gofmt whitespace fix in episode_details_overlay.go\n\n* chore(docs): mark story 235 as done",
"is_bot": false,
"headline": "feat(episode-details): add Episode Details overlay (story 235) (#334)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-15T19:05:51Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3bc77e5e4529c08e5ed8f0da8afd7e0433247269",
"body": "…y with 2 updates (#310)",
"is_bot": true,
"headline": "chore(ci)(deps): bump the actions-minor-patch group across 1 director…",
"author_name": "dependabot[bot]",
"author_login": "dependabot[bot]",
"committed_at": "2026-06-15T15:11:25Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "60b2b8789735d7ef90897b6427e7a4a69cbefa78",
"body": "…234) (#333)\n\n* feat(nowplaying): content-aware rendering for track + episode (story 234)\n\n- Add CurrentlyPlayingType switch in View(): track, episode, empty state\n- Add renderEpisodeSideBySide() with episode InfoBox (name, show, release date)\n- Add buildEpisodeInfoLines() for episode content render\n[…]\nowPlayingPane_EpisodeMode_NormalWidthIsOverlay\n- Add TestNowPlayingPane_SeekArrowLeft_EpisodePlaying\n- Add TestNowPlayingPane_Title_EpisodeCompact_ProgressFormat\n\n* chore(docs): mark story 234 as done",
"is_bot": false,
"headline": "feat(nowplaying): content-aware rendering for track + episode (story …",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-14T09:57:19Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fe86adfdfb01a44e26091585c212e6ea92aeae86",
"body": "…sets, delete panes (#332)\n\n* feat(player): rename PageMusic→PagePlayer, remove PagePodcasts, add 6 presets, delete PodcastPlayback/ShowEpisodes\n\nStory 233: Layout rename, presets, delete panes\n\n- Rename PageMusic→PagePlayer everywhere\n- Remove PagePodcasts from page cycle (2-page model: Player↔Stat\n[…]\n music preset switches to\n podcast, show on Stats page switches to Player, already on podcast\n preset is no-op.\n\n* chore(docs): mark story 233 as done\n\n* style: gofmt search_result_routing_test.go",
"is_bot": false,
"headline": "feat(player): rename PageMusic→PagePlayer, remove PagePodcasts, 6 pre…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-14T09:00:28Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "b9f5ba818f0834293636e1235490654b96db56fb",
"body": "* docs(spec): add feature 19 — Player Page Unification with stories 233–243\n\n* docs(spec): add Tasks sections to feature 19 stories, add story template\n\n- All 9 stories (233-236, 238-243) now have ## Tasks sections with\n specific test function names per task\n- Created docs/spec/TEMPLATE-story.md wi\n[…]\nry story structure\n- Updated refine skill to reference template as required format\n- Fixed 'all 13 themes' → 'ConfigTheme implementation' in feature.md AC\n\n* chore: condense AGENTS.md to caveman style",
"is_bot": false,
"headline": "docs(spec): add feature 19 — Player Page Unification (#331)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-13T22:17:54Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "fb211ee1c2ed1fbc713238eeb9a8ec79ba1494b0",
"body": "…irection (#330)",
"is_bot": false,
"headline": "chore: sync AGENTS.md with CLAUDE.md content, remove instructions ind…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-13T16:05:50Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "f62d5b3502a4e9361bc3db94c679e9f51e6abfcf",
"body": "…#329)",
"is_bot": false,
"headline": "chore: add OpenCode project config with AGENTS.md and opencode.json (…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-13T16:01:21Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "caf9cfed3b4e48e04b965187e83ef8e066bd787a",
"body": "…bs, auto-load, info sizing (#328)\n\n* fix(podcasts): address UX bugs — presets, gradient bar, page label, search, auto-load, info sizing\n\n* fix(podcasts): use NowPlaying border color for PodcastPlayback pane\n\n* fix(podcasts): match InfoBox sub-pane border color to NowPlaying green\n\n* fix(podcasts): \n[…]\ndcasts): add tests for HTML renderer, InfoBox accent, adaptive sizing, pageLabel, padding\n\n* fix(podcasts): address review — update border test, fix ANSI assertion, add HTMLDescription end-to-end test",
"is_bot": false,
"headline": "fix(podcasts): UX bugs — presets, gradient bar, page label, search ta…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-13T14:49:38Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "0d1c50eb70abd985ffe36a1c821eea61271995d7",
"body": "…e cycle (#327)\n\n* feat(podcasts): add domain types, PodcastAPI client, and auth scope (story 227)\n\n* feat(podcasts): add store fields, accessors, and message types (story 228)\n\n* feat(podcasts): add layout presets, theme border tokens, 3-page cycle (story 229)\n\n* feat(podcasts): add PodcastPlayback\n[…]\nph, and border issues for CI\n\n* fix(podcasts): address PR review issues — SetSelectedShow, pane forwarding, dead fields, HTTP client, debounce\n\n* chore(docs): mark feature 18 and all 6 stories as done",
"is_bot": false,
"headline": "feat(podcasts): add Podcasts page with 4 panes, API client, and 3-pag…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-12T22:50:02Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "5d86485e957cb2734628573ee57a50504e37ef8d",
"body": null,
"is_bot": false,
"headline": "docs(spec): add feature 18 — Podcasts Page with 6 stories (#326)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-12T22:00:58Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "0ed1abd7fccbf52a246154753ed9b6a687301e6b",
"body": "* fix(viz): use rune iteration for Segments to avoid UTF-8 corruption\n\nsegBuf.WriteByte(lineText[col]) in GaussianRenderer and FloorRenderer\ntreated multi-byte UTF-8 glyphs as single bytes, producing invalid byte\nsequences in Segments that terminals rendered as ?.\n\nConvert lineText to []rune and Wri\n[…]\n\n visible instead of near-background (black, catppuccin, dracula,\n gruvbox, monokai, mono-dark, nord, rosepine, solarized, synthwave,\n tokyonight)\n- Update test expectations for new gradient values",
"is_bot": false,
"headline": "refactor(viz): remove disabled patterns, brighten viz gradients (#325)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-12T20:50:27Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "ee75af25b8824b74cd948f563b1753f23ffb182a",
"body": "…ents (#324)\n\n* feat(viz): add StyledSegment type and Segments field to StyledLine\n\n* feat(viz): freeze visualizer on pause instead of blanking\n\nCurrentFrame() now returns the last frame frozen in place when paused,\nrather than returning a blank frame. This provides a better UX where\nthe visualizer \n[…]\natting for spec compliance\n\n* chore(viz): remove unused renderers (BrailleRenderer, BlockRenderer, SpectrumRenderer, DensityRenderer)\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(viz): visualizer overhaul with 4 patterns and 7-zone color gradi…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-12T20:18:52Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "27dbfc704a4a297e9a3805512d83c65884bb19d1",
"body": "…ve changes (#323)\n\n* fix(playback): seek bar freeze after seek and volume bar flicker after button release\n\nSeek bar froze after interactive seek because DebounceTracker.ConfirmFromAPI\nkept hasPending=true until an exact-match poll arrived. Spotify poll values\nrarely match the confirmed seek target\n[…]\nhen val >= current && val < confirmed\n- Rename signals monotonic-forward playback constraint\n- Add 4 new tests for backward seek stale/valid poll scenarios\n- Update 3 existing tests for renamed method",
"is_bot": false,
"headline": "fix(playback): seek bar freeze and volume bar flicker after interacti…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-11T15:13:07Z",
"body_truncated": true,
"is_coding_agent": false
},
{
"oid": "3d32626e6bffb716ef9b757c56b4f5c602d8fa62",
"body": "…#322)\n\n* feat(playback): add InfoBox padding and center controls (story 226)\n\n* chore(docs): mark story 226 as done",
"is_bot": false,
"headline": "feat(playback): add InfoBox padding and center controls (story 226) (…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-11T13:51:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "5b303c0ef369e1c6d1facd915a5d041d50226e33",
"body": "…ontrols centering (#321)",
"is_bot": false,
"headline": "docs(spec): add story 226 to feature 03 — InfoBox content padding & c…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-11T13:42:40Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "b5eb2109cdabcb8f5ce8da8a32dbd967a186b41b",
"body": "* fix(handlers): deliver rate-limit errors to open overlays on 429\n\nWhen overlay-initiated API calls hit 429 rate limits, the\nRateLimitedMsg handler set global backoff but never forwarded errors\nto profile/device overlays, leaving them stuck in Loading... or\nshowing misleading No devices found state\n[…]\n Claude Fable 5 <noreply@anthropic.com>\n\n* style(handlers): gofmt overlay rate-limit test file\n\n* chore(docs): mark story 225 as done\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "fix(handlers): deliver rate-limit errors to open overlays on 429 (#320)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-11T12:23:09Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "29d90b0f4902f7303a3427d7bbf8903e141fa12d",
"body": "…9 hang) (#319)",
"is_bot": false,
"headline": "docs(spec): add story 225 — overlay rate-limit error delivery (fix 42…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-11T09:46:42Z",
"body_truncated": false,
"is_coding_agent": false
},
{
"oid": "4bd3de42ba7c90ed2502cb5b1562ce312070783c",
"body": "…318)\n\n* feat(components): add DebounceTracker shared component for seek/volume debounce\n\nStory 224 Task 1: Extract the debounce state machine from GradientVolumeBar\ninto a standalone DebounceTracker struct so both GradientVolumeBar and\nGradientSeekBar can embed it. Includes HandleKey (clamping, acc\n[…]\nClaude Fable 5 <noreply@anthropic.com>\n\n* chore(docs): mark story 224 as done\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
"is_bot": false,
"headline": "feat(playback): add interactive seek bar with debounce (story 224) (#…",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-11T09:01:56Z",
"body_truncated": true,
"is_coding_agent": true
},
{
"oid": "3c6a226b0e10712386167656da33e3a4f08d850c",
"body": "* docs(spec): add story 224 to feature 03 — interactive seek bar\n\n* docs(spec): remove dead 'p' keybinding, Shift+arrows are sole prev/next\n\n* docs(spec): rewrite story 224 to match project story template",
"is_bot": false,
"headline": "docs(spec): add story 224 — interactive seek bar (#317)",
"author_name": "Irshad sheikh",
"author_login": "irshsheik",
"committed_at": "2026-06-11T08:11:49Z",
"body_truncated": false,
"is_coding_agent": false
}
],
"releases_count": 8,
"commits_last_year": 1633,
"latest_release_at": "2026-07-17T11:28:11Z",
"latest_release_tag": "v0.1.1",
"releases_from_tags": false,
"days_since_last_push": 3,
"active_weeks_last_year": 17,
"days_since_latest_release": 5,
"mean_days_between_releases": 10.9
},
"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": "github.com/initgrep-apps/spotnik",
"exists": true,
"license": null,
"keywords": [],
"ecosystem": "go",
"matches_repo": true,
"registry_url": "https://pkg.go.dev/github.com/initgrep-apps/spotnik",
"is_deprecated": false,
"latest_version": "v0.1.1",
"repository_url": "https://github.com/initgrep-apps/spotnik",
"versions_count": 8,
"total_downloads": null,
"dependents_count": null,
"deprecation_note": null,
"maintainers_count": null,
"monthly_downloads": null,
"first_published_at": null,
"latest_published_at": "2026-07-17T11:27:59Z",
"latest_version_yanked": null,
"days_since_latest_publish": 5
}
]
},
"popularity": {
"forks": 0,
"stars": 1,
"watchers": 0,
"fork_history": {
"days": [],
"complete": true,
"collected": 0,
"total_forks": 0
},
"star_history": null,
"open_issues_and_prs": 2
},
"ai_readiness": {
"has_nix": false,
"example_dirs": [],
"has_llms_txt": false,
"has_dockerfile": false,
"has_mcp_signal": false,
"bootstrap_files": [
"Makefile"
],
"api_schema_files": [],
"has_devcontainer": false,
"typecheck_configs": [],
"toolchain_manifests": [
"go.mod"
],
"largest_source_bytes": 124337,
"source_files_sampled": 335,
"oversized_source_files": 4,
"agent_instruction_files": [
"AGENTS.md",
"CLAUDE.md"
],
"agent_instruction_max_bytes": 17571
},
"dependencies": {
"manifests": [
"go.mod"
],
"advisories": {
"error": null,
"scope": "repository_graph",
"source": "osv",
"findings": [
{
"name": "github.com/yuin/goldmark",
"direct": false,
"version": "v1.7.13",
"severity": "unknown",
"ecosystem": "go",
"cvss_score": null,
"advisory_ids": [
"GO-2026-5320"
],
"fixed_version": "1.7.17",
"advisory_count": 1,
"oldest_advisory_days": 15
},
{
"name": "golang.org/x/net",
"direct": false,
"version": "v0.55.0",
"severity": "unknown",
"ecosystem": "go",
"cvss_score": null,
"advisory_ids": [
"GO-2026-5942"
],
"fixed_version": "0.56.0",
"advisory_count": 1,
"oldest_advisory_days": 8
},
{
"name": "golang.org/x/text",
"direct": false,
"version": "v0.37.0",
"severity": "unknown",
"ecosystem": "go",
"cvss_score": null,
"advisory_ids": [
"GO-2026-5970"
],
"fixed_version": "0.39.0",
"advisory_count": 1,
"oldest_advisory_days": 8
}
],
"collected": true,
"malicious": [],
"truncated": false,
"by_severity": {
"unknown": 3
},
"advisory_count": 3,
"affected_count": 3,
"assessed_count": 53,
"malicious_count": 0,
"assessed_package": null,
"unassessed_count": 0,
"direct_affected_count": 0
},
"ecosystems": [
"go"
],
"dependencies": [
{
"name": "github.com/BurntSushi/toml",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.6.0"
},
{
"name": "github.com/charmbracelet/bubbles",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.0"
},
{
"name": "github.com/charmbracelet/bubbletea",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.10"
},
{
"name": "github.com/charmbracelet/glamour",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.0.0"
},
{
"name": "github.com/charmbracelet/lipgloss",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.1.1-0.20250404203927-76690c660834"
},
{
"name": "github.com/charmbracelet/x/ansi",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.11.7"
},
{
"name": "github.com/charmbracelet/x/exp/teatest",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.0.0-20260622092256-25656177ba8e"
},
{
"name": "github.com/evertras/bubble-table",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.19.2"
},
{
"name": "github.com/muesli/termenv",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.16.0"
},
{
"name": "github.com/rmhubbert/bubbletea-overlay",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.6.7"
},
{
"name": "github.com/spf13/cobra",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.10.2"
},
{
"name": "github.com/stretchr/testify",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.11.1"
},
{
"name": "github.com/zalando/go-keyring",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.2.8"
},
{
"name": "go.dalton.dog/bubbleup",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v1.3.0"
},
{
"name": "golang.org/x/term",
"manifest": "go.mod",
"ecosystem": "go",
"version_constraint": "v0.43.0"
}
],
"all_dependencies": {
"error": null,
"source": "github-sbom",
"packages": [
{
"name": "github.com/burntsushi/toml",
"direct": true,
"version": "v1.6.0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/bubbles",
"direct": true,
"version": "v1.0.0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/bubbletea",
"direct": true,
"version": "v1.3.10",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/glamour",
"direct": true,
"version": "v1.0.0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/lipgloss",
"direct": true,
"version": "v1.1.1-0.20250404203927-76690c660834",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/ansi",
"direct": true,
"version": "v0.11.7",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/exp/teatest",
"direct": true,
"version": "v0.0.0-20260622092256-25656177ba8e",
"ecosystem": "go"
},
{
"name": "github.com/evertras/bubble-table",
"direct": true,
"version": "v0.19.2",
"ecosystem": "go"
},
{
"name": "github.com/muesli/termenv",
"direct": true,
"version": "v0.16.0",
"ecosystem": "go"
},
{
"name": "github.com/rmhubbert/bubbletea-overlay",
"direct": true,
"version": "v0.6.7",
"ecosystem": "go"
},
{
"name": "github.com/spf13/cobra",
"direct": true,
"version": "v1.10.2",
"ecosystem": "go"
},
{
"name": "github.com/stretchr/testify",
"direct": true,
"version": "v1.11.1",
"ecosystem": "go"
},
{
"name": "github.com/zalando/go-keyring",
"direct": true,
"version": "v0.2.8",
"ecosystem": "go"
},
{
"name": "go.dalton.dog/bubbleup",
"direct": true,
"version": "v1.3.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/term",
"direct": true,
"version": "v0.43.0",
"ecosystem": "go"
},
{
"name": "github.com/alecthomas/chroma/v2",
"direct": false,
"version": "v2.20.0",
"ecosystem": "go"
},
{
"name": "github.com/atotto/clipboard",
"direct": false,
"version": "v0.1.4",
"ecosystem": "go"
},
{
"name": "github.com/aymanbagabas/go-osc52/v2",
"direct": false,
"version": "v2.0.1",
"ecosystem": "go"
},
{
"name": "github.com/aymanbagabas/go-udiff",
"direct": false,
"version": "v0.3.1",
"ecosystem": "go"
},
{
"name": "github.com/aymerick/douceur",
"direct": false,
"version": "v0.2.0",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/colorprofile",
"direct": false,
"version": "v0.4.1",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/cellbuf",
"direct": false,
"version": "v0.0.15",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/exp/golden",
"direct": false,
"version": "v0.0.0-20241011142426-46044092ad91",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/exp/slice",
"direct": false,
"version": "v0.0.0-20250327172914-2fdc97757edf",
"ecosystem": "go"
},
{
"name": "github.com/charmbracelet/x/term",
"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/danieljoos/wincred",
"direct": false,
"version": "v1.2.3",
"ecosystem": "go"
},
{
"name": "github.com/davecgh/go-spew",
"direct": false,
"version": "v1.1.1",
"ecosystem": "go"
},
{
"name": "github.com/dlclark/regexp2",
"direct": false,
"version": "v1.11.5",
"ecosystem": "go"
},
{
"name": "github.com/erikgeiser/coninput",
"direct": false,
"version": "v0.0.0-20211004153227-1c3628e74d0f",
"ecosystem": "go"
},
{
"name": "github.com/godbus/dbus/v5",
"direct": false,
"version": "v5.2.2",
"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/lucasb-eyer/go-colorful",
"direct": false,
"version": "v1.4.0",
"ecosystem": "go"
},
{
"name": "github.com/mattn/go-isatty",
"direct": false,
"version": "v0.0.20",
"ecosystem": "go"
},
{
"name": "github.com/mattn/go-localereader",
"direct": false,
"version": "v0.0.1",
"ecosystem": "go"
},
{
"name": "github.com/mattn/go-runewidth",
"direct": false,
"version": "v0.0.23",
"ecosystem": "go"
},
{
"name": "github.com/microcosm-cc/bluemonday",
"direct": false,
"version": "v1.0.27",
"ecosystem": "go"
},
{
"name": "github.com/muesli/ansi",
"direct": false,
"version": "v0.0.0-20230316100256-276c6243b2f6",
"ecosystem": "go"
},
{
"name": "github.com/muesli/cancelreader",
"direct": false,
"version": "v0.2.2",
"ecosystem": "go"
},
{
"name": "github.com/muesli/reflow",
"direct": false,
"version": "v0.3.0",
"ecosystem": "go"
},
{
"name": "github.com/pmezard/go-difflib",
"direct": false,
"version": "v1.0.0",
"ecosystem": "go"
},
{
"name": "github.com/rivo/uniseg",
"direct": false,
"version": "v0.4.7",
"ecosystem": "go"
},
{
"name": "github.com/sahilm/fuzzy",
"direct": false,
"version": "v0.1.1",
"ecosystem": "go"
},
{
"name": "github.com/spf13/pflag",
"direct": false,
"version": "v1.0.9",
"ecosystem": "go"
},
{
"name": "github.com/xo/terminfo",
"direct": false,
"version": "v0.0.0-20220910002029-abceb7e1c41e",
"ecosystem": "go"
},
{
"name": "github.com/yuin/goldmark",
"direct": false,
"version": "v1.7.13",
"ecosystem": "go"
},
{
"name": "github.com/yuin/goldmark-emoji",
"direct": false,
"version": "v1.0.6",
"ecosystem": "go"
},
{
"name": "golang.org/x/net",
"direct": false,
"version": "v0.55.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/sys",
"direct": false,
"version": "v0.45.0",
"ecosystem": "go"
},
{
"name": "golang.org/x/text",
"direct": false,
"version": "v0.37.0",
"ecosystem": "go"
},
{
"name": "gopkg.in/yaml.v3",
"direct": false,
"version": "v3.0.1",
"ecosystem": "go"
}
],
"collected": true,
"truncated": false,
"total_count": 53,
"direct_count": 15,
"indirect_count": 38
}
},
"maintainership": {
"issues": {
"open_prs": 2,
"merged_prs": 398,
"open_issues": 0,
"closed_ratio": null,
"closed_issues": 0,
"closed_unmerged_prs": 20
},
"bus_factor": 1,
"bot_contributors": 2,
"top_contributors": [
{
"type": "User",
"login": "irshsheik",
"commits": 1623,
"avatar_url": "https://avatars.githubusercontent.com/u/6179346?v=4"
}
],
"contributors_sampled": 1,
"top_contributor_share": 1
},
"quality_signals": {
"has_ci": true,
"has_tests": true,
"ci_workflows": [
"ci.yml",
"release-please.yml",
"release.yml"
],
"has_docs_dir": true,
"linter_configs": [],
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"security_signals": {
"lockfiles": [
"go.sum"
],
"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": 4,
"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": 0,
"reason": "Found 0/26 approved changesets -- score normalized to 0",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
},
{
"name": "Contributors",
"score": 3,
"reason": "project has 1 contributing companies or organizations -- score normalized to 3",
"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 0 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": 10,
"reason": "all dependencies are pinned",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
},
{
"name": "SAST",
"score": 10,
"reason": "SAST tool is run on all commits",
"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": 7,
"reason": "3 existing vulnerabilities detected",
"documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
}
],
"commit": "26a4b7ed7ee567ba4fa12118fda9e1c6714fc441",
"ran_at": "2026-07-23T07:55:25Z",
"aggregate_score": 6,
"scorecard_version": "v5.5.0"
},
"has_codeql_workflow": false,
"has_security_policy": true,
"has_dependabot_config": true
},
"contribution_flow": {
"collected": true,
"ci_last_run_at": "2026-07-20T04:18:40Z",
"oldest_open_prs": [
{
"number": 420,
"created_at": "2026-07-20T04:18:32Z",
"last_comment_at": "2026-07-20T04:18:32Z",
"last_comment_author": "dependabot"
},
{
"number": 421,
"created_at": "2026-07-20T04:18:37Z",
"last_comment_at": "2026-07-20T04:18:37Z",
"last_comment_author": "dependabot"
}
],
"last_merged_pr_at": "2026-07-18T19:55:42Z",
"ci_last_conclusion": "FAILURE",
"oldest_open_issues": []
}
},
"config": {
"disabled_metrics": [],
"disabled_categories": [],
"disabled_components": {}
},
"source": {
"url": "https://github.com/initgrep-apps/spotnik",
"host": "github.com",
"name": "spotnik",
"owner": "initgrep-apps"
},
"metrics": {
"overall": {
"key": "overall",
"band": "moderate",
"name": "Overall health",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"security": 68,
"vitality": 82,
"community": 24,
"governance": 51,
"engineering": 71
},
"components": []
},
"categories": [
{
"key": "vitality",
"band": "good",
"name": "Vitality",
"value": 82,
"weight": 0.22,
"metrics": [
{
"key": "development_activity",
"band": "good",
"name": "Development activity",
"note": null,
"notes": [],
"value": 76,
"inputs": {
"commits_last_year": 1633,
"human_commit_share": 0.95,
"days_since_last_push": 3,
"active_weeks_last_year": 17
},
"components": [
{
"key": "push_recency",
"name": "Push recency",
"detail": "last push 3 days ago",
"points": 36,
"status": "met",
"details": [
{
"code": "push_recency",
"params": {
"days": 3
}
}
],
"max_points": 36
},
{
"key": "commit_cadence",
"name": "Commit cadence",
"detail": "17/52 weeks with commits",
"points": 11.8,
"status": "partial",
"details": [
{
"code": "commit_cadence_weeks",
"params": {
"weeks": 17
}
}
],
"max_points": 36
},
{
"key": "commit_volume",
"name": "Commit volume",
"detail": "1633 commits in the last year",
"points": 18,
"status": "met",
"details": [
{
"code": "commits_last_year",
"params": {
"count": 1633
}
}
],
"max_points": 18
},
{
"key": "openssf_scorecard_maintained",
"name": "OpenSSF Scorecard: Maintained",
"detail": "30 commit(s) and 0 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": 8,
"latest_release_tag": "v0.1.1",
"releases_from_tags": false,
"days_since_latest_release": 5,
"mean_days_between_releases": 10.9
},
"components": [
{
"key": "ships_releases",
"name": "Ships releases",
"detail": "8 releases published",
"points": 27,
"status": "met",
"details": [
{
"code": "releases_published",
"params": {
"count": 8
}
}
],
"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.9 days",
"points": 27,
"status": "met",
"details": [
{
"code": "release_cadence",
"params": {
"gap": 10.9
}
}
],
"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": "critical",
"name": "Community & Adoption",
"value": 24,
"weight": 0.18,
"metrics": [
{
"key": "popularity",
"band": "critical",
"name": "Popularity & adoption",
"note": null,
"notes": [],
"value": 1,
"inputs": {
"forks": 0,
"stars": 1,
"watchers": 0,
"growth_state": "unverified",
"growth_factor_pct": 100,
"growth_unverified_reason": "no_history"
},
"components": [
{
"key": "stars",
"name": "Stars",
"detail": "1 stars",
"points": 0,
"status": "missed",
"details": [
{
"code": "stars",
"params": {
"count": 1
}
}
],
"max_points": 60
},
{
"key": "forks",
"name": "Forks",
"detail": "0 forks",
"points": 0,
"status": "missed",
"details": [
{
"code": "forks",
"params": {
"count": 0
}
}
],
"max_points": 25
},
{
"key": "watchers",
"name": "Watchers",
"detail": "0 watchers",
"points": 0,
"status": "missed",
"details": [
{
"code": "watchers",
"params": {
"count": 0
}
}
],
"max_points": 15
}
]
},
{
"key": "community_health",
"band": "moderate",
"name": "Community health",
"note": null,
"notes": [],
"value": 50,
"inputs": {
"has_readme": true,
"has_license": true,
"has_contributing": false,
"has_issue_template": false,
"has_code_of_conduct": false,
"has_pull_request_template": false
},
"components": [
{
"key": "readme",
"name": "README",
"detail": null,
"points": 22.5,
"status": "met",
"details": [],
"max_points": 22.5
},
{
"key": "license",
"name": "License",
"detail": "recognized license (MIT)",
"points": 22.5,
"status": "met",
"details": [
{
"code": "license_standard",
"params": {}
},
{
"code": "license_spdx",
"params": {
"spdx": "MIT"
}
}
],
"max_points": 22.5
},
{
"key": "contributing_guide",
"name": "CONTRIBUTING guide",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 18
},
{
"key": "code_of_conduct",
"name": "Code of conduct",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 13.5
},
{
"key": "issue_template",
"name": "Issue template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.2
},
{
"key": "pr_template",
"name": "PR template",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.3
}
]
}
],
"description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
},
{
"key": "governance",
"band": "moderate",
"name": "Sustainability & Governance",
"value": 51,
"weight": 0.24,
"metrics": [
{
"key": "maintainer_resilience",
"band": "critical",
"name": "Maintainer resilience (bus factor)",
"note": null,
"notes": [],
"value": 13,
"inputs": {
"bus_factor": 1,
"contributors_sampled": 1,
"top_contributor_share": 1
},
"components": [
{
"key": "bus_factor",
"name": "Bus factor",
"detail": "1 contributor(s) cover half of all commits",
"points": 9,
"status": "partial",
"details": [
{
"code": "bus_factor",
"params": {
"count": 1
}
}
],
"max_points": 54
},
{
"key": "commit_distribution",
"name": "Commit distribution",
"detail": "top contributor authored 100% of commits",
"points": 0,
"status": "missed",
"details": [
{
"code": "top_contributor_share",
"params": {
"share": 100
}
}
],
"max_points": 22.5
},
{
"key": "contributor_breadth",
"name": "Contributor breadth",
"detail": "1 contributors",
"points": 1.4,
"status": "partial",
"details": [
{
"code": "contributors_sampled",
"params": {
"count": 1
}
}
],
"max_points": 13.5
},
{
"key": "openssf_scorecard_contributors",
"name": "OpenSSF Scorecard: Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 3,
"status": "partial",
"details": [],
"max_points": 10
}
]
},
{
"key": "responsiveness",
"band": "moderate",
"name": "Issue & PR responsiveness",
"note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
"notes": [
{
"code": "excluded_no_data",
"params": {
"components": [
"issue_resolution"
]
}
},
{
"code": "weights_renormalized",
"params": {}
}
],
"value": 68,
"inputs": {
"merged_prs": 398,
"open_issues": 0,
"closed_issues": 0,
"issue_closed_ratio": null,
"closed_unmerged_prs": 20
},
"components": [
{
"key": "issue_resolution",
"name": "Issue resolution",
"detail": "no issues or no data",
"points": 0,
"status": "excluded",
"details": [
{
"code": "no_issues_or_data",
"params": {}
}
],
"max_points": 46.75
},
{
"key": "pr_acceptance",
"name": "PR acceptance",
"detail": "398/418 decided PRs merged",
"points": 36.4,
"status": "partial",
"details": [
{
"code": "decided_prs_merged",
"params": {
"merged": 398,
"decided": 418
}
}
],
"max_points": 38.25
},
{
"key": "openssf_scorecard_code_review",
"name": "OpenSSF Scorecard: Code-Review",
"detail": "Found 0/26 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
}
]
},
{
"key": "stewardship",
"band": "at_risk",
"name": "Ownership & stewardship",
"note": null,
"notes": [],
"value": 41,
"inputs": {
"followers": 0,
"owner_type": "Organization",
"is_verified": null,
"owner_login": "initgrep-apps",
"public_repos": 4,
"account_age_days": 1129
},
"components": [
{
"key": "ownership_backing",
"name": "Ownership backing",
"detail": "organization-owned",
"points": 30,
"status": "met",
"details": [
{
"code": "owner_organization",
"params": {}
}
],
"max_points": 30
},
{
"key": "verified_domain",
"name": "Verified domain",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 20
},
{
"key": "owner_reach",
"name": "Owner reach",
"detail": "0 followers of initgrep-apps",
"points": 0,
"status": "missed",
"details": [
{
"code": "owner_followers",
"params": {
"count": 0,
"login": "initgrep-apps"
}
}
],
"max_points": 25
},
{
"key": "track_record",
"name": "Track record",
"detail": "4 public repos, account ~3 yr old",
"points": 11.3,
"status": "partial",
"details": [
{
"code": "public_repos",
"params": {
"count": 4
}
},
{
"code": "account_age_years",
"params": {
"years": 3
}
}
],
"max_points": 25
}
]
},
{
"key": "package_maintenance",
"band": "excellent",
"name": "Package maintenance",
"note": null,
"notes": [],
"value": 100,
"inputs": {
"packages": [
"github.com/initgrep-apps/spotnik"
],
"ecosystems": "go",
"any_deprecated": false,
"min_days_since_publish": 5
},
"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 5 days ago",
"points": 35,
"status": "met",
"details": [
{
"code": "publish_recency",
"params": {
"days": 5
}
}
],
"max_points": 35
},
{
"key": "version_history",
"name": "Version history",
"detail": "8 published versions",
"points": 20,
"status": "met",
"details": [
{
"code": "published_versions",
"params": {
"count": 8
}
}
],
"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": 71,
"weight": 0.2,
"metrics": [
{
"key": "engineering_practices",
"band": "moderate",
"name": "Engineering practices",
"note": null,
"notes": [],
"value": 68,
"inputs": {
"has_ci": true,
"has_tests": true,
"has_editorconfig": false,
"has_linter_config": false,
"has_precommit_config": false
},
"components": [
{
"key": "ci_workflows",
"name": "CI workflows",
"detail": "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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 16
},
{
"key": "pre_commit_hooks",
"name": "Pre-commit hooks",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 9.6
},
{
"key": "editorconfig",
"name": ".editorconfig",
"detail": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 6.4
},
{
"key": "openssf_scorecard_ci_tests",
"name": "OpenSSF Scorecard: CI-Tests",
"detail": "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": 75,
"inputs": {
"topics": [
"cli",
"spotify",
"tui",
"bubbletea",
"charmbracelet",
"golang"
],
"has_wiki": false,
"homepage": null,
"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": null,
"points": 0,
"status": "missed",
"details": [],
"max_points": 15
},
{
"key": "repository_description",
"name": "Repository description",
"detail": null,
"points": 10,
"status": "met",
"details": [],
"max_points": 10
},
{
"key": "topics",
"name": "Topics",
"detail": "6 topics",
"points": 10,
"status": "met",
"details": [
{
"code": "topics_count",
"params": {
"count": 6
}
}
],
"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": 68,
"weight": 0.16,
"metrics": [
{
"key": "security_posture",
"band": "moderate",
"name": "Security posture",
"note": null,
"notes": [],
"value": 60,
"inputs": {
"source": "openssf_scorecard",
"checks_evaluated": 18,
"scorecard_version": "v5.5.0",
"checks_inconclusive": 0,
"scorecard_aggregate": 6
},
"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": 3,
"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 0/26 approved changesets -- score normalized to 0",
"points": 0,
"status": "missed",
"details": [],
"max_points": 7.5
},
{
"key": "contributors",
"name": "Contributors",
"detail": "project has 1 contributing companies or organizations -- score normalized to 3",
"points": 0.8,
"status": "partial",
"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 0 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": "all dependencies are pinned",
"points": 5,
"status": "met",
"details": [],
"max_points": 5
},
{
"key": "sast",
"name": "SAST",
"detail": "SAST tool is run on all commits",
"points": 5,
"status": "met",
"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": "3 existing vulnerabilities detected",
"points": 5.2,
"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, No advisories left outstanding. Remaining weights renormalized. Matched 53 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",
"no_advisories_left_outstanding"
]
}
},
{
"code": "weights_renormalized",
"params": {}
},
{
"code": "advisories_scope_repository",
"params": {
"assessed": 53
}
},
{
"code": "advisories_repo_graph_caveat",
"params": {}
},
{
"code": "advisories_reachability",
"params": {}
}
],
"value": 100,
"inputs": {
"source": "osv",
"advisories": 3,
"affected_packages": 3,
"assessed_packages": 53,
"unassessed_packages": 0,
"affected_by_severity": "unknown 3",
"direct_affected_packages": 0
},
"components": [
{
"key": "direct_dependencies_free_of_known_advisories",
"name": "Direct dependencies free of known advisories",
"detail": "no direct dependency carries a known advisory",
"points": 35,
"status": "met",
"details": [
{
"code": "no_direct_advisories",
"params": {}
}
],
"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 carries a publication date",
"points": 0,
"status": "excluded",
"details": [
{
"code": "advisories_no_publication_date",
"params": {}
}
],
"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": 53,
"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": 1
},
"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": 87,
"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": 17571
},
"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": "95 of 95 human commits state their intent (structured subject or explanatory body)",
"points": 40,
"status": "met",
"details": [
{
"code": "legible_history",
"params": {
"legible": 95,
"sampled": 95
}
}
],
"max_points": 40
}
]
},
{
"key": "ai_verify_loop",
"band": "excellent",
"name": "Verify loop (build / test / typecheck)",
"note": null,
"notes": [],
"value": 85,
"inputs": {
"has_nix": false,
"has_tests": true,
"lockfiles": [
"go.sum"
],
"has_dockerfile": false,
"typed_language": true,
"bootstrap_files": [
"Makefile"
],
"has_devcontainer": false,
"has_linter_config": false,
"typecheck_configs": [],
"agent_commit_share": 0.03,
"toolchain_manifests": [
"go.mod"
],
"dependency_bot_commit_share": 0.04
},
"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": null,
"points": 0,
"status": "missed",
"details": [],
"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": "lockfile",
"points": 10,
"status": "met",
"details": [
{
"code": "file_list",
"params": {
"files": "lockfile"
}
}
],
"max_points": 10
},
{
"key": "demonstrated_agent_practice",
"name": "Demonstrated agent practice",
"detail": "3 of the last 100 commits agent-authored or agent-credited",
"points": 6,
"status": "partial",
"details": [
{
"code": "agent_authored_commits",
"params": {
"count": 3,
"sampled": 100
}
}
],
"max_points": 10
},
{
"key": "automated_maintenance",
"name": "Automated maintenance",
"detail": "4 of the last 100 commits are automated dependency updates",
"points": 8,
"status": "met",
"details": [
{
"code": "dependency_bot_commits",
"params": {
"count": 4,
"sampled": 100
}
}
],
"max_points": 8
},
{
"key": "openssf_scorecard_pinned_dependencies",
"name": "OpenSSF Scorecard: Pinned-Dependencies",
"detail": "all dependencies are pinned",
"points": 10,
"status": "met",
"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": 124337,
"source_files_sampled": 335,
"oversized_source_files": 4
},
"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": "4/335 source files over 60KB",
"points": 54.3,
"status": "partial",
"details": [
{
"code": "oversized_source_files",
"params": {
"kb": 60,
"sampled": 335,
"oversized": 4
}
}
],
"max_points": 55
}
]
}
],
"description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
}
],
"metrics_version": "1.13.0"
},
"warnings": [
"Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
],
"report_type": "repository",
"generated_at": "2026-07-23T07:55:43.492636Z",
"schema_version": "0.27.0",
"badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/i/initgrep-apps/spotnik.svg",
"full_name": "initgrep-apps/spotnik",
"license_state": "standard",
"license_spdx": "MIT"
}