Public record
Software health reportschema 0.27.0 · metrics 1.13.0 · 2026-07-27 05:41 UTC

bang9 / ai-tools

A collection of tools for Claude Code to operate more efficiently

TypeScript · Rust · GoMIT★ 10 stars⑂ 1 forksince Feb 2026View on GitHub ↗

bang9/ai-tools holds a health index of 58 out of 100, placing it in the Moderate band. It scores highest on AI Readiness (86/100) and lowest on Community & Adoption (32/100). It was last updated 11 days ago. A single contributor accounts for most of its recent work.

58
overall / 100
Moderate

Software health index

Metrics are grouped into weighted categories on one standardized 1–100 scale. Overall starts as their weighted mean; when public evidence triggers the High-Risk Jurisdiction Policy, the rating is adjusted and receives an At risk ceiling of 49. AI Readiness sits outside the overall score.

58
Excellent85-100Exemplary; meets essentially all checked criteria
Good70-84Healthy; minor gaps
Moderate50-69Acceptable with notable gaps; review recommended
At risk30-49Significant weaknesses; adoption warrants caution
Critical1-29Severe problems (abandoned, single-maintainer, no hygiene)
VitalityCommunity &AdoptionSustainability &GovernanceEngineeringQualitySecurityAI Readiness

Score profile

Each axis is a category. The shape matters more than the average — a healthy subject fills the whole shape, while a spike-and-crater profile means strength in one dimension is masking risk in another.

Ownership

Hyungu Kang | AirenPersonal account
142 followers106 public repossince Mar 2017@sendbird

This repository is owned by a personal account. A single-owner project carries more continuity risk than an organization-backed one.

Package ecosystems

RegistryPackageVersionDownloads / moVersionsLast publish
Gogithub.com/bang9/ai-toolsv2.17.1+incompatible-11415 days ago

Metrics by category

Vitality

Is the project alive — is code being written and are releases shipping?

82Good · 22% of overall
How it's scored
28.8/36Push recency — last push 11 days ago
13.8/36Commit cadence — 20/52 weeks with commits
18/18Commit volume — 1,068 commits in the last year
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Inputs used
commits_last_year1,068
human_commit_share0.96
days_since_last_push11
active_weeks_last_year20
How it's scored
27/27Ships releases — 100 releases published
36/36Release recency — latest release 15 days ago
27/27Release cadence — a release every ~8.8 days
8/10OpenSSF Scorecard: Signed-Releases — 5 out of the last 5 releases have a total of 5 signed artifacts.
Inputs used
releases_count100
latest_release_tagv2.17.1
releases_from_tagsno
days_since_latest_release15
mean_days_between_releases8.8

Community & Adoption

Does the project have users, downloads, attention, and a welcoming setup for contributors?

32At risk · 18% of overall
How it's scored
15.5/60Stars — 10 stars
0/25Forks — 1 forks
0/15Watchers — 0 watchers
Inputs used
forks1
stars10
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
How it's scored
22.5/22.5README
22.5/22.5License — recognized license (MIT)
0/18CONTRIBUTING guide
0/13.5Code of conduct
0/7.2Issue template
0/6.3PR template
Inputs used
has_readmeyes
has_licenseyes
has_contributingno
has_issue_templateno
has_code_of_conductno
has_pull_request_templateno

Sustainability & Governance

Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?

62Moderate · 24% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
0.4/22.5Commit distribution — top contributor authored 98% of commits
2.7/13.5Contributor breadth — 2 contributors
10/10OpenSSF Scorecard: Contributors — project has 3 contributing companies or organizations -- score normalized to 10
Inputs used
bus_factor1
contributors_sampled2
top_contributor_share0.984
How it's scored
43.5/46.8Issue resolution — 93% of issues closed
34.3/38.3PR acceptance — 26/29 decided PRs merged
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Inputs used
merged_prs26
open_issues2
closed_issues27
issue_closed_ratio0.931
closed_unmerged_prs3
How it's scored
10/30Ownership backing — personal (user) account
0/20Verified domain — not applicable to user accounts
15.5/25Owner reach — 142 followers of bang9
25/25Track record — 106 public repos, account ~9 yr old
Inputs used
followers142
owner_typeUser
is_verified
owner_loginbang9
public_repos106
account_age_days3,425
Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.
How it's scored
25/25Published & resolvable — 1 package(s) on go
35/35Publish recency — latest publish 15 days ago
20/20Version history — 114 published versions
20/20Not deprecated — active, not deprecated or yanked
Inputs used
packagesgithub.com/bang9/ai-tools
ecosystemsgo
any_deprecatedno
min_days_since_publish15

Engineering Quality

Are baseline engineering and documentation practices in place?

66Moderate · 20% of overall
How it's scored
24/24CI workflows — 22 workflow(s)
24/24Tests present
0/16Linter config
0/9.6Pre-commit hooks
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — no data
Inputs used
has_ciyes
has_testsyes
has_editorconfigno
has_linter_configno
has_precommit_configno
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.
How it's scored
30/30README
25/25Documentation directory
0/15Documentation / homepage site
10/10Repository description
10/10Topics — 5 topics
0/10Wiki
Inputs used
topicsai-agent, claude-code, codex, task-manager, task-orchestration
has_wikino
homepage
has_readmeyes
has_docs_diryes
has_descriptionyes

Security

Are visible security and supply-chain practices strong, without unresolved high-risk jurisdiction exposure?

37At risk · 16% of overall
How it's scored
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — no data
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 3 contributing companies or organizations -- score normalized to 10
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5License — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — no data
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
6/7.5Signed-Releases — 5 out of the last 5 releases have a total of 5 signed artifacts.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 140 existing vulnerabilities detected
Inputs used
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate3.7
Excluded from scoring (no data or not applicable): ci_tests, packaging. Remaining weights renormalized.

AI Readiness

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.

86Excellent · 0% of overall
How it's scored
45/45Agent instructions — AGENTS.md, CLAUDE.md, claude-irc/AGENTS.md, claude-irc/CLAUDE.md, grove/AGENTS.md, grove/CLAUDE.md, pipemd/AGENTS.md, pipemd/CLAUDE.md, redit/AGENTS.md, redit/CLAUDE.md, rewind/AGENTS.md, rewind/CLAUDE.md, vaultkey/AGENTS.md, vaultkey/CLAUDE.md, webform/AGENTS.md, webform/CLAUDE.md, whip/AGENTS.md, whip/CLAUDE.md
15/15Machine-readable docs (llms.txt) — llms.txt present
40/40Legible commit history — 95 of 96 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtyes
legible_history_share0.99
agent_instruction_filesAGENTS.md, CLAUDE.md, claude-irc/AGENTS.md, claude-irc/CLAUDE.md, grove/AGENTS.md, grove/CLAUDE.md, pipemd/AGENTS.md, pipemd/CLAUDE.md, redit/AGENTS.md, redit/CLAUDE.md, rewind/AGENTS.md, rewind/CLAUDE.md, vaultkey/AGENTS.md, vaultkey/CLAUDE.md, webform/AGENTS.md, webform/CLAUDE.md, whip/AGENTS.md, whip/CLAUDE.md
agent_instruction_max_bytes11,585
How it's scored
18/18One-command bootstrap — claude-irc/Makefile, pipemd/Makefile, redit/Makefile, rewind/Makefile, vaultkey/Makefile, webform/Makefile, whip/Makefile
22/22Automated tests
0/11Lint / format config
11/11Static type checking — grove/tsconfig.json, rewind/web/tsconfig.json, whip/dashboard-web/tsconfig.json
10/10Reproducible environment — lockfile
10/10Demonstrated agent practice — 83 of the last 100 commits agent-authored or agent-credited
0/8Automated maintenance — no automated dependency updates observed
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Inputs used
has_nixno
has_testsyes
lockfilesCargo.lock, go.sum, pnpm-lock.yaml
has_dockerfileno
typed_languageyes
bootstrap_filesclaude-irc/Makefile, pipemd/Makefile, redit/Makefile, rewind/Makefile, vaultkey/Makefile, webform/Makefile, whip/Makefile
has_devcontainerno
has_linter_configno
typecheck_configsgrove/tsconfig.json, rewind/web/tsconfig.json, whip/dashboard-web/tsconfig.json
agent_commit_share0.83
toolchain_manifestsclaude-irc/go.mod, grove/Cargo.toml, grove/grove-agent/Cargo.toml, grove/grove-core/Cargo.toml, grove/grove-daemon/Cargo.toml, grove/src-electron/native/Cargo.toml, grove/src-tauri/Cargo.toml, pipemd/go.mod, redit/go.mod, rewind/go.mod, shared/irclib/go.mod, shared/upgrade/go.mod, vaultkey/go.mod, webform/go.mod, whip/go.mod
dependency_bot_commit_share0
How it's scored
45/45Type-checkable code — TypeScript (statically typed)
54.4/55Manageable file sizes — 6/586 source files over 60KB
Inputs used
primary_languageTypeScript
largest_source_bytes156,492
source_files_sampled586
oversized_source_files6

Key facts

10GitHub stars
2contributors
1,068commits, last 12 months
11days since last push
100releases
1bus factor
2open issues
crates.io, Go, npmpackage ecosystems

Data collection warnings

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

More detail

OpenSSF Scorecard 3.7 / 10
3.7aggregate

Independent, tool-agnostic security assessment from the open-source OpenSSF Scorecard. Each check rewards a security practice, not a specific vendor's tool. Checks Scorecard could not determine are marked n/a and excluded from the security score (never counted as zero).Scorecard v5.5.0 · 2026-07-27 05:41 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
n/aCI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
10Contributorsproject has 3 contributing companies or organizations -- score normalized to 10
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
n/aPackagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
8Signed-Releases5 out of the last 5 releases have a total of 5 signed artifacts.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities140 existing vulnerabilities detected
Direct dependencies 58
RegistryPackageVersion constraintManifest
Gogithub.com/bang9/ai-tools/shared/irclibv0.0.0claude-irc/go.mod
Gogithub.com/bang9/ai-tools/shared/upgradev0.0.0claude-irc/go.mod
Gogithub.com/spf13/cobrav1.10.2claude-irc/go.mod
npm@dnd-kit/core^6.3.1grove/package.json
npm@dnd-kit/modifiers^9.0.0grove/package.json
npm@dnd-kit/sortable^10.0.0grove/package.json
npm@dnd-kit/utilities^3.2.2grove/package.json
npm@radix-ui/react-context-menu^2.2.16grove/package.json
npm@radix-ui/react-dialog^1.1.15grove/package.json
npm@radix-ui/react-popover^1.1.15grove/package.json
npm@radix-ui/react-separator^1.1.8grove/package.json
npm@radix-ui/react-slot^1.2.4grove/package.json
npm@radix-ui/react-toast^1.2.15grove/package.json
npm@radix-ui/react-tooltip^1.2.8grove/package.json
npm@tanstack/react-virtual3.13.24grove/package.json
npm@tauri-apps/api^2grove/package.json
npm@tauri-apps/plugin-process^2.3.1grove/package.json
npm@tauri-apps/plugin-updater^2.10.0grove/package.json
npm@xterm/addon-fit0.12.0-beta.289grove/package.json
npm@xterm/addon-search0.17.0-beta.289grove/package.json
npm@xterm/addon-unicode110.10.0-beta.289grove/package.json
npm@xterm/addon-web-links0.13.0-beta.289grove/package.json
npm@xterm/addon-webgl0.20.0-beta.288grove/package.json
npm@xterm/xterm6.1.0-beta.289grove/package.json
npmallotment^1grove/package.json
npmclass-variance-authority^0.7.1grove/package.json
npmclsx^2.1.1grove/package.json
npmlucide-react^0.577.0grove/package.json
npmreact^19grove/package.json
npmreact-dom^19grove/package.json
npmshiki^4.3.1grove/package.json
npmtailwind-merge^3.5.0grove/package.json
npmzustand^5grove/package.json
Gogithub.com/alecthomas/chroma/v2v2.20.0pipemd/go.mod
Gogithub.com/bang9/ai-tools/shared/upgradev0.0.0pipemd/go.mod
Gogithub.com/mattn/go-runewidthv0.0.16pipemd/go.mod
Gogithub.com/yuin/goldmarkv1.7.16pipemd/go.mod
Gogolang.org/x/termv0.30.0pipemd/go.mod
Gogithub.com/bang9/ai-tools/shared/upgradev0.0.0redit/go.mod
Gogithub.com/bang9/ai-tools/shared/upgradev0.0.0rewind/go.mod
Gogithub.com/charmbracelet/bubblesv1.0.0rewind/go.mod
Gogithub.com/charmbracelet/bubbleteav1.3.10rewind/go.mod
Gogithub.com/charmbracelet/lipglossv1.1.0rewind/go.mod
Gogithub.com/tdewolff/minify/v2v2.24.10rewind/go.mod
Gogithub.com/bang9/ai-tools/shared/upgradev0.0.0vaultkey/go.mod
Gogithub.com/spf13/cobrav1.9.1vaultkey/go.mod
Gogolang.org/x/cryptov0.48.0vaultkey/go.mod
Gogolang.org/x/termv0.40.0vaultkey/go.mod
Gogithub.com/bang9/ai-tools/shared/upgradev0.0.0webform/go.mod
Gogithub.com/bang9/ai-tools/shared/irclibv0.0.0whip/go.mod
Gogithub.com/bang9/ai-tools/shared/upgradev0.0.0whip/go.mod
Gogithub.com/charmbracelet/bubbleteav1.3.4whip/go.mod
Gogithub.com/charmbracelet/lipglossv1.1.0whip/go.mod
Gogithub.com/charmbracelet/x/ansiv0.8.0whip/go.mod
Gogithub.com/google/uuidv1.6.0whip/go.mod
Gogithub.com/mdp/qrterminal/v3v3.2.1whip/go.mod
Gogithub.com/spf13/cobrav1.10.2whip/go.mod
Gogolang.org/x/termv0.40.0whip/go.mod
All dependencies not collected

The resolved dependency set could not be collected for this report: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Raw JSON report machine-readable
{
  "data": {
    "repo": {
      "topics": [
        "ai-agent",
        "claude-code",
        "codex",
        "task-manager",
        "task-orchestration"
      ],
      "is_fork": false,
      "size_kb": 11293,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Go": 1104757,
        "CSS": 35055,
        "HTML": 2927,
        "Rust": 1587620,
        "Shell": 134307,
        "Makefile": 4872,
        "JavaScript": 35911,
        "TypeScript": 1705844
      },
      "pushed_at": "2026-07-16T01:18:21Z",
      "created_at": "2026-02-05T11:56:29Z",
      "owner_type": "User",
      "updated_at": "2026-07-16T01:18:25Z",
      "description": "A collection of tools for Claude Code to operate more efficiently",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript",
        "Rust",
        "Go"
      ]
    },
    "owner": {
      "blog": "https://velog.io/@bang9dev",
      "name": "Hyungu Kang | Airen",
      "type": "User",
      "login": "bang9",
      "company": "@sendbird",
      "location": "Seoul",
      "followers": 142,
      "avatar_url": "https://avatars.githubusercontent.com/u/26326015?v=4",
      "created_at": "2017-03-10T12:18:40Z",
      "is_verified": null,
      "public_repos": 106,
      "account_age_days": 3425
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.17.1",
          "kind": "patch",
          "published_at": "2026-07-11T17:23:44Z"
        },
        {
          "tag": "v2.17.0",
          "kind": "minor",
          "published_at": "2026-07-11T16:58:00Z"
        },
        {
          "tag": "v2.16.11",
          "kind": "patch",
          "published_at": "2026-07-10T05:46:56Z"
        },
        {
          "tag": "v2.16.10",
          "kind": "patch",
          "published_at": "2026-07-10T05:07:19Z"
        },
        {
          "tag": "v2.16.9",
          "kind": "patch",
          "published_at": "2026-07-09T06:14:44Z"
        },
        {
          "tag": "v2.16.8",
          "kind": "patch",
          "published_at": "2026-07-08T03:30:32Z"
        },
        {
          "tag": "v2.16.7",
          "kind": "patch",
          "published_at": "2026-07-05T14:22:18Z"
        },
        {
          "tag": "v2.16.6",
          "kind": "patch",
          "published_at": "2026-05-30T06:01:40Z"
        },
        {
          "tag": "v2.16.5",
          "kind": "patch",
          "published_at": "2026-04-24T10:29:43Z"
        },
        {
          "tag": "v2.16.4",
          "kind": "patch",
          "published_at": "2026-04-23T18:17:02Z"
        },
        {
          "tag": "v2.16.3",
          "kind": "patch",
          "published_at": "2026-04-05T11:04:50Z"
        },
        {
          "tag": "v2.16.2",
          "kind": "patch",
          "published_at": "2026-04-05T10:30:44Z"
        },
        {
          "tag": "v2.16.1",
          "kind": "patch",
          "published_at": "2026-04-05T10:11:40Z"
        },
        {
          "tag": "v2.16.0",
          "kind": "minor",
          "published_at": "2026-04-04T13:31:08Z"
        },
        {
          "tag": "v2.15.0",
          "kind": "minor",
          "published_at": "2026-03-30T20:16:30Z"
        },
        {
          "tag": "v2.14.2",
          "kind": "patch",
          "published_at": "2026-03-27T06:02:48Z"
        },
        {
          "tag": "v2.14.1",
          "kind": "patch",
          "published_at": "2026-03-26T12:27:38Z"
        },
        {
          "tag": "v2.14.0",
          "kind": "minor",
          "published_at": "2026-03-26T11:01:23Z"
        },
        {
          "tag": "v2.13.1",
          "kind": "patch",
          "published_at": "2026-03-24T04:48:30Z"
        },
        {
          "tag": "v2.13.0",
          "kind": "minor",
          "published_at": "2026-03-23T11:39:16Z"
        },
        {
          "tag": "v2.12.0",
          "kind": "minor",
          "published_at": "2026-03-20T16:42:40Z"
        },
        {
          "tag": "v2.11.0",
          "kind": "minor",
          "published_at": "2026-03-20T09:08:31Z"
        },
        {
          "tag": "v2.10.1",
          "kind": "patch",
          "published_at": "2026-03-19T17:24:34Z"
        },
        {
          "tag": "v2.10.0",
          "kind": "minor",
          "published_at": "2026-03-19T17:03:42Z"
        },
        {
          "tag": "v2.9.5",
          "kind": "patch",
          "published_at": "2026-03-18T02:40:43Z"
        },
        {
          "tag": "v2.9.4",
          "kind": "patch",
          "published_at": "2026-03-18T00:25:27Z"
        },
        {
          "tag": "v2.9.3",
          "kind": "patch",
          "published_at": "2026-03-17T15:52:23Z"
        },
        {
          "tag": "v2.9.2",
          "kind": "patch",
          "published_at": "2026-03-17T09:21:51Z"
        },
        {
          "tag": "v2.9.1",
          "kind": "patch",
          "published_at": "2026-03-17T08:41:33Z"
        },
        {
          "tag": "v2.9.0",
          "kind": "minor",
          "published_at": "2026-03-17T08:10:57Z"
        },
        {
          "tag": "v2.8.2",
          "kind": "patch",
          "published_at": "2026-03-16T13:41:20Z"
        },
        {
          "tag": "v2.8.1",
          "kind": "patch",
          "published_at": "2026-03-16T13:09:54Z"
        },
        {
          "tag": "v2.8.0",
          "kind": "minor",
          "published_at": "2026-03-16T12:45:45Z"
        },
        {
          "tag": "v2.7.2",
          "kind": "patch",
          "published_at": "2026-03-15T17:38:48Z"
        },
        {
          "tag": "v2.7.1",
          "kind": "patch",
          "published_at": "2026-03-15T17:24:57Z"
        },
        {
          "tag": "v2.7.0",
          "kind": "minor",
          "published_at": "2026-03-15T16:37:11Z"
        },
        {
          "tag": "v2.6.2",
          "kind": "patch",
          "published_at": "2026-03-15T04:56:01Z"
        },
        {
          "tag": "v2.6.1",
          "kind": "patch",
          "published_at": "2026-03-15T00:56:05Z"
        },
        {
          "tag": "v2.6.0",
          "kind": "minor",
          "published_at": "2026-03-13T21:41:35Z"
        },
        {
          "tag": "v2.5.0",
          "kind": "minor",
          "published_at": "2026-03-13T17:01:53Z"
        },
        {
          "tag": "v2.4.2",
          "kind": "patch",
          "published_at": "2026-03-12T00:31:47Z"
        },
        {
          "tag": "v2.4.1",
          "kind": "patch",
          "published_at": "2026-03-11T19:22:58Z"
        },
        {
          "tag": "v2.4.0",
          "kind": "minor",
          "published_at": "2026-03-11T18:48:27Z"
        },
        {
          "tag": "v2.3.0",
          "kind": "minor",
          "published_at": "2026-03-11T13:27:43Z"
        },
        {
          "tag": "v2.2.0",
          "kind": "minor",
          "published_at": "2026-03-11T12:40:33Z"
        },
        {
          "tag": "v2.1.3",
          "kind": "patch",
          "published_at": "2026-03-10T09:04:24Z"
        },
        {
          "tag": "v2.1.2",
          "kind": "patch",
          "published_at": "2026-03-10T08:42:42Z"
        },
        {
          "tag": "v2.1.1",
          "kind": "patch",
          "published_at": "2026-03-10T08:36:26Z"
        },
        {
          "tag": "v2.1.0",
          "kind": "minor",
          "published_at": "2026-03-10T06:50:46Z"
        },
        {
          "tag": "v2.0.0",
          "kind": "major",
          "published_at": "2026-03-09T19:34:50Z"
        },
        {
          "tag": "v1.39.0",
          "kind": "minor",
          "published_at": "2026-03-09T14:02:32Z"
        },
        {
          "tag": "v1.38.1",
          "kind": "patch",
          "published_at": "2026-03-09T08:17:57Z"
        },
        {
          "tag": "v1.38.0",
          "kind": "minor",
          "published_at": "2026-03-09T08:03:43Z"
        },
        {
          "tag": "v1.37.0",
          "kind": "minor",
          "published_at": "2026-03-09T05:59:45Z"
        },
        {
          "tag": "v1.36.0",
          "kind": "minor",
          "published_at": "2026-03-09T03:26:55Z"
        },
        {
          "tag": "v1.35.4",
          "kind": "patch",
          "published_at": "2026-03-08T10:48:31Z"
        },
        {
          "tag": "v1.35.3",
          "kind": "patch",
          "published_at": "2026-03-08T09:59:04Z"
        },
        {
          "tag": "v1.35.2",
          "kind": "patch",
          "published_at": "2026-03-08T03:03:04Z"
        },
        {
          "tag": "v1.35.1",
          "kind": "patch",
          "published_at": "2026-03-08T02:59:17Z"
        },
        {
          "tag": "v1.35.0",
          "kind": "minor",
          "published_at": "2026-03-08T02:46:17Z"
        },
        {
          "tag": "v1.34.9",
          "kind": "patch",
          "published_at": "2026-03-08T02:29:33Z"
        },
        {
          "tag": "v1.34.8",
          "kind": "patch",
          "published_at": "2026-03-08T02:24:57Z"
        },
        {
          "tag": "v1.34.7",
          "kind": "patch",
          "published_at": "2026-03-08T01:52:29Z"
        },
        {
          "tag": "v1.34.6",
          "kind": "patch",
          "published_at": "2026-03-08T01:45:40Z"
        },
        {
          "tag": "v1.34.5",
          "kind": "patch",
          "published_at": "2026-03-08T01:33:48Z"
        },
        {
          "tag": "v1.34.4",
          "kind": "patch",
          "published_at": "2026-03-08T01:30:47Z"
        },
        {
          "tag": "v1.34.3",
          "kind": "patch",
          "published_at": "2026-03-08T01:26:56Z"
        },
        {
          "tag": "v1.34.2",
          "kind": "patch",
          "published_at": "2026-03-08T01:22:44Z"
        },
        {
          "tag": "v1.34.1",
          "kind": "patch",
          "published_at": "2026-03-08T01:21:00Z"
        },
        {
          "tag": "v1.34.0",
          "kind": "minor",
          "published_at": "2026-03-08T01:15:45Z"
        },
        {
          "tag": "v1.33.9",
          "kind": "patch",
          "published_at": "2026-03-08T01:14:21Z"
        },
        {
          "tag": "v1.33.8",
          "kind": "patch",
          "published_at": "2026-03-08T01:09:43Z"
        },
        {
          "tag": "v1.33.7",
          "kind": "patch",
          "published_at": "2026-03-08T01:08:25Z"
        },
        {
          "tag": "v1.33.6",
          "kind": "patch",
          "published_at": "2026-03-08T01:03:26Z"
        },
        {
          "tag": "v1.33.5",
          "kind": "patch",
          "published_at": "2026-03-08T00:56:59Z"
        },
        {
          "tag": "v1.33.4",
          "kind": "patch",
          "published_at": "2026-03-08T00:52:23Z"
        },
        {
          "tag": "v1.33.3",
          "kind": "patch",
          "published_at": "2026-03-08T00:50:09Z"
        },
        {
          "tag": "v1.33.2",
          "kind": "patch",
          "published_at": "2026-03-08T00:48:13Z"
        },
        {
          "tag": "v1.33.1",
          "kind": "patch",
          "published_at": "2026-03-08T00:43:55Z"
        },
        {
          "tag": "v1.33.0",
          "kind": "minor",
          "published_at": "2026-03-08T00:34:11Z"
        },
        {
          "tag": "v1.32.0",
          "kind": "minor",
          "published_at": "2026-03-07T23:35:52Z"
        },
        {
          "tag": "v1.31.0",
          "kind": "minor",
          "published_at": "2026-03-07T22:17:55Z"
        },
        {
          "tag": "v1.30.0",
          "kind": "minor",
          "published_at": "2026-03-07T20:20:50Z"
        },
        {
          "tag": "v1.29.0",
          "kind": "minor",
          "published_at": "2026-03-07T18:58:44Z"
        },
        {
          "tag": "v1.28.0",
          "kind": "minor",
          "published_at": "2026-03-07T18:48:14Z"
        },
        {
          "tag": "v1.27.0",
          "kind": "minor",
          "published_at": "2026-03-07T18:10:12Z"
        },
        {
          "tag": "v1.26.1",
          "kind": "patch",
          "published_at": "2026-03-07T17:11:11Z"
        },
        {
          "tag": "v1.26.0",
          "kind": "minor",
          "published_at": "2026-03-07T17:06:40Z"
        },
        {
          "tag": "v1.25.0",
          "kind": "minor",
          "published_at": "2026-03-07T16:21:33Z"
        },
        {
          "tag": "v1.24.0",
          "kind": "minor",
          "published_at": "2026-03-07T15:57:25Z"
        },
        {
          "tag": "v1.23.0",
          "kind": "minor",
          "published_at": "2026-03-07T15:31:53Z"
        },
        {
          "tag": "v1.22.0",
          "kind": "minor",
          "published_at": "2026-03-07T14:45:17Z"
        },
        {
          "tag": "v1.21.0",
          "kind": "minor",
          "published_at": "2026-03-07T14:27:59Z"
        },
        {
          "tag": "v1.20.3",
          "kind": "patch",
          "published_at": "2026-03-06T09:35:59Z"
        },
        {
          "tag": "v1.20.2",
          "kind": "patch",
          "published_at": "2026-03-06T09:19:09Z"
        },
        {
          "tag": "v1.20.1",
          "kind": "patch",
          "published_at": "2026-03-06T08:31:30Z"
        },
        {
          "tag": "v1.19.0",
          "kind": "minor",
          "published_at": "2026-03-06T03:17:53Z"
        },
        {
          "tag": "v1.18.0",
          "kind": "minor",
          "published_at": "2026-03-04T17:03:26Z"
        },
        {
          "tag": "v1.17.0",
          "kind": "minor",
          "published_at": "2026-03-04T16:50:34Z"
        },
        {
          "tag": "v1.16.0",
          "kind": "minor",
          "published_at": "2026-03-04T16:33:56Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "23a780750dbd2faf797094538f725b29ed2cc1de",
          "body": null,
          "is_bot": false,
          "headline": "fix(grove): restore window and panel layout state",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-16T01:18:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0ac5effd083813ba086f2b2003e786de9ef64405",
          "body": "Grove's terminal WebGL lifecycle/atlas-recovery handling references\npatterns from Orca (stablyai/orca, MIT, Copyright (c) 2026 Lovecast\nInc.) — record the attribution with the full MIT text.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(grove): add Orca third-party license notice",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-15T05:24:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "061a075755104d0c03836ff10037b8ab31e654d7",
          "body": "The global terminal's canvas sits inside a CSS-transformed slide container\n(the tab translateX animation), and WKWebView composites a WebGL canvas\nunder a transform unreliably — panes gradually accumulated glyph\ncorruption while simply idling, with the worktree panes unaffected. Add a\nTerminalRuntim\n[…]\nset it for global terminal tabs.\nMirror tabs keep the source pane's runtime, so worktree panes stay on\nWebGL for TUI-heavy rendering throughput.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): pin the global terminal to the DOM renderer",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-15T05:24:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0fd787fc21fea2d7af9c54bd1c6ee8cc32cd4471",
          "body": "…r terminal\n\nxterm's WebGL glyph atlas is shared across every same-config terminal\n(module-level CharAtlasCache), but WebglAddon.clearTextureAtlas() repaints\nonly its own renderer. Any pane clearing the atlas therefore invalidated\nthe glyph coordinates every OTHER pane still held, rendering them as\n\n[…]\ngle shared\n  clear followed by a repaint of every visible pane\n  (recoverTerminalsForWake), with regression tests for the clear-once\n  contract.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): stop per-pane glyph-atlas clears from garbling every othe…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-15T05:23:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b42c10913ac9ebc3acf5a8771b550ec2636de083",
          "body": "…n fixes\n\nStable xterm 6.0.0 ships two texture-atlas bugs that corrupt WebGL panes:\natlas page merges leave stale vertices (xtermjs/xterm.js#5883) and shared\natlas pages are not invalidated per renderer (#6042) — visible as black\ncells and scattered glyph fragments while typing. Pin the 6.1.0-beta l\n[…]\nnew options-object signature so\npreserveDrawingBuffer (needed by the broadcast snapshot compositor) stays\nenabled instead of silently degrading.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): bump xterm to the 6.1 beta line for WebGL atlas corruptio…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-15T05:22:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a99ee8130bbf43ef4ead029885185013a9ce2ece",
          "body": "… the pub-API test\n\nThe lifecycle test's final teardown calls shutdown(true); a shutdown that kills\nthe daemon naturally drops the control connection, so on a slower runner the\nreply never arrives and the client returns ConnectionLost. That IS the daemon\ngoing down — the goal of the call. Production\n[…]\n\nrunner is green (all other daemon suites, incl. the flow-control ordering test\nthat only breaks on Linux, already pass on macOS).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(grove): tolerate ConnectionLost when shutting the daemon down in…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T15:22:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f37435ac9f3e2aa72a7f64268c60933911f3adb6",
          "body": "…d macOS PTY/kernel)\n\ngrove ships only on macOS, and the grove-daemon integration tests exercise\nmacOS-specific behavior (sysctl KERN_PROC_PID, LOCAL_PEERPID, real-shell\noutput ordering under flow control) that does not reproduce on the Ubuntu\nrunner. Split the Rust job: grove-core (portable) stays \n[…]\n macos-latest so CI tests what actually ships. Also run\nthe workflow on changes to itself + add workflow_dispatch for manual runs.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ci(grove): run grove-daemon tests on macOS (its integration tests nee…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T15:17:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "33ff1ad999c5eb494a09f630db3334f14ccc9422",
          "body": "…inux CI)\n\nThe agent-status claim path reads the connecting pid via LOCAL_PEERPID and\nprocess facts via sysctl(KERN_PROC_PID) — both macOS-only, matching grove's\nmacOS-only shipping target. peer_pid was cfg(unix) and used the macOS\nSOL_LOCAL option on Linux too, so it returned 'peer pid unreadable' \n[…]\ntegration tests to macOS. The\npure map_event/resolve logic stays covered on every target by the FakeKernel\nunit tests in agent.rs.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): gate agent-status peer-pid + socket tests to macOS (fix L…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T15:12:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "163b4a9d7b4e410ff4c625ea99f6f28d23bf2489",
          "body": "…cess-group reap\n\nThe previous commit (70f3d2c) accidentally committed a DELETION of\ngrove-core/src/process_env.rs: the mission working directory was removed by\nan external process mid-commit, so `git commit --only <path>` staged the\nfile's now-deleted state. This restores the file (from 0f79fd3) an\n[…]\nprocess group and killpg on timeout, so a timed-out interactive probe reaps\nany children its rc spawned instead of orphaning them.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): restore process_env.rs (accidentally deleted) + probe pro…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T14:58:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "70f3d2cd620770b17641fecabb057f73c1df91d8",
          "body": "The interactive login-shell PATH probe (zsh -i -c) sources the user's rc,\nwhich can spawn children (a plugin, a backgrounded job). On the 15s timeout\nthe code killed only the shell's own pid, orphaning any such children.\nSpawn the probe in its own process group and killpg on timeout so the whole\ntre\n[…]\nnceLock-cached per\nprocess and completes in ms), but leaking the probe's grandchildren on a\ngenuine timeout was a real latent bug.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): reap the whole login-shell probe group on timeout",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T14:55:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0f79fd398a3b4607c5d93c29deb79cbe1fdef5fa",
          "body": "One line per pane per app launch, to the daemon log — makes it observable\nwhether a relaunch warm-reattached a surviving session or spawned fresh,\nwhich is exactly the signal needed to diagnose 'my terminal did not survive\nthe app restart' reports. Confirmed against the real app: quit → relaunch\nlogs ATTACH (warm reattach) for each surviving pane.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(grove): log daemon createOrAttach decisions (attach vs spawn)",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T14:17:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "eefb2806aa1dc5968c821a249ae17e00a2cee199",
          "body": "On reattach, the restored scrollback replays the device queries a running\nagent emitted at startup (OSC 10/11 colour probes, DSR/CPR, DA). xterm\nanswers them via onData, and the runtime forwarded every onData straight to\nthe PTY — so those stale duplicate replies (ESC]11;rgb:…, ESC[…R, ESC[?…c,\nESC[\n[…]\neply must reach the PTY. A headless-xterm test pins that xterm really\ndoes answer an embedded query, so the guard is load-bearing.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): drop xterm query replies during scrollback replay",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T13:46:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f658db6b1774373cc19cf4138fefc3a074d45bba",
          "body": "…ing it\n\nA v1 user upgrading to v2 must not keep running the old daemon. The adoption\ngate preserved a stale daemon whenever it owned live sessions (L5), so on a\nmajor update the new app silently adopted the old build — which does not speak\nthe new protocol (the agent-status role is additive; an old\n[…]\ntale daemon stays the exception: it can't be RPC-migrated, so it is\nadopted-unresponsive and the client reconnect-drains it (L3e).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): replace a stale daemon on version change instead of adopt…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T13:27:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ec2ad4f229f1a89e26f8504e4e8b33c7d6bb7633",
          "body": "This reverts commit 46ed2134115421cd4a6ffb8f5f6ca6a09997260e.",
          "is_bot": false,
          "headline": "Revert \"fix(grove): no agent badge until the agent reports a phase\"",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T13:21:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2d3997e297a829c39db77ff1cd73d413d701e5ce",
          "body": "The detached PTY daemon and the agent-status launcher are load-bearing now,\nbut neither Tauri nor Electron builds them, so a fresh install shipped an app\nwhose Contents/MacOS held only `grove` — the daemon could not spawn (and the\nrelease codesign gate would refuse an unsigned one anyway). install-l\n[…]\nnotarized Developer-ID release must instead sign each sidecar with the cert\nand re-sign + notarize the whole .app after injection.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "build(grove): bundle grove-daemon and grove-agent sidecars into the app",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T13:01:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "46ed2134115421cd4a6ffb8f5f6ca6a09997260e",
          "body": "Closes the one documented gap in the status redesign: a claimed-but-eventless\nagent (a codex whose one-time hook-trust the user has not granted) showed\ncodex:idle instead of no badge, contradicting the design's thesis that no\nbadge beats a wrong one. AgentClaim.phase is now Option<Phase>, None until\n[…]\nes with\nSessionStart within milliseconds, so they still earn their idle badge; only\nthe genuinely-silent hook channel stays blank.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): no agent badge until the agent reports a phase",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T13:00:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a18fba28c979ef8055cdbca7c853618e109b8d30",
          "body": "…timers, ps-walk, status file)\n\nStatus now comes from exactly one source — the agents' own structured hook\nevents — and liveness from exactly one source — the kernel, queried at read\ntime (pid + p_starttime fence + p_stat). Claude and Codex both ship a\nPermissionRequest hook that fires at the instan\n[…]\n granted shows codex:idle instead of no badge (never a false\nattention, never a wedge; self-heals globally the moment they trust).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): agent status from hook events + kernel liveness (delete …",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T12:47:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c8e436425f41449818251f32bbe89013743299ae",
          "body": "…it and reboot\n\nBREAKING: grove no longer uses tmux. The detached grove-daemon owns every\nPTY, so shells now survive app quit AND machine reboot (warm reattach to the\nlive shell; cold restore from disk when the daemon died). External\n'tmux attach' recovery and ~/.tmux.conf (keybindings, copy-mode,\nh\n[…]\nB RSS / 5.8%\nCPU vs tmux server 8.5 MB / 3.4%; RSS plateaus (per-session ring and\nscrollback caps), no leak, no checkpoint stalls.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove)!: PTY daemon P9 cutover — tmux removed, shells survive qu…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T09:10:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "edfba08cc84c0f77188351a3b9dbd1c4a6b83e20",
          "body": "on_new_window is backed by WKWebView's UI delegate\n(-webView:createWebViewWithConfiguration:...), and WebKit's popup blocker runs\nBEFORE that delegate. WKPreferences.javaScriptCanOpenWindowsAutomatically\ndefaults to NO and neither wry nor Tauri turns it on for macOS (wry only does so\non Android), so\n[…]\n ever created — on_new_window still denies every request and\nthe frontend opens a Grove browser tab, now in the opener's worktree.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): let Tauri browser guests open popups without a user gesture",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T08:17:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d52bccb16776371267a199829d50b18eff01ecf0",
          "body": "…n them at all)\n\nTwo bugs, one path.\n\n1. On Electron, target=_blank / window.open did nothing at all. The `<webview>`\n   is created without `allowpopups`, so the guest may not even request a window\n   — the request is dropped before the main process's setWindowOpenHandler runs.\n   That handler is no\n[…]\n when that worktree is the visible one — a background\npage must not steal the active tab of a worktree the user will come back to.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): open target=_blank tabs in the opener's worktree (and ope…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T08:01:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f5eda52850eee061cd2bfd97f5bb5ec7e51055ae",
          "body": "AppTabContent only enumerated the selected worktree's tabs, so switching\nworktrees unmounted every BrowserPanel. On Electron that detaches the in-DOM\n<webview> and destroys the guest — the page reloaded, losing scroll, form and\nin-page state. (Tauri's native child webview merely hid, so the gap was\n\n[…]\native subviews could stack itself over the active page), and the\n  suggestion memos no longer recompute over the frecency history.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): keep browser pages alive across worktree switches",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T07:33:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "85083e19844ad1e1e1494739a324163a0f20f86c",
          "body": "Opening any overlay (the \"+\" new-tab context menu, dialogs) blacked out the\nbrowser area on Tauri: the visibility effect hid the native child webview, so\nthe punchout hole showed its dark window backing instead of the page.\n\nOverlays now do what the suggestions/history dropdowns already do — send th\n[…]\nerlay composites\nover a still-visible page. Electron is unaffected (its in-DOM webview is\nz-indexed under the overlay either way).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): keep browser page visible while overlays are open",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-12T06:56:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c0e43da295cb75b184a0bf13ee9f19fa715a63b3",
          "body": "…GC helpers, restart\n\nProducer flow control (S14/P11): pause parks the blocking reader on a\ncondvar before catch_unwind (kernel PTY backpressure blocks the child);\n5s generation-guarded failsafe force-resumes so a lost resume can never\nwedge a shell; kill/watchdog resume BEFORE signalling (a parked \n[…]\nP9 frontend can synthesize\nexits before teardown; SIGSTOP-wedged daemon recovered via re-verified\nSIGKILL; 3 restart cycles leak zero processes.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): PTY daemon P8 — flow control, sleep/wake, runtime RPCs, …",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T22:36:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "087f3dea4ca7548285a11efab291c2e9ebcadadc",
          "body": "history.rs: per-session terminal-history/v{N}/{pty_id}/ dirs with advisory\nflock ownership, meta.json ended_at discriminator, durable-rename\ncheckpoints (tmp → fsync → rename → fsync(dir), off the tick thread), GCKL\nincremental log with generation pairing (mismatch/seq-gap → log dropped),\ntorn-tail \n[…]\nould replay a previous session under a reused\nid; torn checkpoints with gen≥1 logs restored nothing instead of degrading\nto a tail-only restore.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): PTY daemon P7 — disk history, checkpointer, cold restore",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T21:15:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a751b86cf98e2b010aee0bed5bd1c1fcfae9422f",
          "body": "- Tauri: inject a guest script that hooks history.pushState/replaceState\n  and popstate and reports route changes over a `grovespa://` channel, so\n  client-side SPA navigations update the address bar and history stack\n  (pushState → push a new entry, replaceState → replace current, popstate\n  → move\n[…]\nlank page, regardless of the app theme — matching a\n  loaded page's white and never revealing the transparent window's dark\n  punchout backing.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): capture SPA navigation on Tauri + white browser start page",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T19:54:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c4133b379dd4086fbae1fa6d5b97cbf077edb827",
          "body": "Ubuntu's default bashrc PS1 repaints the title via OSC 0 on every prompt\nunder TERM=xterm*, overwriting the printf'd OSC 2 title before the test\npolls it. Spawn the session with TERM=dumb so rc files stay quiet.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): stabilize daemon OSC title test on Linux CI",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T19:36:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d3bfb0dd0fa9522841b2863f5e7c49aeff5b6950",
          "body": "…r tag\n\nThe release CI publishes a floating major tag (`v2`) alongside `vX.Y.Z`.\n`git tag --sort=-creatordate | head -1` was picking `v2`, so APP_VERSION\nbecame \"2\" — which the Tauri build rejected (\"version must be a semver\nstring\"). Filter to full `vX.Y.Z` tags so local Tauri builds work again.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): install-local.sh picks semver tags, not the floating majo…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T19:34:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4ac7828a4374d37bb137e9b9bb73105289ad62b2",
          "body": "…ix Tauri stack collapse\n\nBack/forward niceties (parity with orca's browser pane):\n- Long-press or right-click the Back/Forward buttons to open a history\n  dropdown (favicon + title from frecency history) and jump multiple\n  entries at once. New store `jumpHistory` optimistically pre-sets the\n  inde\n[…]\n URL): the bridge now uses the\n  store's MERGED title instead of the raw event title, which Tauri's\n  page_load Finished event carries as null.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): browser back/forward history dropdown + mouse buttons; f…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T19:34:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ff7308b90bdcdac0459e6bb7ccda096569888456",
          "body": "Two Linux-runner-only failures:\n- git_diff test helper committed without a git identity, which fails on\n  runners with no global config — inject GIT_AUTHOR/COMMITTER env vars.\n- refresh_project fake-git/ssh scripts separated argv with printf '%s\\x1f',\n  but dash (Ubuntu /bin/sh) printf has no hex escapes and logged the literal\n  text, breaking the 0x1f pattern match — use octal \\037 instead.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): make grove-core tests pass on CI runners",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T19:30:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bc238577515bb7e1cd90b0cde8d5f29ce9cbf4b7",
          "body": "…ation, golden differential tests\n\nClient: DaemonClient now parses the daemon's S15 warm-reattach reply into\nWarmReattach (snapshot payload, dims, alt flag, pending escape tail, kitty\nflags, cwd/title, degraded marker) instead of dropping it; global client\nslot + ack_cold_restore seam added (populat\n[…]\n all attack rounds (tmux\nbyte-identity, S16 order fidelity vs orca, write-guard ordering, a novel\nalt+kitty+DECSTBM+DECSC+dangling-CSI fixture).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): PTY daemon P6 — reattach end-to-end, daemonSnapshot hydr…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T19:18:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d7550614643fb266eb8f4a1e8cac427c4f52b039",
          "body": "…hot serializer\n\nDaemonEmulator wraps vt100::Parser as the daemon-side emulator-of-record;\nsnapshot() serializes preamble (modes vt100 omits: 1049/mouse/focus/kitty/\nbracketed-paste, OSC 0/2 title, DECSTBM) + contents_formatted body + gated\nsaved-cursor tail (off by default — trust vt100). ModeState\n[…]\nndependently verified against 4.3M-stream\nexhaustive scan, 16 fresh seeds, and persisted park->prepend->rescan\nreplay with zero counterexamples.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): PTY daemon P5 — vt100 emulator, ModeState tracker, snaps…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T18:27:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "31f4252eca8e93f575b97c60f0cad5746162153a",
          "body": "Port the remaining browser affordances to the Electron in-DOM <webview>\nwithout a preload bundle: inject scripts via executeJavaScript and receive\nguest→host messages over console-message sentinels (orca's annotation pattern).\n\n- grab mode: port the Tauri picker (crosshair hover-highlight, click to \n[…]\nnd bar even when the guest page holds focus (__GROVE_FIND_OPEN__).\n- tab-chip favicons: browser tabs show tab.faviconUrl with a globe fallback.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): Electron browser grab + in-page find + tab favicons",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T18:03:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f11b1576c20645a383e816b88320de80322c24b0",
          "body": "…ied-size readback\n\nLand the Electron halves of already-committed grove-core features:\n- powerMonitor 'resume' → grove:display-wake broadcast (WebGL atlas heal);\n  'unlock-screen' deliberately excluded (fires without a GPU reset)\n- setAppVersion(app.getVersion()) before any PTY create so shells see \n[…]\nassert + post-spawn\nreconcile + non-convergence adopt-and-stop) in terminal-resize.md and the\nMirror-clamp interaction in terminal-broadcast.md.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): Electron shell wiring for display-wake, app version, appl…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T18:01:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d43a568114e30c47ed4b497d3f23ff4a50e2c251",
          "body": "… punchout\n\nMake the address-bar dropdown (and DOM chrome) overlay the browser page on\nBOTH platforms, orca-style, instead of pushing the webview down.\n\n- Electron: replace the native WebContentsView (composited above the DOM) with\n  an in-DOM <webview> element (lib/browser-dom-webview.ts). DOM chro\n[…]\nills it; the host window needs sandbox:true + webviewTag for the\nguest to attach; dev:electron needs a full restart to pick up main.ts changes.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): true browser overlay — Electron in-DOM <webview> + Tauri…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T17:52:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6638bfaae7f71f1ad99c93cb3695f2624a7a738b",
          "body": "…on@v2 resolves",
          "is_bot": false,
          "headline": "fix(ci): maintain floating major tag (v2) on release so vaultkey-acti…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T17:33:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "35d7bafbf9991e5015f95f139c19392399013868",
          "body": null,
          "is_bot": true,
          "headline": "chore: update plugin versions to v2.17.1",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-11T17:24:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "142736de14dbb71283fbb6ae1a593b4cb04638f0",
          "body": "…t conflicted rebases, add repair command",
          "is_bot": false,
          "headline": "fix(vaultkey): multi-user sync recovery — push leftover commits, abor…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T17:23:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8d5dca467a954c32399e00e17d70c7a11296b833",
          "body": "…atch",
          "is_bot": false,
          "headline": "ci(vaultkey-action): trigger test on workflow changes and manual disp…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T17:08:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "82f37509ea6efec910a1a2c88a058032eba214c1",
          "body": null,
          "is_bot": false,
          "headline": "fix(ci): update vaultkey-action smoke test for multi-vault repo path",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T17:07:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "54f4db2bf3be910a40c4f4cee85f43ac6bd282e6",
          "body": null,
          "is_bot": true,
          "headline": "chore: update plugin versions to v2.17.0",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-11T16:59:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9f5377419e4abab8f0910667ae2bc655d6cde217",
          "body": "…ds, per-vault password env",
          "is_bot": false,
          "headline": "feat(vaultkey): multi-vault support — named vaults, use/vaults comman…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T16:57:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "02f4866d65fa5a25aaf98b0f086c2b3ce6dbd9a7",
          "body": "Daemon phases P3/P4 per notes/daemon-design.md; tmux path untouched.\n\nP3 DaemonClient (grove-core/src/daemon/client.rs): NDJSON control RPC\nwith id→oneshot pending map and per-request timeouts; binary GCKL\nstream loop with per-session Data/Exit subscribers (byte seq);\ngeneration-guarded reconnect — \n[…]\ns replaces. Review: 2 lenses, 5\nminors fixed + adversarially re-verified. grove-core 251 Rust tests\ngreen; workspace clean; JS suites untouched.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): PTY daemon P3+P4 — client and supervisor (adoption gate)",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T16:43:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bc1aba1b1d8f44fe9b2d5d256309f927ff46a8e3",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): center right-panel empty-state text when wrapped",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T16:18:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "91284d3700670e59f7b062b36bf987172c88af14",
          "body": "Both are prompt-only rows with no queryable status, and macOS shows their\none-time consent prompt automatically on first real use (per target app\nfor Apple Events, per app for local network) — after a denial the nudge\ncannot re-prompt either, so the rows carried no real control. The\nInfo.plist usage strings stay since the organic prompts still use them.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): drop automation/local-network rows from permissions pane",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T15:52:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "241b411b4c416c09b7b1b76f8193d57b2b311d28",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(grove): run grove-daemon tests in CI",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T15:47:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "59d26d1457ddef8ae1a988fa7d9ab06ea3d587e8",
          "body": "De-tmux daemon per notes/daemon-design.md (orca-parity restart survival;\nclean cut, ships as a major update; tmux path untouched until the P9\ncutover).\n\nP1 — grove-core/src/daemon/: GROVE_DAEMON_PROTOCOL_VERSION=1, versioned\nendpoint path helpers (0600 token/pid), Hello handshake + NDJSON RPC\nenvelo\n[…]\n fixed and adversarially re-verified. Gates: grove-core 235 +\ngrove-daemon 12 Rust tests, workspace check clean, JS suite untouched\n(632 green).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): PTY daemon P1+P2 — protocol module and grove-daemon binary",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T15:46:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "406fbc79f4bc4f1d10be3fd83aeec22b26685943",
          "body": "…ription\n\nTCC SIGKILLs the process when requestAccessForMediaType: runs without the\nmatching NS*UsageDescription in the main bundle — exactly what happened in\ntauri dev when the running image predated the Info.plist embedding. Check\nthe key via NSBundle (the same source TCC consults) and fall back to\nopening the Privacy pane instead of prompting when it is absent.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): guard media permission request against missing usage desc…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T14:49:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8dc02b4aa3c092afd764cf423027e93d14de4501",
          "body": "…loper permissions)\n\nSettings gains a Permissions tab showing live TCC status for microphone,\ncamera, screen recording, accessibility, full disk access, automation,\nand local network, with per-row request / open-settings / trigger-prompt\nactions. Granting Full Disk Access stops the per-folder macOS \n[…]\nc-tauri/src/dev_permissions.rs). Usage-description strings land in\nsrc-tauri/Info.plist (merged at bundle time) and electron-builder\nextendInfo.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): add macOS permissions management pane (port of orca deve…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T14:42:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3b703e031bb9c7e5ecba81768f2aec17ba505257",
          "body": "The suggestions dropdown is a DOM element and the browser content is a native\nwebview layered above the DOM, so the dropdown was made visible by hiding the\nwhole webview — blanking the entire page the moment the address bar was\nfocused. Instead, keep the webview visible and push its top down past the\ndropdown's bottom edge, so the dropdown shows in the reclaimed strip and the\npage stays visible below it.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): keep the page visible when the address-bar dropdown is open",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T14:37:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b952daa9bfae737b57f3f07a2a94971fc87b6faf",
          "body": "…name, successor rule\n\nApplies /simplify review findings across the tab overhaul:\n- ui/sortable.tsx: shared SortableItem wrapper + usePointerDragSensors,\n  replacing three near-identical copies (AppTabBar, ProjectCategoryFilterBar,\n  ProjectTree)\n- hooks/useInlineRename.ts: one inline-edit state mac\n[…]\nile-browser preference when visiting non-git selections\n- drop dead pinned-era closable guards, memoize tab ids, single-pass\n  terminal ordinals\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(grove): dedupe tab/pane cleanup — shared sortable, inline re…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T14:09:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "26a4627723912d5cb8d880bbe4dd7a4015e6b5f2",
          "body": "…resize reconcile\n\nTerminal-parity Phases 7+10 (tmux-path hardening; carries the transition\nperiod while the PTY-daemon backend is built).\n\nAtlas recovery: in-place TUI redraws with CJK/emoji/RTL/replacement\nglyphs could leave stale wide glyphs in the WebGL atlas until the next\nreveal. Risky output \n[…]\nss/invariance): both majors\n(Hangul atlas refresh, stability-gate bypass) fixed + verified. Suite:\n617 JS + 207 Rust green; both shells compile.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): atlas recovery on CJK output + applied-size readback and …",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T14:08:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e861a9d032a1797ff3d1861708eef9eda160eb4a",
          "body": "WKWebView has no page-favicon-updated event, so the favicon is resolved in\nthe guest (GUEST_FAVICON_SCRIPT): prefer the largest declared\n<link rel~=\"icon\">, else the origin /favicon.ico; only http(s)/data URLs are\nposted so the app chrome can render them. A <head> MutationObserver\nre-reports when SP\n[…]\nuseInlineRename)\n— that one-line render is held in the working tree until that refactor lands.\nVerified: lint, tsc, browser tests, cargo check.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): browser favicons — resolve, store, and show in suggestions",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T14:06:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d63166f03f144b61cc9489681930df58b6fad2d4",
          "body": "The leading address-bar icon now reflects the loaded page's transport — a\nlock for https, an amber shield for http (\"Not secure\"), a file glyph for\nfile://, globe otherwise — instead of a static globe.\n\nAddress-bar input that reads as a query (whitespace, or a bare word with no\nhost/port/scheme) now\n[…]\n. Search engine\ndefaults to Google (looksLikeSearchQuery/buildSearchUrl/resolveAddressInput\nin browser-url.ts). Verified: lint, tsc, 612 tests.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): address-bar security indicator + web-search fallback",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T13:56:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1719107c48a8e3b35c78832b404f8c0725b9a209",
          "body": "CSS.Translate instead of CSS.Transform — the horizontal sortable strategy's\nscale component resized the dragged chip to each differently-sized neighbor\nit passed over.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): dragged tab chip no longer stretches to neighbor widths",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T13:53:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "40aee994fc49a385407949e9c3fc8c2b89d82204",
          "body": "Replace the thin address-bar-only MRU list (recentUrls: string[], 50 max,\nrecency only) with a real visited-page history: {url, normalizedUrl, title,\nfaviconUrl?, visitCount, lastVisitedAt}, capped at 200 and persisted to\nlocalStorage (the legacy recentUrls list migrates on first load).\n\nEvery commi\n[…]\nefix match. Start-page quick links use the top sites.\n\nrecordFavicon is added for the upcoming favicon feature. Verified: lint,\ntsc, 603 tests.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): frecency browser history + richer address-bar autocomplete",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T13:50:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d102acf84d2110224c6e8427291ea32999af243e",
          "body": "…nal tab rename\n\n- Adding a terminal tab switches to it only after the pty spawns, instead\n  of flashing the previously active terminal\n- Closing the visible tab activates its nearest neighbor in the unified\n  list; a terminal neighbor is addressed via the sentinel + terminal store\n  (previously lan\n[…]\nty resets to the derived Terminal N name), title\n  persists on the tab entry in ui-state.json\n- IME guard added to the pane label editor as well\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): tab selection on add/close, dnd-kit sortable strip, termi…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T13:47:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a389405b62e4473d6b44f46b6479bf8657986a31",
          "body": "Cmd/Ctrl+F opens a docked find bar over browser tabs. Because the native\nwebview sits above the DOM, the bar can't overlay it — it renders as a row\nthat shrinks the webview host, and the existing bounds-sync moves the view\ndown to make room. Typing highlights matches; Enter / Shift+Enter and the\nche\n[…]\n but the main-process handlers are\ndeferred (main.ts is mid-change in a parallel session); Tauri is the default\ntarget and is fully wired here.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): find-in-page for the embedded browser (Tauri)",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T13:31:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "16b5eeae8ca8d3a4b55f3cb387a514bdc067e741",
          "body": "The strip takes all remaining bar width, hides its scrollbar, gains\nside padding so the chip hover lift/scale isn't clipped, and the +\nbutton rides inside the strip right after the last tab.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): tab strip spans full width with hidden scrollbar",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T13:22:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fe214dd2488190e279f43a31b7671737feb3c758",
          "body": "…er, chip polish\n\nTerminal tabs become ordered entries in the app tab list so every tab\nkind shares one creation-ordered, user-reorderable row.\n\n- terminal entries mirror the terminal store via a subscription\n  (lib/terminal-tab-sync); the tab store owns only their position and\n  never touches scope\n[…]\np-right\n  pane header: the label stays visible, the actions (and a Tag button\n  to add a label) expand on pane hover, and editing happens inline\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): unified tab ordering, closable last terminal, drag reord…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T13:21:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3c7f4257ec8a4b8e8ba433bd012cca864a225651",
          "body": "…ness\n\nTerminal-parity Phases 6+8.\n\nPhase 6 — a theme toggle left 2031-subscribed TUIs (fish, neovim,\nClaude Code) rendering a stale palette:\n- Pure color-scheme module: background-luminance dark/light classifier\n  (Rec.709 over normalized sRGB so mid-gray sits exactly at the 0.5\n  boundary), orca's\n[…]\nnned byte-identical by tests.\n\nSuite: 544 JS + 203 Rust green; both shells compile; 2-lens review\npassed (its three minor findings fixed above).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): DECSET 2031 theme notifications + shell env/PATH correct…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T08:50:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "51e9b7dec1145ba9307a24c5f20db1ccd8713fde",
          "body": "Add resolveSelectionCapabilities as the single source of truth for\nwhich features the current sidebar selection supports: git-backed\nselections (worktrees, source) get everything, plain directories\n(mission roots) get directory features only, git features (changes,\ncommits) are blocked.\n\n- pinned Te\n[…]\ne right panel mode via the new\n  right-panel store\n- PiP now follows the user to every non-terminal tab, including native\n  browser webview tabs\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): selection-capability driven tab and panel visibility",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T08:48:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "63532c79b9f9f66059a90b5e2ae280e80e88252c",
          "body": "…y lines\n\nThe grab payload is multi-line markdown; writing it raw to the terminal made\neach newline submit a separate line, so one picked element looked like several\nsends. Wrap it in a single bracketed paste (sanitized) so it lands as one block\nin the agent's input, and drop a duplicate delivery of the same element within\na short window as a guard.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): deliver a grabbed element as one bracketed paste, not man…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T08:34:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "498d92282c5ee22008ff05cef80539d12a07f6da",
          "body": "…2/7/8, theme gate\n\nTerminal-parity Phase 5.\n\n- Bracketed-paste command-injection fix (security): xterm 6.0.0's built-in\n  paste wraps clipboard text in ESC[200~/201~ with no embedded-ESC\n  stripping, so pasted text containing ESC[201~;<cmd> closes the frame\n  early and executes the tail. A capture-\n[…]\nreplay. disposed\n  runtimes skip the swap entirely.\n\n3-lens review (security/correctness/invariance) passed; suite 519 JS\ngreen, tsc/lint clean.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): terminal protocol correctness — paste sanitization, OSC 5…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T08:30:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9f49b048ddd5f944a487d0f72dc0fb0cba3d5c38",
          "body": "…> Browser\n\nCookie import is a session-level action, not a per-tab one, so remove the\ntoolbar cookie menu and add a Browser tab in Preferences that lists detected\nbrowsers and imports their full cookie jar (no per-site scoping).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(grove): move cookie import from browser toolbar to Settings …",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T08:26:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "78bfa6361c49bf22168e6c4abf895fee5c01857a",
          "body": "Terminal tabs now render as first-class chips in the app tab bar (the\npinned Terminal slot expands into one chip per terminal tab), instead\nof a nested tab strip inside the terminal area. The add-tab menu now\noffers Browser | Terminal | Changes: Terminal opens a new terminal tab\nin the current workt\n[…]\ninal tab is guarded on an existing session so a pty is\n  never spawned into a worktree without one\n- removes the nested TerminalTabBar component\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): lift terminal tabs into the app tab bar",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T08:25:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4d7bfa9523e2ae828f8a3d9973fb09702099cbc5",
          "body": "Terminal sessions become tabbed: each worktree holds multiple terminal\ntabs, each tab its own split tree. A tab bar above the terminal area\nlists tabs by number with add/close controls and a red dot when a\nbackground tab has a bell or an AI session awaiting attention.\n\n- store model: sessions map to\n[…]\ngates on active worktree AND active tab)\n- PiP/Mirror policies unchanged; they key off the focused pane, which\n  always lives in the visible tab\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): add per-worktree terminal tabs",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T08:10:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5c5285611ff7b2ceff5b5e6ffde142e2ffb296f8",
          "body": "Terminal-parity Phase 4 (data integrity). Two real corruption paths:\nconcurrent writePty calls for one PTY raced a non-FIFO writer mutex\nacross spawn_blocking threads, so >4KB pastes could reorder whole\nbatches (paste body vs trailing Enter); and a multi-MB paste was one\nunbounded fire-and-forget wr\n[…]\nadversarial lenses; the one major finding (stranded opener)\nis fixed above. Suite: 197 Rust + 453 JS green, tsc/lint clean, both\nshells compile.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): guarantee terminal input ordering and pace large pastes",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T07:49:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "12f8eb2706b7a502a7096119ae9a825a1ff3cf54",
          "body": "Replace the shared terminal toolbar with a per-pane action cluster\n(mirror / split vertical / split horizontal / close) shown on pane hover\nat the top-right, styled like the pane label chip. Actions target the\npane they belong to instead of the focused pty, so the focused-pane\nreverse lookup and the\n[…]\nast overlay\n- refresh is dropped (superseded by the upcoming terminal tabs)\n- removes TerminalToolbar and the terminal command pipeline/registry\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): move terminal actions to per-pane hover cluster",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T07:46:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a6d237b92b412c7d77e2baca6f9d986481873f7d",
          "body": "Cookie import only looked at \"<browser>/Default/Cookies\", so Chrome installs\nwhose active profile is \"Profile 1\" (or any non-Default profile) were reported\nas not installed and could not be imported. Scan every profile directory and\nsupport both the legacy \"<profile>/Cookies\" and newer\n\"<profile>/Network/Cookies\" locations, picking the most-recently-modified\ncookie DB (the active profile). Guest/System profiles are skipped.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): detect Chromium cookies across profiles and Network/ layout",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T07:21:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "36299cbaa35f7edc616ee9abb2e25e940091dfc4",
          "body": "Adds orca-style \"grab mode\" to browser tabs. Clicking the crosshair toolbar\nbutton arms an element picker in the guest; hovering highlights elements and\nclicking one captures it (selector, tag, text, outer HTML, page URL/title) and\nsends it as markdown into the focused worktree terminal, where a cod\n[…]\ntext-menu\nchannel; Rust forwards it to the renderer as a browser:grab event, which writes\nthe formatted element to the focused PTY via writePty.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): grab browser elements into the agent terminal",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T07:05:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8e5e098a2939cf638fb49e155a54b98b679eef06",
          "body": "Tauri half of the Phase-2 display-wake recovery: an NSWorkspace didWake\nobserver (raw objc2 msg_send + block2, matching the existing FFI style\nin browser.rs) emits grove:display-wake through the AppHandle; the\nfrontend subscription (436d96e) clears the WebGL DOM-latch and rebuilds\nglyph atlases on visible panes. The Electron powerMonitor half follows\nseparately (its file is entangled with in-flight browser work).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): emit display-wake event from Tauri on macOS system resume",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T07:03:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ececcf15490e0ee2ea934a365d8ee3c2ca2ece56",
          "body": "…t foundation)\n\nGrove had only a per-keydown isComposing guard with no persistent\ncomposition-active state, so nothing could safely ask \"is a Hangul/CJK\ncomposition live right now?\" — the question the upcoming capture-phase\nbracketed-paste sanitizer must answer to avoid corrupting an in-flight\ncompo\n[…]\nlls on term.open and\ndisposes with the pane. 9 unit tests (state transitions, IME quirks,\nexpiry clock, listener-leak assertion); suite 433/433.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): track IME composition state on the terminal (Korean inpu…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T07:03:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "436d96e0e927269125aa9e01ed34401619e76abc",
          "body": "…GPU churn\n\nTerminal-parity Phase 2 (renderer side). Previously onContextLoss\ndisposed and rescheduled a new WebglAddon indefinitely — a busy loop\nunder persistent GPU failure — and a reveal/resize/theme tick could\nconstruct addons with no cool-down; suspend/dispose dropped the addon\nwithout releasi\n[…]\n release spy, snapshot\nfallback, wake debounce/visibility gating); suite 424 JS + 193 Rust\ngreen; behavior below the failure paths is unchanged.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): harden WebGL renderer lifecycle against context loss and …",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:53:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "44a748ad15208af435d30b43540dd9c5fb748326",
          "body": "…r tabs\n\nAdds a toolbar menu on browser tabs that imports login cookies from an\ninstalled browser (Chrome, Arc, Brave, Edge, Chromium, Safari, Firefox) into\nGrove's browser session, so the user is signed in inside the embedded browser.\nPorted from orca's browser-cookie-import, scoped to macOS.\n\n- gr\n[…]\nDecryption/Keychain run off-thread.\n- UI: BrowserCookieImportMenu detects browsers and imports scoped to the active\n  site's host, then reloads.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): import login cookies from installed browsers into browse…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:53:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8871c09d1433fba737275de630dc82e92693e112",
          "body": "A parallel test process churning the shared tmux server can make the\nhas-session probe transiently error, which the reap path correctly\ntreats as skip-this-round; the test now retries briefly instead of\nfailing on that environment race.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(grove): retry tmux reap probe under concurrent server churn",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:53:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d675d06632671fdb679eb2a5338682e3e9930f62",
          "body": "A PTY whose tmux session died outside grove (external kill, tmux server\nrestart, pane exit) left its registry entry — master fd, writer, child\nhandle — leaked until app restart: the reader thread EOFs silently and\nthe worktree-path GC never sees in-registry corpses.\n\nTerminal GC now snapshots the re\n[…]\n item.\n\nTerminalGcReport TS fields landed with 29376c3; the developer tab now\nlists reaped/dead-reader entries and counts them in run summaries.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): reap dead PTY registry entries in terminal GC",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:48:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "29376c3fa76314bddc094a4c3f5c08fd4b1b7217",
          "body": "…estarts\n\nUI state persists to ~/.grove/ui-state.json via new save_ui_state /\nload_ui_state commands, following the panel-layouts convention (loaded\nonce into a synchronous cache before mount, whole-file flush on a short\ndebounce):\n\n- File browser: per-root expanded paths + selection restore on root\n[…]\nhanges tabs; file viewer tabs reload\n  lazily on first activation; browser tabs restore in the suspended\n  shape (URL only, native history gone)\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): persist file browser expansion and tab sessions across r…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:47:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9322ad4580f8eef80ec63677442fc35d528ee5a4",
          "body": "…malize IconButton icon sizing\n\nClosing the active tab now prefers the closable neighbor and falls back\nto Terminal instead of a pinned tab the user didn't pick. IconButton\ngains an iconSize prop (sm/md) that sizes child svgs, so the file\nbrowser toolbar and file/image viewer headers share one icon scale\nwithout per-icon size classes.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): land on terminal after closing the last closable tab; nor…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:30:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e1dd66358b27636f5c10bb49f6e78b115813918d",
          "body": "Differential harness for the raw-tail scrollback restore path: a seeded\n(mulberry32) agent-TUI stream generator (CJK/emoji/ZWJ, SGR, cursor moves,\nscroll regions, alt-screen, DEC 2026 frames) replayed into @xterm/headless,\ncomparing a live reference against tail-cut restores at arbitrary byte\noffset\n[…]\nenv vars\ngate the deep loop. Adds @xterm/headless as a devDependency (no runtime\ndep). The Rust ring-boundary property test landed with 000417d.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(grove): seeded ANSI restore-fidelity fuzz harness",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:25:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c89f79c553bb29d79da4cac2cf8d3a080948eff2",
          "body": "…r wedge\n\nA synchronous throw inside a term.write completion callback permanently\nwedges xterm's vendored WriteBuffer: the drain never re-arms and the pane\nfreezes for the rest of the session (reproduced against real @xterm/xterm\n6.0.0 in the new test). Port orca's write-callback-guard semantics: ea\n[…]\nerately untouched and pinned by tests.\n\nRegression proof: neutering the guard fails 4 of the 7 new tests,\nincluding the WriteBuffer stall repro.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): guard xterm write-completion callbacks against WriteBuffe…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:24:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "000417d1e799d1ff6fe379888f48749aea757989",
          "body": "…alescer backlog\n\nThree coupled freeze/crash safety nets in grove-core (terminal-parity Phase 1):\n\n- lock_recover(): every hot production lock (registry, per-instance\n  writer/tracked, coalescer state) recovers a poisoned mutex via\n  into_inner() instead of bricking all future PTY ops after a panic.\n[…]\nng behavior).\n\nRegression proof: each behavior test fails with its fix reverted;\ncargo test -p grove-core 180 passed; both shell crates compile.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): contain PTY thread panics, recover poisoned locks, cap co…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:24:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "684dfe25119303e3943f964abaaf58a625a7f241",
          "body": "Adds a test-core job (tmux installed so the real tmux session paths run;\nthey self-skip where tmux is absent) alongside the existing lint+vitest job.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(grove): run grove-core Rust tests in CI",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:24:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f8a7a6cf692a42cb7dfc0ca1bbd1ed1e5e68ab30",
          "body": "The file viewer's Open in Browser action now opens a grove browser tab\npointed at the file:// URL instead of the default browser (which stays\nas the fallback when no tab session exists). Allow the file scheme in\nthe Tauri/Electron webview URL guards and in address-bar normalization;\nfile tabs are titled by file name.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): open html previews in the internal browser tab",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:21:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9829c7684cefa48d750485f2d6ca534a378ba9bb",
          "body": "…e bar\n\nOn Electron windowDragRegionProps is a style prop ({ WebkitAppRegion:\n\"drag\" }), so spreading it after style={{ height: 38 }} replaced the\ninline style and collapsed the title bar to its content height (~22px),\npushing the header content out of line with the traffic lights. Move the\nheight into the className so the drag style can't clobber it. Tauri uses\na data attribute, so its rendering is unchanged.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): stop electron drag-region spread from collapsing the titl…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T06:18:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "60e12435d1ee90d310755119db0cd7b2536dcba4",
          "body": "…l open-in-browser\n\n- Remove the Expand All toolbar button (Collapse All + Refresh remain;\n  the deep-listing backend and store action stay for future use)\n- Shrink file browser and file/image viewer icons one step\n- Reduce file viewer header name/path font sizes slightly\n- Add an Open in Browser action for .html/.htm/.xhtml files (file:// via\n  the default browser)\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): file browser polish — drop expand-all, shrink icons, htm…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T05:55:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9487bab7a96d14b6af805efe68abc65928f1c790",
          "body": "Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(grove): warn that the vite dev server is GROVE_TARGET-locked",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T05:43:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9ac47b3ba34b7b96c526f944bac6cf8f096591b4",
          "body": "…r tabs\n\nPorts orca's browser context menu to grove's native-webview browser tabs.\nBecause browser content is a native layer painted over the DOM (WebContentsView\non Electron, child Webview on Tauri), a renderer/React menu would render under\nthe page — so both platforms build the menu natively in th\n[…]\nback over a denied\n  grovemenu:// navigation parsed in on_navigation. Reuses the existing detached\n  WKWebView _inspector hack for Inspect Page.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): add right-click context menu with Inspect Page to browse…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T05:38:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ad1a031c85ea939835002fe415410a843318bf7d",
          "body": "…ens in-app\n\nTab sessions were keyed strictly by worktreePath, so selecting a mission\nroot (terminal path, no worktree) left tab switching dead and made the\nfile viewer fall back to opening files externally. Key the tab scope by\nworktreePath ?? terminalPath, matching how terminal sessions already\nscope to mission roots.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): give mission roots working tab sessions so file viewer op…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T05:32:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "12f6e14951aeab806230f4288a938be497ff229f",
          "body": "…ll, and refresh\n\n- File viewer tab: read-only virtualized code view with lazy shiki\n  highlighting (github-light/dark, 1M-char/20k-line caps), word wrap\n  toggle, line-number gutter, binary/too-large placeholders\n- Image viewer tab: base64-over-IPC preview with fit/1:1/zoom controls,\n  ctrl+wheel z\n[…]\npanel mode switches\n- Backend: read_workspace_file command with NUL-probe binary detection,\n  10MB text / 20MB image caps, path traversal guards\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(grove): upgrade file browser with viewer tabs, expand/collapse a…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T05:23:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2131e3a52ab6545b0c68e87fc2536e91c5905bf1",
          "body": "…ntal trembling\n\nThe PTY hold removed the vertical redraw tremble, but mid-drag stability-cap\nfits that changed cols still re-wrapped the entire scrollback locally, which\nreads as left-right trembling. While a resize hold is active, defer any fit\nwhose proposed cols differ from the current grid to t\n[…]\nut sync, so the drag ends with a single reflow and a\nsingle PTY resize. Rows-only fits stay live mid-drag — they never reflow\ntext horizontally.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): defer cols-changing fits during sash drags to stop horizo…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T04:36:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5d965aba2bc81bd817e72c5c6b82266c498ea72e",
          "body": "…ling\n\nThe fit-stability loop removed per-frame flicker, but mid-drag fits still\nstreamed SIGWINCH into the PTY, making TUIs (Claude Code, Codex) redraw-\nthrash — visible as trembling while dragging a divider. Port orca's\npane-pty-resize-hold:\n\n- holdPanePtyResizes(): depth-counted per-runtime hold;\n[…]\nl panes)\n- adopt orca's 1-row bottom tolerance (isViewportAtBottom) so a fit\n  sampled a hair behind baseY doesn't misread as reading scrollback\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(grove): hold PTY resizes during sash drags to stop terminal tremb…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T04:29:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2856497cf17e99ae501485776347f8c5038adb1f",
          "body": "Port orca's fit-stability + viewport-preservation resize architecture:\n\n- Apply a proposed grid only after it holds for 2 consecutive frames\n  (8-frame cap so continuous drags still track), instead of running\n  FitAddon.fit()'s renderer clear + scrollback reflow every frame\n- Skip fit entirely when \n[…]\nows the\n  theme background instead of xterm.css's opaque #000\n- Document the pipeline + manual regression checklist in\n  docs/terminal-resize.md\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(grove): eliminate terminal resize flicker with fit-stability loop",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T04:08:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bfc17c5924ee1a7a41fb37c9114b4c05b2225ff9",
          "body": null,
          "is_bot": false,
          "headline": "chore: add staged-only pre-commit hook (secretlint/oxlint/oxfmt)",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T03:13:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "77bc2db8d8381f41858f405bddee0982d368d05a",
          "body": null,
          "is_bot": false,
          "headline": "style: apply oxfmt baseline",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T03:10:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80e58a969a9132deb7b17642af7a1b24c391b121",
          "body": null,
          "is_bot": false,
          "headline": "chore(grove): replace eslint with oxlint",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T03:09:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "666e857699941d210051b7f38e8484973381ac7a",
          "body": "…rminal resize work",
          "is_bot": false,
          "headline": "perf(grove): coalesce PTY output, drop base64 transport, and scope te…",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-11T03:01:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "10c6d05e52633c49975e0d9d2802db3a626b6cbe",
          "body": null,
          "is_bot": true,
          "headline": "chore: update plugin versions to v2.16.11",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-10T05:48:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03f1f19b03b319f15c8cf2090485d72faf405610",
          "body": null,
          "is_bot": false,
          "headline": "fix(whip): show dates for distant usage resets",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-10T05:45:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "95ca2c3f345cff89479954a1ffc86dacc5185e79",
          "body": null,
          "is_bot": true,
          "headline": "chore: update plugin versions to v2.16.10",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-10T05:08:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9fd2a45a43adc5363a792954da007f0c91f2cd7f",
          "body": null,
          "is_bot": false,
          "headline": "fix(whip): track Codex spend limits and GPT-5.6 pricing",
          "author_name": "bang9",
          "author_login": "bang9",
          "committed_at": "2026-07-10T03:02:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 100,
      "commits_last_year": 1068,
      "latest_release_at": "2026-07-11T17:23:44Z",
      "latest_release_tag": "v2.17.1",
      "releases_from_tags": false,
      "days_since_last_push": 11,
      "active_weeks_last_year": 20,
      "days_since_latest_release": 15,
      "mean_days_between_releases": 8.8
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/bang9/ai-tools",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/bang9/ai-tools",
          "is_deprecated": false,
          "latest_version": "v2.17.1+incompatible",
          "repository_url": "https://github.com/bang9/ai-tools",
          "versions_count": 114,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-11T17:23:19Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 15
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 10,
      "watchers": 0,
      "fork_history": {
        "days": [
          {
            "date": "2026-03-26",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 2
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": true,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "claude-irc/Makefile",
        "pipemd/Makefile",
        "redit/Makefile",
        "rewind/Makefile",
        "vaultkey/Makefile",
        "webform/Makefile",
        "whip/Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "grove/tsconfig.json",
        "rewind/web/tsconfig.json",
        "whip/dashboard-web/tsconfig.json"
      ],
      "toolchain_manifests": [
        "claude-irc/go.mod",
        "grove/Cargo.toml",
        "grove/grove-agent/Cargo.toml",
        "grove/grove-core/Cargo.toml",
        "grove/grove-daemon/Cargo.toml",
        "grove/src-electron/native/Cargo.toml",
        "grove/src-tauri/Cargo.toml",
        "pipemd/go.mod",
        "redit/go.mod",
        "rewind/go.mod",
        "shared/irclib/go.mod",
        "shared/upgrade/go.mod",
        "vaultkey/go.mod",
        "webform/go.mod",
        "whip/go.mod"
      ],
      "largest_source_bytes": 156492,
      "source_files_sampled": 586,
      "oversized_source_files": 6,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md",
        "claude-irc/AGENTS.md",
        "claude-irc/CLAUDE.md",
        "grove/AGENTS.md",
        "grove/CLAUDE.md",
        "pipemd/AGENTS.md",
        "pipemd/CLAUDE.md",
        "redit/AGENTS.md",
        "redit/CLAUDE.md",
        "rewind/AGENTS.md",
        "rewind/CLAUDE.md",
        "vaultkey/AGENTS.md",
        "vaultkey/CLAUDE.md",
        "webform/AGENTS.md",
        "webform/CLAUDE.md",
        "whip/AGENTS.md",
        "whip/CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 11585
    },
    "dependencies": {
      "manifests": [
        "claude-irc/go.mod",
        "grove/Cargo.toml",
        "grove/package.json",
        "pipemd/go.mod",
        "redit/go.mod",
        "rewind/go.mod",
        "vaultkey/go.mod",
        "webform/go.mod",
        "whip/go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "crates",
        "go",
        "npm"
      ],
      "dependencies": [
        {
          "name": "github.com/bang9/ai-tools/shared/irclib",
          "manifest": "claude-irc/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0"
        },
        {
          "name": "github.com/bang9/ai-tools/shared/upgrade",
          "manifest": "claude-irc/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "claude-irc/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "@dnd-kit/core",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^6.3.1"
        },
        {
          "name": "@dnd-kit/modifiers",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^9.0.0"
        },
        {
          "name": "@dnd-kit/sortable",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.0.0"
        },
        {
          "name": "@dnd-kit/utilities",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.2.2"
        },
        {
          "name": "@radix-ui/react-context-menu",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.2.16"
        },
        {
          "name": "@radix-ui/react-dialog",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.15"
        },
        {
          "name": "@radix-ui/react-popover",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.15"
        },
        {
          "name": "@radix-ui/react-separator",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.1.8"
        },
        {
          "name": "@radix-ui/react-slot",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.4"
        },
        {
          "name": "@radix-ui/react-toast",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.15"
        },
        {
          "name": "@radix-ui/react-tooltip",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.8"
        },
        {
          "name": "@tanstack/react-virtual",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "3.13.24"
        },
        {
          "name": "@tauri-apps/api",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2"
        },
        {
          "name": "@tauri-apps/plugin-process",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.3.1"
        },
        {
          "name": "@tauri-apps/plugin-updater",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.10.0"
        },
        {
          "name": "@xterm/addon-fit",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "0.12.0-beta.289"
        },
        {
          "name": "@xterm/addon-search",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "0.17.0-beta.289"
        },
        {
          "name": "@xterm/addon-unicode11",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "0.10.0-beta.289"
        },
        {
          "name": "@xterm/addon-web-links",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "0.13.0-beta.289"
        },
        {
          "name": "@xterm/addon-webgl",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "0.20.0-beta.288"
        },
        {
          "name": "@xterm/xterm",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "6.1.0-beta.289"
        },
        {
          "name": "allotment",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1"
        },
        {
          "name": "class-variance-authority",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.7.1"
        },
        {
          "name": "clsx",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.1"
        },
        {
          "name": "lucide-react",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.577.0"
        },
        {
          "name": "react",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19"
        },
        {
          "name": "react-dom",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19"
        },
        {
          "name": "shiki",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.3.1"
        },
        {
          "name": "tailwind-merge",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.5.0"
        },
        {
          "name": "zustand",
          "manifest": "grove/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5"
        },
        {
          "name": "github.com/alecthomas/chroma/v2",
          "manifest": "pipemd/go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.20.0"
        },
        {
          "name": "github.com/bang9/ai-tools/shared/upgrade",
          "manifest": "pipemd/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0"
        },
        {
          "name": "github.com/mattn/go-runewidth",
          "manifest": "pipemd/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.16"
        },
        {
          "name": "github.com/yuin/goldmark",
          "manifest": "pipemd/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.7.16"
        },
        {
          "name": "golang.org/x/term",
          "manifest": "pipemd/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.30.0"
        },
        {
          "name": "github.com/bang9/ai-tools/shared/upgrade",
          "manifest": "redit/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0"
        },
        {
          "name": "github.com/bang9/ai-tools/shared/upgrade",
          "manifest": "rewind/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0"
        },
        {
          "name": "github.com/charmbracelet/bubbles",
          "manifest": "rewind/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.0"
        },
        {
          "name": "github.com/charmbracelet/bubbletea",
          "manifest": "rewind/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.3.10"
        },
        {
          "name": "github.com/charmbracelet/lipgloss",
          "manifest": "rewind/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.0"
        },
        {
          "name": "github.com/tdewolff/minify/v2",
          "manifest": "rewind/go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.24.10"
        },
        {
          "name": "github.com/bang9/ai-tools/shared/upgrade",
          "manifest": "vaultkey/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "vaultkey/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.9.1"
        },
        {
          "name": "golang.org/x/crypto",
          "manifest": "vaultkey/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.48.0"
        },
        {
          "name": "golang.org/x/term",
          "manifest": "vaultkey/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.40.0"
        },
        {
          "name": "github.com/bang9/ai-tools/shared/upgrade",
          "manifest": "webform/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0"
        },
        {
          "name": "github.com/bang9/ai-tools/shared/irclib",
          "manifest": "whip/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0"
        },
        {
          "name": "github.com/bang9/ai-tools/shared/upgrade",
          "manifest": "whip/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.0"
        },
        {
          "name": "github.com/charmbracelet/bubbletea",
          "manifest": "whip/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.3.4"
        },
        {
          "name": "github.com/charmbracelet/lipgloss",
          "manifest": "whip/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.0"
        },
        {
          "name": "github.com/charmbracelet/x/ansi",
          "manifest": "whip/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.8.0"
        },
        {
          "name": "github.com/google/uuid",
          "manifest": "whip/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.0"
        },
        {
          "name": "github.com/mdp/qrterminal/v3",
          "manifest": "whip/go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.2.1"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "whip/go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "golang.org/x/term",
          "manifest": "whip/go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.40.0"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 26,
        "open_issues": 2,
        "closed_ratio": 0.931,
        "closed_issues": 27,
        "closed_unmerged_prs": 3
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "bang9",
          "commits": 963,
          "avatar_url": "https://avatars.githubusercontent.com/u/26326015?v=4"
        },
        {
          "type": "User",
          "login": "DongGukMon",
          "commits": 16,
          "avatar_url": "https://avatars.githubusercontent.com/u/30457954?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.984
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "cc-marketplace-release.yml",
        "claude-irc-release.yml",
        "claude-irc-test.yml",
        "grove-release.yml",
        "grove-test.yml",
        "pipemd-release.yml",
        "pipemd-test.yml",
        "redit-release.yml",
        "redit-test.yml",
        "release.yml",
        "rewind-release.yml",
        "rewind-test.yml",
        "scripts-check.yml",
        "shared-test.yml",
        "vaultkey-action-test.yml",
        "vaultkey-release.yml",
        "vaultkey-test.yml",
        "webform-release.yml",
        "webform-test.yml",
        "whip-release.yml",
        "whip-test.yml",
        "whip-web-deploy.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "Cargo.lock",
        "go.sum",
        "pnpm-lock.yaml"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 3 contributing companies or organizations -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 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": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 8,
            "reason": "5 out of the last 5 releases have a total of 5 signed artifacts.",
            "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": 0,
            "reason": "140 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "23a780750dbd2faf797094538f725b29ed2cc1de",
        "ran_at": "2026-07-27T05:41:05Z",
        "aggregate_score": 3.7,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-16T01:20:31Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-06-22T07:45:15Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 42,
          "created_at": "2026-03-16T02:17:32Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 53,
          "created_at": "2026-03-25T02:38:53Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/bang9/ai-tools",
    "host": "github.com",
    "name": "ai-tools",
    "owner": "bang9"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 58,
      "inputs": {
        "security": 37,
        "vitality": 82,
        "community": 32,
        "governance": 62,
        "engineering": 66
      },
      "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": 71,
            "inputs": {
              "commits_last_year": 1068,
              "human_commit_share": 0.96,
              "days_since_last_push": 11,
              "active_weeks_last_year": 20
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 11 days ago",
                "points": 28.8,
                "status": "partial",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 11
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "20/52 weeks with commits",
                "points": 13.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 20
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "1068 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1068
                    }
                  }
                ],
                "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": 98,
            "inputs": {
              "releases_count": 100,
              "latest_release_tag": "v2.17.1",
              "releases_from_tags": false,
              "days_since_latest_release": 15,
              "mean_days_between_releases": 8.8
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "100 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 15 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 15
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~8.8 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 8.8
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "5 out of the last 5 releases have a total of 5 signed artifacts.",
                "points": 8,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 32,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 16,
            "inputs": {
              "forks": 1,
              "stars": 10,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "10 stars",
                "points": 15.5,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 10
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "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": 62,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 22,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.984
            },
            "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 98% of commits",
                "points": 0.4,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 98
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "2 contributors",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 78,
            "inputs": {
              "merged_prs": 26,
              "open_issues": 2,
              "closed_issues": 27,
              "issue_closed_ratio": 0.931,
              "closed_unmerged_prs": 3
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "93% of issues closed",
                "points": 43.5,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 93
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "26/29 decided PRs merged",
                "points": 34.3,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 26,
                      "decided": 29
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 63,
            "inputs": {
              "followers": 142,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "bang9",
              "public_repos": 106,
              "account_age_days": 3425
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "142 followers of bang9",
                "points": 15.5,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 142,
                      "login": "bang9"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "106 public repos, account ~9 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 106
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 9
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/bang9/ai-tools"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 15
            },
            "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 15 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 15
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "114 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 114
                    }
                  }
                ],
                "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": "moderate",
        "name": "Engineering Quality",
        "value": 66,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "22 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 22
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [
                "ai-agent",
                "claude-code",
                "codex",
                "task-manager",
                "task-orchestration"
              ],
              "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": "5 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "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": "at_risk",
        "name": "Security",
        "value": 37,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "packaging"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 37,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 3.7
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "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 not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "5 out of the last 5 releases have a total of 5 signed artifacts.",
                "points": 6,
                "status": "partial",
                "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": "140 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 3
            },
            "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": 86,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "has_llms_txt": true,
              "legible_history_share": 0.99,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md",
                "claude-irc/AGENTS.md",
                "claude-irc/CLAUDE.md",
                "grove/AGENTS.md",
                "grove/CLAUDE.md",
                "pipemd/AGENTS.md",
                "pipemd/CLAUDE.md",
                "redit/AGENTS.md",
                "redit/CLAUDE.md",
                "rewind/AGENTS.md",
                "rewind/CLAUDE.md",
                "vaultkey/AGENTS.md",
                "vaultkey/CLAUDE.md",
                "webform/AGENTS.md",
                "webform/CLAUDE.md",
                "whip/AGENTS.md",
                "whip/CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 11585
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md, claude-irc/AGENTS.md, claude-irc/CLAUDE.md, grove/AGENTS.md, grove/CLAUDE.md, pipemd/AGENTS.md, pipemd/CLAUDE.md, redit/AGENTS.md, redit/CLAUDE.md, rewind/AGENTS.md, rewind/CLAUDE.md, vaultkey/AGENTS.md, vaultkey/CLAUDE.md, webform/AGENTS.md, webform/CLAUDE.md, whip/AGENTS.md, whip/CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md, claude-irc/AGENTS.md, claude-irc/CLAUDE.md, grove/AGENTS.md, grove/CLAUDE.md, pipemd/AGENTS.md, pipemd/CLAUDE.md, redit/AGENTS.md, redit/CLAUDE.md, rewind/AGENTS.md, rewind/CLAUDE.md, vaultkey/AGENTS.md, vaultkey/CLAUDE.md, webform/AGENTS.md, webform/CLAUDE.md, whip/AGENTS.md, whip/CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": "llms.txt present",
                "points": 15,
                "status": "met",
                "details": [
                  {
                    "code": "llms_txt_present",
                    "params": {}
                  }
                ],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "95 of 96 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 95,
                      "sampled": 96
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 71,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "Cargo.lock",
                "go.sum",
                "pnpm-lock.yaml"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "claude-irc/Makefile",
                "pipemd/Makefile",
                "redit/Makefile",
                "rewind/Makefile",
                "vaultkey/Makefile",
                "webform/Makefile",
                "whip/Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "grove/tsconfig.json",
                "rewind/web/tsconfig.json",
                "whip/dashboard-web/tsconfig.json"
              ],
              "agent_commit_share": 0.83,
              "toolchain_manifests": [
                "claude-irc/go.mod",
                "grove/Cargo.toml",
                "grove/grove-agent/Cargo.toml",
                "grove/grove-core/Cargo.toml",
                "grove/grove-daemon/Cargo.toml",
                "grove/src-electron/native/Cargo.toml",
                "grove/src-tauri/Cargo.toml",
                "pipemd/go.mod",
                "redit/go.mod",
                "rewind/go.mod",
                "shared/irclib/go.mod",
                "shared/upgrade/go.mod",
                "vaultkey/go.mod",
                "webform/go.mod",
                "whip/go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "claude-irc/Makefile, pipemd/Makefile, redit/Makefile, rewind/Makefile, vaultkey/Makefile, webform/Makefile, whip/Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "claude-irc/Makefile, pipemd/Makefile, redit/Makefile, rewind/Makefile, vaultkey/Makefile, webform/Makefile, whip/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": "grove/tsconfig.json, rewind/web/tsconfig.json, whip/dashboard-web/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "grove/tsconfig.json, rewind/web/tsconfig.json, whip/dashboard-web/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "83 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 83,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 99,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 156492,
              "source_files_sampled": 586,
              "oversized_source_files": 6
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "6/586 source files over 60KB",
                "points": 54.4,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 586,
                      "oversized": 6
                    }
                  }
                ],
                "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",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-27T05:41:12.856502Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/b/bang9/ai-tools.svg",
  "full_name": "bang9/ai-tools",
  "license_state": "standard",
  "license_spdx": "MIT"
}

Scores are signals, not warranties. They reflect publicly visible practices on GitHub — not a code audit, and not a security guarantee.

Missing data is excluded and weights renormalized, never scored as zero. Methodology is versioned and open: metrics v1.13.0, schema v0.27.0 — full methodology · metrics wiki.

How one result sits in the wider record: aggregate statisticsGo.