公开记录
软件健康报告模式 0.26.0 · 指标 1.13.0 · 2026-07-22 09:31 UTC

genai-io / san

A minimal, fast agent harness for the terminal. One ~12 MB native binary that runs anywhere, with an open, extensible architecture.

GoApache-2.0★ 70 星标⑂ 32 复刻始于 2024年9月在 GitHub 上查看 ↗

genai-io/san 的健康指数为 100 分中的 73 分,处于「良好」区间。 其得分最高的类别是Vitality(86/100),最低的是Sustainability & Governance(63/100)。 最近一次更新在今天。 近期的大部分工作由 1 位贡献者完成。

73
总分 / 100
良好

软件健康指数

指标归入加权类别,统一采用 1–100 量表。总体分先取类别加权平均;当公开证据触发高风险司法辖区政策时,评级会按政策调整,并设置 49(有风险)的上限。AI 就绪度不计入总体分。

73
优秀85-100堪称典范;基本满足所有检验标准
良好70-84健康;仅有轻微不足
中等50-69可接受,但存在明显不足;建议进行审查
存在风险30-49存在重大薄弱环节;采用时应保持审慎
危急1-29问题严重(项目被弃置、仅有单一维护者、缺乏基本工程规范)
活力社区与采用可持续性与治理工程质量安全AI 就绪度

评分画像

每条轴代表一个类别。形状比平均值更重要——健康的对象会填满整个图形,而“一峰一谷”式画像意味着某一维度的优势正掩盖另一维度的风险。

所有权

GenAI Lab组织
6 关注者13 个公开仓库始于 2026年5月

该仓库由组织支持——共同承担、可问责的托管责任,可延续于任何单一维护者之后。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
Gogithub.com/genai-io/sanv1.21.11-1230 天前

按类别列示的指标

活力

项目是否仍有生命——是否仍在编写代码,是否仍在发布版本?

86优秀 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 0 天前
19.4/36提交节奏 — 52 周中有 28 周有提交
18/18提交量 — 最近一年 979 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 24 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year979
human_commit_share0.98
days_since_last_push0
active_weeks_last_year28

发布纪律

90优秀
评分方式
27/27有发布版本 — 已发布 100 个发布版本
36/36发布时效 — 最近一次发布版本于 0 天前
27/27发布节奏 — 约每 1.3 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — Project has not signed or included provenance with any releases.
所用输入
releases_count100
latest_release_tagv1.21.11
releases_from_tags
days_since_latest_release0
mean_days_between_releases1.3

社区与采用

项目是否拥有用户、下载量与关注度,并具备欢迎贡献者参与的配置?

66中等 · 占总体的 18%

流行度与采用

44存在风险
评分方式
29.8/60星标 — 70 个星标
12.4/25复刻 — 32 个复刻
1.7/15关注者 — 3 位关注者
所用输入
forks32
stars70
watchers3
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonbelow_threshold

社区健康

92优秀
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(Apache-2.0)
18/18CONTRIBUTING 指南
13.5/13.5行为准则
0/7.2议题模板
6.3/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template

可持续性与治理

项目能否在其成员之外延续——巴士系数、响应能力、由谁支持,以及软件包的维护状况?

63中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
1.5/22.5提交分布 — 头号贡献者编写了 93% 的提交
13.5/13.5贡献者广度 — 13 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 5 contributing companies or organizations
所用输入
bus_factor1
contributors_sampled13
top_contributor_share0.934
评分方式
38.1/46.8议题解决 — 81% 的议题已关闭
34.2/38.3PR 接受 — 已裁定的 PR 中 296/331 已合并
15/15OpenSSF Scorecard:Code-Review — all changesets reviewed
所用输入
merged_prs296
open_issues8
closed_issues35
issue_closed_ratio0.814
closed_unmerged_prs35
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
6.1/25所有者影响力 — genai-io 有 6 位关注者
8.8/25既往记录 — 13 个公开仓库,账户约 0 年
所用输入
followers6
owner_typeOrganization
is_verified
owner_logingenai-io
public_repos13
account_age_days82
评分方式
25/25已发布且可解析 — go 上有 1 个软件包
35/35发布时效 — 最近一次发布于 0 天前
20/20版本历史 — 123 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesgithub.com/genai-io/san
ecosystemsgo
any_deprecated
min_days_since_publish0

工程质量

基础的工程与文档实践是否到位?

81良好 · 占总体的 20%

工程实践

68中等
评分方式
24/24CI 工作流 — 4 个工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
0/6.4.editorconfig
20/20OpenSSF Scorecard:CI-Tests — 28 out of 28 merged PRs checked by a CI test -- score normalized to 10
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config

文档

100优秀
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://genai-io.github.io/san/
10/10仓库描述
10/10主题标签 — 11 个主题标签
10/10Wiki
所用输入
topicsai-agents, provider-agnostic, llm, coding-agent, agent-harness, claude-code, cli, golang, mcp, terminal, tui
has_wiki
homepagehttps://genai-io.github.io/san/
has_readme
has_docs_dir
has_description

安全

可见的安全与供应链实践是否稳固,且不存在未解决的高风险司法辖区暴露?

66中等 · 占总体的 16%

安全态势

58中等
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — 无数据
2.5/2.5CI-Tests — 28 out of 28 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
7.5/7.5Code-Review — all changesets reviewed
2.5/2.5Contributors — project has 5 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 24 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — 无数据
1.5/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 3
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 31 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate5.8
已排除计分(无数据或不适用):branch_protection, packaging。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
0/25间接依赖不含已知公告 — 在此范围内,传递依赖集合无法与开发和测试依赖区分
0/40没有长期未处理的公告 — 没有公告带有发布日期
所用输入
sourceosv
advisories48
affected_packages5
assessed_packages78
unassessed_packages0
affected_by_severitycritical 2, moderate 1, unknown 2
direct_affected_packages0
已排除计分(无数据或不适用):间接依赖不含已知公告, 没有长期未处理的公告。 其余权重已重新归一化。 已将 78 个已解析依赖与 OSV 比对。 该仓库未发布任何索引可解析的软件包,因此改为评估仓库依赖图。该图将开发与测试版本固定同交付的依赖混在一起,因此仅对声明的运行时依赖计分;传递性发现仅作为背景信息列出,不计入评分。 未对可达性进行分析。

AI 就绪度

该仓库在多大程度上具备与 AI 编码代理协同开发与维护的条件?这是一枚独立的实验性徽章——权重为 0.0,因此单独呈现,不影响总体健康评分。

86优秀 · 占总体的 0%
评分方式
45/45代理指令 — AGENTS.md, docs/packages/2-feature/agent.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 98 次人类提交中有 98 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share1
agent_instruction_filesAGENTS.md, docs/packages/2-feature/agent.md
agent_instruction_max_bytes3,518
评分方式
18/18一条命令的引导启动 — Makefile
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — Go(静态类型)
10/10可复现环境 — lockfile
10/10已体现的代理实践 — 最近 100 次提交中有 5 次由代理编写或署名代理
8/8自动化维护 — 最近 100 次提交中有 2 次为自动依赖更新
3/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 3
所用输入
has_nix
has_tests
lockfilesgo.sum
has_dockerfile
typed_language
bootstrap_filesMakefile
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0.05
toolchain_manifestsgo.mod
dependency_bot_commit_share0.02
评分方式
45/45可类型检查的代码 — Go(静态类型)
55/55可控的文件大小 — 采样的 622 个源文件中有 0 个超过 60KB
所用输入
primary_languageGo
largest_source_bytes49,529
source_files_sampled622
oversized_source_files0

关键数据

70GitHub 星标
13贡献者
979最近 12 个月提交数
0距最近推送天数
100发布版本数
1巴士系数(bus factor)
8开放议题
Go软件包生态系统数

更多细节

Star 与 Fork 历史 70 ★ / 32 ⇿
70Star
32Fork
97发布

每颗 star 和每个 fork 的添加时间,来自 GitHub 并按天汇总。累计增长位于其构成来源——每日新增——的正上方,二者可相互对照:稳定的自然增长与短暂的突增形态截然不同。当这一差别可被衡量时,它会作为增长真实性予以报告。

01325385063757032142024-112025-092026-07
主版本 0次版本 15修订 82

每个点涵盖 2 天。

OpenSSF Scorecard 5.8 / 10
5.8综合

来自开源项目 OpenSSF Scorecard 的独立、工具无关的安全评估。每项检查奖励的是安全实践本身,而非特定供应商的工具。Scorecard 无法判定的检查项标记为 不适用,并从安全评分中剔除(绝不按零分计)。Scorecard v5.5.0 · 2026-07-22 09:31 UTC

10Binary-Artifactsno binaries found in the repo
不适用Branch-Protectioninternal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md
10CI-Tests28 out of 28 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
10Code-Reviewall changesets reviewed
10Contributorsproject has 5 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 24 issue activity found in the last 90 days -- score normalized to 10
不适用Packagingpackaging workflow not detected
3Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 3
0SASTSAST tool is not run on all commits -- score normalized to 0
10Security-Policysecurity policy file detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities31 existing vulnerabilities detected
直接依赖 21
注册表软件包版本约束清单文件
Gocharm.land/bubbles/v2v2.1.0go.mod
Gocharm.land/bubbletea/v2v2.0.7go.mod
Gocharm.land/glamour/v2v2.0.1go.mod
Gocharm.land/lipgloss/v2v2.0.4go.mod
Gogithub.com/JohannesKaufmann/html-to-markdownv1.6.0go.mod
Gogithub.com/PuerkitoBio/goqueryv1.9.2go.mod
Gogithub.com/anthropics/anthropic-sdk-gov1.27.1go.mod
Gogithub.com/bmatcuk/doublestar/v4v4.9.2go.mod
Gogithub.com/charmbracelet/x/ansiv0.11.7go.mod
Gogithub.com/creack/ptyv1.1.24go.mod
Gogithub.com/hexops/gotextdiffv1.0.3go.mod
Gogithub.com/joho/godotenvv1.5.1go.mod
Gogithub.com/mattn/go-runewidthv0.0.23go.mod
Gogithub.com/openai/openai-go/v3v3.32.0go.mod
Gogithub.com/spf13/cobrav1.8.1go.mod
Gogo.uber.org/zapv1.27.0go.mod
Gogolang.org/x/termv0.40.0go.mod
Gogoogle.golang.org/genaiv1.58.0go.mod
Gogopkg.in/natefinch/lumberjack.v2v2.2.1go.mod
Gogopkg.in/yaml.v3v3.0.1go.mod
Gomvdan.cc/sh/v3v3.13.0go.mod
全部依赖 78

来自 GitHub 依赖图的完整解析依赖集合:21 个直接依赖与 57 个间接(传递)软件包。仓库提交锁文件时,传递闭包才是完整的。

注册表软件包版本关系
Gocharm.land/bubbles/v2v2.1.0直接
Gocharm.land/bubbletea/v2v2.0.7直接
Gocharm.land/glamour/v2v2.0.1直接
Gocharm.land/lipgloss/v2v2.0.4直接
Gogithub.com/anthropics/anthropic-sdk-gov1.27.1直接
Gogithub.com/bmatcuk/doublestar/v4v4.9.2直接
Gogithub.com/charmbracelet/x/ansiv0.11.7直接
Gogithub.com/creack/ptyv1.1.24直接
Gogithub.com/hexops/gotextdiffv1.0.3直接
Gogithub.com/johanneskaufmann/html-to-markdownv1.6.0直接
Gogithub.com/joho/godotenvv1.5.1直接
Gogithub.com/mattn/go-runewidthv0.0.23直接
Gogithub.com/openai/openai-go/v3v3.32.0直接
Gogithub.com/puerkitobio/goqueryv1.9.2直接
Gogithub.com/spf13/cobrav1.8.1直接
Gogo.uber.org/zapv1.27.0直接
Gogolang.org/x/termv0.40.0直接
Gogoogle.golang.org/genaiv1.58.0直接
Gogopkg.in/natefinch/lumberjack.v2v2.2.1直接
Gogopkg.in/yaml.v3v3.0.1直接
Gomvdan.cc/sh/v3v3.13.0直接
Gocloud.google.com/gov0.116.0间接
Gocloud.google.com/go/authv0.9.3间接
Gocloud.google.com/go/auth/oauth2adaptv0.2.4间接
Gocloud.google.com/go/compute/metadatav0.5.0间接
Gogithub.com/alecthomas/chroma/v2v2.20.0间接
Gogithub.com/andybalholm/cascadiav1.3.2间接
Gogithub.com/atotto/clipboardv0.1.4间接
Gogithub.com/aymerick/douceurv0.2.0间接
Gogithub.com/charmbracelet/colorprofilev0.4.3间接
Gogithub.com/charmbracelet/ultravioletv0.0.0-20260525132238-948f4557a654间接
Gogithub.com/charmbracelet/x/exp/slicev0.0.0-20250327172914-2fdc97757edf间接
Gogithub.com/charmbracelet/x/termv0.2.2间接
Gogithub.com/charmbracelet/x/termiosv0.1.1间接
Gogithub.com/charmbracelet/x/windowsv0.2.2间接
Gogithub.com/clipperhouse/displaywidthv0.11.0间接
Gogithub.com/clipperhouse/uax29/v2v2.7.0间接
Gogithub.com/dlclark/regexp2v1.11.5间接
Gogithub.com/felixge/httpsnoopv1.0.4间接
Gogithub.com/go-logr/logrv1.4.2间接
Gogithub.com/go-logr/stdrv1.2.2间接
Gogithub.com/golang/groupcachev0.0.0-20210331224755-41bb18bfe9da间接
Gogithub.com/google/go-cmpv0.7.0间接
Gogithub.com/google/s2a-gov0.1.8间接
Gogithub.com/googleapis/enterprise-certificate-proxyv0.3.4间接
Gogithub.com/gorilla/cssv1.0.1间接
Gogithub.com/gorilla/websocketv1.5.3间接
Gogithub.com/inconshreveable/mousetrapv1.1.0间接
Gogithub.com/lucasb-eyer/go-colorfulv1.4.0间接
Gogithub.com/microcosm-cc/bluemondayv1.0.27间接
Gogithub.com/muesli/cancelreaderv0.2.2间接
Gogithub.com/rivo/unisegv0.4.7间接
Gogithub.com/spf13/pflagv1.0.5间接
Gogithub.com/tidwall/gjsonv1.18.0间接
Gogithub.com/tidwall/matchv1.1.1间接
Gogithub.com/tidwall/prettyv1.2.1间接
Gogithub.com/tidwall/sjsonv1.2.5间接
Gogithub.com/xo/terminfov0.0.0-20220910002029-abceb7e1c41e间接
Gogithub.com/yuin/goldmarkv1.7.13间接
Gogithub.com/yuin/goldmark-emojiv1.0.6间接
Gogo.opencensus.iov0.24.0间接
Gogo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpcv0.54.0间接
Gogo.opentelemetry.io/contrib/instrumentation/net/http/otelhttpv0.54.0间接
Gogo.opentelemetry.io/otelv1.29.0间接
Gogo.opentelemetry.io/otel/metricv1.29.0间接
Gogo.opentelemetry.io/otel/tracev1.29.0间接
Gogo.uber.org/multierrv1.10.0间接
Gogolang.org/x/cryptov0.40.0间接
Gogolang.org/x/netv0.41.0间接
Gogolang.org/x/oauth2v0.30.0间接
Gogolang.org/x/syncv0.20.0间接
Gogolang.org/x/sysv0.45.0间接
Gogolang.org/x/textv0.30.0间接
Gogolang.org/x/timev0.6.0间接
Gogoogle.golang.org/apiv0.197.0间接
Gogoogle.golang.org/genproto/googleapis/rpcv0.0.0-20240903143218-8af14fe29dc1间接
Gogoogle.golang.org/grpcv1.66.2间接
Gogoogle.golang.org/protobufv1.34.2间接
依赖安全公告 5

该仓库未发布可被索引解析的包,因此评估的是其自身的依赖图——共 78 个包,其中也包含从不交付的开发与测试版本固定:5 个存在已知公告,0 个为直接依赖。

软件包版本关系严重程度公告数修复版本
golang.org/x/cryptov0.40.0间接严重320.52.0
google.golang.org/grpcv1.66.2间接严重31.82.1
golang.org/x/netv0.41.0间接111.26.3
github.com/yuin/goldmarkv1.7.13间接未知11.7.17
golang.org/x/textv0.30.0间接未知10.39.0

公告表示依赖图中记录的版本落入某条公告的受影响范围。可达性未经分析,且依赖图包含开发与测试的版本固定——某项发现可能只涉及工具链而非交付的软件。

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "ai-agents",
        "provider-agnostic",
        "llm",
        "coding-agent",
        "agent-harness",
        "claude-code",
        "cli",
        "golang",
        "mcp",
        "terminal",
        "tui"
      ],
      "is_fork": false,
      "size_kb": 30411,
      "has_wiki": true,
      "homepage": "https://genai-io.github.io/san/",
      "languages": {
        "Go": 3685554,
        "CSS": 55107,
        "HTML": 105807,
        "Shell": 5474,
        "Makefile": 5662,
        "JavaScript": 47772,
        "PowerShell": 5198
      },
      "pushed_at": "2026-07-22T09:22:24Z",
      "created_at": "2024-09-05T16:16:25Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-21T15:32:52Z",
      "description": "A minimal, fast agent harness for the terminal. One ~12 MB native binary that runs anywhere, with an open, extensible architecture.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "Apache-2.0",
      "default_branch": "main",
      "license_spdx_raw": "Apache-2.0",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": null,
      "name": "GenAI Lab",
      "type": "Organization",
      "login": "genai-io",
      "company": null,
      "location": null,
      "followers": 6,
      "avatar_url": "https://avatars.githubusercontent.com/u/280842444?v=4",
      "created_at": "2026-05-01T01:06:19Z",
      "is_verified": null,
      "public_repos": 13,
      "account_age_days": 82
    },
    "license": {
      "state": "standard",
      "spdx_id": "Apache-2.0",
      "raw_spdx": "Apache-2.0",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v1.21.11",
          "kind": "patch",
          "published_at": "2026-07-21T16:26:44Z"
        },
        {
          "tag": "v1.21.10",
          "kind": "patch",
          "published_at": "2026-07-20T11:03:08Z"
        },
        {
          "tag": "v1.21.9",
          "kind": "patch",
          "published_at": "2026-07-19T17:33:30Z"
        },
        {
          "tag": "v1.21.8",
          "kind": "patch",
          "published_at": "2026-07-18T17:12:52Z"
        },
        {
          "tag": "v1.21.6",
          "kind": "patch",
          "published_at": "2026-07-17T17:10:04Z"
        },
        {
          "tag": "v1.21.5",
          "kind": "patch",
          "published_at": "2026-07-17T09:54:42Z"
        },
        {
          "tag": "v1.21.4",
          "kind": "patch",
          "published_at": "2026-07-10T18:45:39Z"
        },
        {
          "tag": "v1.21.3",
          "kind": "patch",
          "published_at": "2026-07-10T14:33:44Z"
        },
        {
          "tag": "v1.21.2",
          "kind": "patch",
          "published_at": "2026-07-10T00:30:07Z"
        },
        {
          "tag": "v1.21.1",
          "kind": "patch",
          "published_at": "2026-07-09T18:10:03Z"
        },
        {
          "tag": "v1.21.0",
          "kind": "minor",
          "published_at": "2026-07-09T05:08:46Z"
        },
        {
          "tag": "v1.20.11",
          "kind": "patch",
          "published_at": "2026-07-05T12:20:42Z"
        },
        {
          "tag": "v1.20.10",
          "kind": "patch",
          "published_at": "2026-07-05T03:13:49Z"
        },
        {
          "tag": "v1.20.9",
          "kind": "patch",
          "published_at": "2026-07-03T10:38:10Z"
        },
        {
          "tag": "v1.20.8",
          "kind": "patch",
          "published_at": "2026-07-02T16:33:10Z"
        },
        {
          "tag": "v1.20.7",
          "kind": "patch",
          "published_at": "2026-06-27T16:10:10Z"
        },
        {
          "tag": "v1.20.6",
          "kind": "patch",
          "published_at": "2026-06-18T14:42:01Z"
        },
        {
          "tag": "v1.20.5",
          "kind": "patch",
          "published_at": "2026-06-16T12:39:58Z"
        },
        {
          "tag": "v1.20.4",
          "kind": "patch",
          "published_at": "2026-06-16T11:52:39Z"
        },
        {
          "tag": "v1.20.3",
          "kind": "patch",
          "published_at": "2026-06-15T05:27:59Z"
        },
        {
          "tag": "v1.20.2",
          "kind": "patch",
          "published_at": "2026-06-13T07:54:37Z"
        },
        {
          "tag": "v1.20.1",
          "kind": "patch",
          "published_at": "2026-06-11T15:06:31Z"
        },
        {
          "tag": "v1.20.0",
          "kind": "minor",
          "published_at": "2026-06-05T23:52:34Z"
        },
        {
          "tag": "v1.19.3",
          "kind": "patch",
          "published_at": "2026-06-03T04:53:23Z"
        },
        {
          "tag": "v1.19.2",
          "kind": "patch",
          "published_at": "2026-06-03T03:06:04Z"
        },
        {
          "tag": "v1.19.1",
          "kind": "patch",
          "published_at": "2026-05-23T00:46:46Z"
        },
        {
          "tag": "v1.19.0",
          "kind": "minor",
          "published_at": "2026-05-22T16:58:53Z"
        },
        {
          "tag": "v1.18.0",
          "kind": "minor",
          "published_at": "2026-05-17T14:38:25Z"
        },
        {
          "tag": "v1.17.4",
          "kind": "patch",
          "published_at": "2026-05-06T10:06:27Z"
        },
        {
          "tag": "v1.17.3",
          "kind": "patch",
          "published_at": "2026-05-06T09:11:05Z"
        },
        {
          "tag": "v1.17.2",
          "kind": "patch",
          "published_at": "2026-05-06T08:35:35Z"
        },
        {
          "tag": "v1.17.1",
          "kind": "patch",
          "published_at": "2026-05-05T03:19:03Z"
        },
        {
          "tag": "v1.17.0",
          "kind": "minor",
          "published_at": "2026-05-04T15:01:18Z"
        },
        {
          "tag": "v1.16.0",
          "kind": "minor",
          "published_at": "2026-05-04T08:07:48Z"
        },
        {
          "tag": "v1.15.14",
          "kind": "patch",
          "published_at": "2026-05-02T13:35:26Z"
        },
        {
          "tag": "v0.0.2",
          "kind": "patch",
          "published_at": "2026-05-02T10:35:38Z"
        },
        {
          "tag": "v0.0.1",
          "kind": "patch",
          "published_at": "2026-05-02T10:33:00Z"
        },
        {
          "tag": "v1.15.13",
          "kind": "patch",
          "published_at": "2026-05-02T02:57:20Z"
        },
        {
          "tag": "v1.15.12",
          "kind": "patch",
          "published_at": "2026-05-02T02:02:41Z"
        },
        {
          "tag": "v1.15.11",
          "kind": "patch",
          "published_at": "2026-05-01T06:11:32Z"
        },
        {
          "tag": "v1.15.10",
          "kind": "patch",
          "published_at": "2026-05-01T00:03:50Z"
        },
        {
          "tag": "v1.15.9",
          "kind": "patch",
          "published_at": "2026-04-30T23:49:22Z"
        },
        {
          "tag": "v1.15.8",
          "kind": "patch",
          "published_at": "2026-04-30T16:37:10Z"
        },
        {
          "tag": "v1.15.7",
          "kind": "patch",
          "published_at": "2026-04-30T12:01:28Z"
        },
        {
          "tag": "v1.15.6",
          "kind": "patch",
          "published_at": "2026-04-29T13:52:32Z"
        },
        {
          "tag": "v1.15.5",
          "kind": "patch",
          "published_at": "2026-04-25T23:13:08Z"
        },
        {
          "tag": "v1.15.4",
          "kind": "patch",
          "published_at": "2026-04-25T14:21:37Z"
        },
        {
          "tag": "v1.15.3",
          "kind": "patch",
          "published_at": "2026-04-25T09:37:07Z"
        },
        {
          "tag": "v1.15.2",
          "kind": "patch",
          "published_at": "2026-04-24T02:35:36Z"
        },
        {
          "tag": "v1.15.1",
          "kind": "patch",
          "published_at": "2026-04-24T02:14:28Z"
        },
        {
          "tag": "v1.15.0",
          "kind": "minor",
          "published_at": "2026-04-24T01:45:25Z"
        },
        {
          "tag": "v1.14.9",
          "kind": "patch",
          "published_at": "2026-04-23T15:11:31Z"
        },
        {
          "tag": "v1.14.8",
          "kind": "patch",
          "published_at": "2026-04-23T14:06:48Z"
        },
        {
          "tag": "v1.14.7",
          "kind": "patch",
          "published_at": "2026-04-23T04:52:33Z"
        },
        {
          "tag": "v1.14.6",
          "kind": "patch",
          "published_at": "2026-04-23T04:19:22Z"
        },
        {
          "tag": "v1.14.5",
          "kind": "patch",
          "published_at": "2026-04-22T06:04:44Z"
        },
        {
          "tag": "v1.14.4",
          "kind": "patch",
          "published_at": "2026-04-22T01:30:23Z"
        },
        {
          "tag": "v1.14.3",
          "kind": "patch",
          "published_at": "2026-04-21T12:45:30Z"
        },
        {
          "tag": "v1.14.2",
          "kind": "patch",
          "published_at": "2026-04-21T11:42:19Z"
        },
        {
          "tag": "v1.14.1",
          "kind": "patch",
          "published_at": "2026-04-21T09:04:24Z"
        },
        {
          "tag": "v1.14.0",
          "kind": "minor",
          "published_at": "2026-04-21T08:41:48Z"
        },
        {
          "tag": "v1.13.2",
          "kind": "patch",
          "published_at": "2026-04-14T16:55:39Z"
        },
        {
          "tag": "v1.13.1",
          "kind": "patch",
          "published_at": "2026-04-14T16:37:01Z"
        },
        {
          "tag": "v1.13.0",
          "kind": "minor",
          "published_at": "2026-04-14T15:40:15Z"
        },
        {
          "tag": "v1.12.2",
          "kind": "patch",
          "published_at": "2026-04-14T16:36:57Z"
        },
        {
          "tag": "v1.12.1",
          "kind": "patch",
          "published_at": "2026-04-13T10:14:23Z"
        },
        {
          "tag": "v1.12.0",
          "kind": "minor",
          "published_at": "2026-04-09T14:59:07Z"
        },
        {
          "tag": "v1.11.7",
          "kind": "patch",
          "published_at": "2026-04-08T05:50:36Z"
        },
        {
          "tag": "v1.11.6",
          "kind": "patch",
          "published_at": "2026-04-07T10:47:25Z"
        },
        {
          "tag": "v1.11.5",
          "kind": "patch",
          "published_at": "2026-04-07T05:09:32Z"
        },
        {
          "tag": "v1.11.4",
          "kind": "patch",
          "published_at": "2026-04-07T04:55:04Z"
        },
        {
          "tag": "v1.11.3",
          "kind": "patch",
          "published_at": "2026-04-07T04:01:44Z"
        },
        {
          "tag": "v1.11.2",
          "kind": "patch",
          "published_at": "2026-04-06T15:04:46Z"
        },
        {
          "tag": "v1.11.1",
          "kind": "patch",
          "published_at": "2026-04-06T12:03:44Z"
        },
        {
          "tag": "v1.11.0",
          "kind": "minor",
          "published_at": "2026-04-06T11:39:17Z"
        },
        {
          "tag": "v1.10.3",
          "kind": "patch",
          "published_at": "2026-03-30T10:33:19Z"
        },
        {
          "tag": "v1.10.2",
          "kind": "patch",
          "published_at": "2026-03-25T00:49:17Z"
        },
        {
          "tag": "v1.10.1",
          "kind": "patch",
          "published_at": "2026-03-24T01:42:07Z"
        },
        {
          "tag": "v1.10.0",
          "kind": "minor",
          "published_at": "2026-03-23T11:37:13Z"
        },
        {
          "tag": "v1.9.10",
          "kind": "patch",
          "published_at": "2026-03-16T09:40:32Z"
        },
        {
          "tag": "v1.9.9",
          "kind": "patch",
          "published_at": "2026-03-16T05:44:33Z"
        },
        {
          "tag": "v1.9.8",
          "kind": "patch",
          "published_at": "2026-03-15T18:37:08Z"
        },
        {
          "tag": "v1.9.7",
          "kind": "patch",
          "published_at": "2026-03-15T03:21:26Z"
        },
        {
          "tag": "v1.9.6",
          "kind": "patch",
          "published_at": "2026-03-11T08:04:28Z"
        },
        {
          "tag": "v1.9.5",
          "kind": "patch",
          "published_at": "2026-03-11T04:25:20Z"
        },
        {
          "tag": "v1.9.4",
          "kind": "patch",
          "published_at": "2026-03-11T02:36:16Z"
        },
        {
          "tag": "v1.9.3",
          "kind": "patch",
          "published_at": "2026-03-08T14:03:29Z"
        },
        {
          "tag": "v1.9.2",
          "kind": "patch",
          "published_at": "2026-03-08T14:03:23Z"
        },
        {
          "tag": "v1.9.1",
          "kind": "patch",
          "published_at": "2026-03-08T11:02:08Z"
        },
        {
          "tag": "v1.9.0",
          "kind": "minor",
          "published_at": "2026-03-08T04:56:17Z"
        },
        {
          "tag": "v1.8.2",
          "kind": "patch",
          "published_at": "2026-03-07T15:40:45Z"
        },
        {
          "tag": "v1.8.1",
          "kind": "patch",
          "published_at": "2026-03-07T12:31:57Z"
        },
        {
          "tag": "v1.8.0",
          "kind": "minor",
          "published_at": "2026-03-07T06:25:45Z"
        },
        {
          "tag": "v1.7.6",
          "kind": "patch",
          "published_at": "2026-03-05T01:55:07Z"
        },
        {
          "tag": "v1.7.5",
          "kind": "patch",
          "published_at": "2026-03-05T01:26:06Z"
        },
        {
          "tag": "v1.7.4",
          "kind": "patch",
          "published_at": "2026-02-25T02:57:38Z"
        },
        {
          "tag": "v1.7.3",
          "kind": "patch",
          "published_at": "2026-02-24T02:36:09Z"
        },
        {
          "tag": "v1.7.2",
          "kind": "patch",
          "published_at": "2026-02-24T02:31:00Z"
        },
        {
          "tag": "v1.7.1",
          "kind": "patch",
          "published_at": "2026-02-23T13:55:17Z"
        },
        {
          "tag": "v1.7.0",
          "kind": "minor",
          "published_at": "2026-02-18T17:07:45Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "445f0c7a6a4ff2c716a2e508d4364ab000ac06c4",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.21.11",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T15:28:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "093765a231d0e7ec1628bfdd5949b9bd87a14b68",
          "body": "Follow-up to #375, which swapped the \"▌\" caret for a reverse-video-space\none — that still trails a block caret after the live streaming text. Drop\nit altogether: the leading spinner already marks the turn as live, and a\nlone space covers the momentary gap right after a block commits so the\nspinner stays on screen. Nothing now trails the streamed text.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(conv): remove the streaming caret entirely",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T14:16:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7f5931a9a6594a07b2db11f3303374de2501f0fa",
          "body": "The live streaming tail appended a \"▌\" caret (U+258C) after the text. It is\nan East-Asian ambiguous-width glyph — measured as one cell by\nlipgloss/bubbletea but painted two cells wide by CJK terminals — so redrawn\nevery frame at the growing edge, the half-cell the cell differ never\nreclaims stranded\n[…]\nthe momentary gap right after a block commits (empty remainder) a lone space\nkeeps that spinner on screen, so nothing trails the streamed text.\n\nCloses #374\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(conv): drop the streaming caret that stranded a vertical line",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T14:05:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bab0439153324700baf549dd428e06f86955ef26",
          "body": "* refactor: write files atomically through one helper\n\nThe temp-file-then-rename dance was hand-copied into 19 call sites across\n14 packages, and the copies had drifted apart.\n\nThree of the differences mattered:\n\n- internal/secret/store.go, the file holding API keys and tokens, was the\n  only copy t\n[…]\npackage-map.md.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n* refactor(atomicfile): unexport dirPerm\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor: write files atomically through one helper (#354)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:33:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "70edf68b2868039bae104662d46601077a038ba3",
          "body": "…ting (#357)\n\nMoney.Add panicked when the two amounts named different currencies, and\nthat input is reachable: providers do not agree on a currency — MiniMax\nprices in CNY, DeepSeek/MiMo/Ollama in USD — and switching provider\nmid-session does not reset env.ConversationCost. Only /clear and /new do.\n\n[…]\noney keeps its single-amount meaning and loses Add entirely — it had one\ncaller, and leaving a panicking helper behind is an invitation to\nreintroduce this.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(llm): stop a provider switch from crashing the TUI on cost accoun…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:30:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "57318f1c98c84d1f296a4e212b8ea617d489c153",
          "body": "* fix(mcp): keep servers connected across a cwd change\n\nmcp.Initialize replaces the package registry, and reloadProjectServices\ncalls it on every cwd change and plugin reload. The replacement started\nwith no clients, and nothing reconnected them: AutoConnect runs once, from\nmodel.Init at startup.\n\nT\n[…]\n-off-by: Meng Yan <yanmxa@gmail.com>\n\n* docs(mcp): remove the stale duplicate defaultRegistry comment\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(mcp): keep servers connected across a cwd change (#361)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:28:10Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5a7d0409107eab0846c3a90fbc8f525d6d44bd11",
          "body": "Both reload paths merged plugin hooks into a throwaway snapshot:\n\n\tplugin.MergePluginHooksIntoSettings(m.services.Setting.Snapshot())\n\tm.syncSettingsToHookEngine()   // SetSettings(Snapshot()) — a second clone\n\nSettings.Snapshot() returns data.Clone(), a fresh deep copy on every call,\nso the merge l\n[…]\ninside syncSettingsToHookEngine, on the\nsnapshot it actually hands over. A caller can no longer get it wrong,\nand the two now-redundant merge calls go away.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(hook): stop losing plugin hooks on every reload (#362)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:25:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7a6cc33a2eb5adf6428de517a98388338028c5e1",
          "body": "Two hook calls run synchronously on the bubbletea goroutine with\ncontext.Background():\n\n\tupdate_submit.go:94    checkPromptHook  (UserPromptSubmit)\n\tmodel_lifecycle.go:264 FireSessionEnd   (SessionEnd)\n\nThe engine's default timeout is 600 seconds. That default suits a detached\nhook; applied to a gat\n[…]\nwait — complexity in the most-used path in the app, to support a\nslow hook nobody has asked for. Bounding the wait fixes what the user actually\nexperiences.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(app): bound the hooks the UI goroutine waits on (#370)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:21:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e471fa9bcdb4d4dddf54b461c236083098a4a3e4",
          "body": "…ion (#363)\n\nLosing transcripts-index.json made every prior session permanently\ninvisible in /resume, while the .jsonl transcripts sat on disk untouched.\n\nlistIndexEntries already recovers: when loadIndexLocked fails it calls\nrebuildIndexLocked, which reconstructs the index from the transcripts\ndire\n[…]\ndex remains the right answer — loadIndexLocked's own doc already\nnamed both branches (\"rebuild, or start a fresh index\"); this path just\ntook the wrong one.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(transcript): rebuild a damaged index instead of hiding every sess…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:15:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b8aebf355fd45936345149ccdf28ae6d8bfa7364",
          "body": "…ssion (#364)\n\nloadRecordsLocked rejected the whole transcript when any line failed to\ndecode, so one interrupted turn made a session permanently unresumable\neven though every record before the tear was intact.\n\nThe transcript is append-only and appendRecord fsyncs only on turn\nboundaries (inference\n[…]\nnd skipping it silently would leave a hole in the\nreplayed conversation with nothing to show for it, so that still fails\nloudly. The dropped line is logged.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(transcript): survive a torn final record instead of losing the se…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:12:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4bcae47f4864e9f6ed04bdd55cfa925de29a16f6",
          "body": "…#366)\n\nEnable and Disable write p.Enabled under r.mu, but Get, List, GetEnabled\nand GetByScope returned the live *Plugin and released the lock. Callers\ndereferenced it outside — refreshInstalledPlugins reads p.Enabled on the\nUI goroutine (on_plugin.go:483).\n\nThe writer is not on the UI goroutine. /\n[…]\nEnabledState reads it under r.mu.\nplugin.Install builds an Installer inside a tea.Cmd goroutine, so a\nconcurrent cd raced it. Replaced with a locked SetCwd.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(plugin): stop handing out live pointers to lock-protected state (…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:08:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "039d42297bd055964ac2e6c76d128094b81e7764",
          "body": "Registry.Disconnect called Client.Disconnect while holding the registry\nwrite lock:\n\n\tr.mu.Lock()\n\terr := client.Disconnect()      // blocks\n\tdelete(r.clients, name)\n\tr.mu.Unlock()\n\nSTDIOTransport.Close waits up to 2s for the read loop and then up to 5s\nfor cmd.Wait — seven seconds for a wedged serv\n[…]\n waiting for it is precisely the freeze. It is\nlogged instead. One caller reported it (/mcp disconnect) and now reports\nthe removal, which is what happened.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(mcp): stop a server teardown freezing the TUI and the agent (#367)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:04:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3f15eb2aa20d358d95530da43e176a61f064cf87",
          "body": "* fix(cron): stop one san window deleting another's scheduled jobs\n\nThe durable-job file is per-project, not per-process: two san windows open\non the same repo write scheduled_tasks.json. LoadDurable runs once, at\nstartup, and saveDurableLocked rewrote the file from the in-memory view —\nso a job cre\n[…]\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n* docs(cron): merge the stacked saveDurableLocked comment\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(cron): stop one san window deleting another's scheduled jobs (#371)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T12:01:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4b303c34736fb4480457514c883eecc05923d7f4",
          "body": "SessionPermissions is shared by two goroutines with no synchronisation.\nThe UI goroutine rewrites the posture whenever the user cycles the\noperation mode (Shift+Tab → env.ApplyModePermissions), and the agent\ngoroutine reads the same struct on every tool call through\nHasPermissionToUseTool. The race \n[…]\nly while it is parked. That still holds, and is not the\npath at fault: mode cycling is not covered by it, since the agent is\nrunning when Shift+Tab arrives.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(setting): stop the permission check racing the mode switch",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T11:46:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e16adfd3197ea92855196fdd28a415bc97821c90",
          "body": "A CJK character is one rune, three bytes, and two terminal columns. Twelve\nsites across the selectors mixed those up, so every panel misrenders as\nsoon as a name, path or prompt contains Chinese.\n\nByte-slicing against a column budget (mojibake, and a cut third of the\nrow):\n\n  on_session.go     the /\n[…]\nhose end\nidentifies them — a path's filename. suggest.go's rune-based\ntruncateFromLeft is the same idea but measured wrong; this is the\nwidth-aware version.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(tui): measure panel layout in display columns, not bytes or runes",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T11:42:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f7d346ba1e2332000d027e44396a9a60e2afd2a1",
          "body": "A background bash task runs in its own process group, and Stop/Kill signalled\nthe raw PGID. Once cmd.Wait reaps the child the kernel may reissue that PGID, so\na signal racing the reap could land on an unrelated group of the user's.\n\nThe cancel-driven path is the only fully race-free one — os/exec in\n[…]\nhat may already\nbe reissued — an inherent limit of raw-PGID signalling, where the common outcome\nis a harmless ESRCH. The stale \"safe against PID reuse\" claim on TerminateGroup\nis corrected to say so.",
          "is_bot": false,
          "headline": "fix(task): stop signalling a process group that may have been reissued",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T11:39:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "970576f4c9db39e59b76bd279fcd28e24a0045d3",
          "body": "executeCommand returned a clean outcome for any non-zero exit other than\n2, leaving Error nil and discarding stderr:\n\n\tif exitCode != 0 {\n\t\treturn outcome\n\t}\n\nEngine.Execute keys everything off result.Error, so the run took neither\nthe warn branch nor the audit-error branch and was recorded as \"ran\"\n[…]\ne turn carries on exactly as\nbefore — the only change is that the failure is now visible.\n\nExit 2 keeps its own blocking path, and a zero exit is untouched.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(hook): stop swallowing a hook that exited non-zero",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T11:37:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dc64c01271d9f6dbde1ec59008544277a9a549ae",
          "body": "forkSession re-pointed the session id but left the agent running. The\nagent holds an onEvent closure over the Recorder it was built with\n(app/agent.go:96), and a Recorder's session is fixed at construction\n(session/recorder.go:78) — so every message, inference, permission and\nhook record after the f\n[…]\n keeps OmitMessageWrites true\ninstead of re-chaining the fork's messages with synthetic timestamps), and\nthe hook engine's transcript path follows the fork.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(session): stop /fork writing the fork's history into the parent",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T11:34:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "39794fd2c23383a3ab886d63dd2e87827ff9942b",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(core): do not emit TurnEvent for a failed turn",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T11:32:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "81a2ef62f74e713341af8c9c67e82de4b85005e6",
          "body": "ThinkAct dropped the turn entirely when the retry budget ran out or the\nerror was not retryable — `return nil, err`. The steps already taken were\nbilled, their messages were already appended, and all of it went nowhere.\n\nsubagent is where that costs the most. Run falls through to the bare-error\npath\n[…]\nirst signal on this path: Run's\nerror is discarded at agent/session.go:45 and StopEvent has no consumer,\nso a turn that died this way was previously silent.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(core): return a Result when a turn dies on inference failure",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T11:32:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bd3c5dd18292f5f7c100c7501a83ea40e5a152a3",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "docs(skill): trim the registryMu comment, deduped with the test",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T11:28:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4daeec4958166acce12e23e4247591aad846a113",
          "body": "skill.Initialize swapped the package-level *Registry with no\nsynchronisation, and Default()/DefaultIfInit() read it the same way.\n\nBoth goroutines are live at once. Initialize runs on the bubbletea\ngoroutine via reloadProjectServices, which is reached whenever the working\ndirectory changes — and the\n[…]\ngoes through Default() and Count() rather than touching\ndefaultRegistry.skills directly, so the read is covered by both locks\ninstead of reaching past them.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(skill): guard the package-level registry against concurrent reinit",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T11:28:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "26a96c91fd57112c0c0ece103dff28d9ffa521e9",
          "body": "* fix(subagent): keep the task tracker parent-only\n\nEvery conversation shares one process-global todo store, and subagents get\nthe tracker tools by default. A background subagent that calls TaskCreate to\nplan its own work leaks that item into the main session's task panel — it\nshows up as an extra r\n[…]\ned tracker\nregardless of their allow list; their progress is still surfaced by the worker\nitem the main conversation creates for them.\n\n* test(subagent): assert tracker tools have no subagent executor",
          "is_bot": false,
          "headline": "fix(subagent): keep the task tracker parent-only (#373)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T09:47:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a61597625e5fc1ad64e15ed075987d93dc63204b",
          "body": "Tint each tracker row owned by a background agent (icon + text) with that\nagent's color, mirroring the agent's launch line in the conversation flow.\nPlain user todos keep the status palette; aborted rows stay error-red and\nstalled rows stay muted, since those states carry more meaning than whose\nage\n[…]\nws stay in ID order and the active/pending tail — the work the\npanel exists to surface — is never hidden behind the fold. A failed/killed\nitem breaks the run so a failure is never folded out of sight.",
          "is_bot": false,
          "headline": "feat(tracker): tint agent-owned rows and fold finished overflow (#372)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-21T09:35:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b6a44f39ca35eecc8859c8266a4c949d396942ac",
          "body": "…utput (#350)\n\n* fix(task): make a bash task's graceful stop actually graceful\n\nStop cancelled the task context before sending SIGTERM. bash.go overrides\ncmd.Cancel to SIGKILL the whole process group, and exec runs that the instant\nthe context is done — so the kill always landed first and the SIGTER\n[…]\n, so \"Stop must not\ncancel the run\" is checked by handing it a cancel func that records being\ncalled.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(task): make the graceful stop graceful, and bound a bash task's o…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T17:16:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "616efb6967048b38d71c0edc9301f37b47051440",
          "body": "ThinkAct built Result.Content from a per-return-site argument while Steps\nand the token counts came from closure capture. Four of the six exits got\nit wrong: the step cap passed the literal \"max steps reached\" and all\nthree cancellation paths passed \"\".\n\nTwo consequences, both reachable:\n\n- A subage\n[…]\nn the wrong text or none.\n\nThe detail parameter is dropped for the same reason: all six sites passed\n\"\". The StopDetail field stays, since it has consumers.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(core): report the model's own output at every turn exit (#351)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T17:06:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4395ddcd6df478cf04160834fe4a5dbd48a95d25",
          "body": "* feat(autopilot): add /goal to hand over the wheel in one line\n\nDriving a goal hands-free meant opening /autopilot, writing a mission,\ntoggling four steers, and clearing the continuation cap — enough setup that\nthe autonomy was there but rarely reached for.\n\n/goal <what to achieve> does all of it: \n[…]\nly what happened the first time it was tried.\nSay so where the reader picks the directory, not after.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat(autopilot): add /goal, and fix two defects from #347 (#349)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T16:33:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0eef967471c775b58091c15758d1c9d489112c5a",
          "body": "…esult (#348)\n\n* fix(tracker): create worker entries from the task lifecycle, not the tool result\n\nA background task's tracker entry was built from the launching tool's\nHookResponse, which reaches the UI goroutine long after the task is already\nrunning. Its completion is announced from the task's ow\n[…]\nthe\n\"Tasks\" panel header. The translation now happens at those edges instead of\ninside every package.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(tracker): join worker items to the task lifecycle, not the tool r…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T16:28:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ae9dc8918d5c258e0366be49c9258592d3b54480",
          "body": "Closes #343.\n\nAllDone read Status and drove UI, the shape #342 removed elsewhere. It is\nnot a liveness query, though: it asks whether the model closed out every item\nit wrote down, and Status is the only record of that. Deriving it would be\nwrong, not merely unnecessary — a task left in_progress wit\n[…]\nnd give renderTrackerList a pointer receiver —\nit passes a *model method value, so a value receiver moved the whole ~68 KB\nmodel to the heap on every frame.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(tracker): window the task list on the newest items (#346)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T15:31:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4dbeb11634330d4a250b9f31a181ed84cf599094",
          "body": "* feat(autopilot): keep an unattended run alive\n\nAutopilot handed control back at every point a session normally stalls, so\na run left alone ended at the first thing that wasn't a clean turn.\n\n- Continue through a turn that stopped mid-work (step limit, unrecoverable\n  truncation), telling the copil\n[…]\n will not fix itself (bad credentials,\n  unknown model) returns instead of spending the retry budget.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat(autopilot): raise the autonomy level (#347)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T15:26:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b5635373f6fe63d3cfdc54378d4c9f1ebd7bfa8b",
          "body": "Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6 to 7.\n- [Release notes](https://github.com/actions/setup-go/releases)\n- [Commits](https://github.com/actions/setup-go/compare/v6...v7)\n\n---\nupdated-dependencies:\n- dependency-name: actions/setup-go\n  dependency-version: '7'\n  depen\n[…]\nirect:production\n  update-type: version-update:semver-major\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "ci(deps): bump actions/setup-go from 6 to 7 (#341)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-20T12:30:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d04e1d6040b55df1369b3f5d97203c57cc04fb4c",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.21.10 (#345)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T10:58:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4426109c3f799ad16415d6cebfad04d6090e6fc9",
          "body": "The tracker's ●/◌ pulse kept animating after a turn ended. needsSpinner\nkeyed off todo.Task.Status == in_progress, but that status records what\nthe model intended and outlives whatever was executing it — a task can be\nleft open by a kill, a crash, a cancel, or the model simply never closing\nit out. \n[…]\niveness\n  query and had no remaining consumer.\n\nAlso removes a TaskUpdate prompt line referencing a <task-reminder> that\nnothing in the codebase ever emits.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(tracker): derive in-progress state from live executors (#342)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T10:36:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "088933ab048af3155c896897b92211396a15ff84",
          "body": "… (#339)\n\n* fix: base auto-compaction on the full prompt, including cached tokens\n\nThe proactive compaction check used resp.InputTokens as its input. With\nprompt caching active a provider reports the cached prefix under\nCacheRead/CacheCreation and leaves only the uncached delta in InputTokens —\na fe\n[…]\nllm.DefaultInputLimit, removed earlier.\n- Delete a doc comment left duplicated above isPromptTooLong.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix: base auto-compaction on the full prompt, including cached tokens…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T10:04:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fa64b9724f7b76cc98849fbcff5b8929dddaeb40",
          "body": "…wrapping (#340)\n\n* fix(input): bind shift+enter, place the real cursor, size the box by wrapping\n\nThree composer defects, each independent.\n\nThe terminal cursor never moved to the input box. The textarea painted a\nreverse-video block and tea.View.Cursor was left nil, so the real cursor\nstayed where\n[…]\nouching the filesystem through history.Load to exercise a widget, and the\nplain-enter case folds into the newline table. go mod tidy demotes uniseg,\nwhose last use went with the old height arithmetic.",
          "is_bot": false,
          "headline": "fix(input): bind shift+enter, place the real cursor, size the box by …",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-20T08:18:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "49e00da4086f6f327ea5189c41381d5879e74ddd",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.21.9",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:27:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6be4704f5b0abaa7e3748e5a97c1e2e9a7d32e96",
          "body": "The editResult submap in the Edit HookResponse duplicated the typed\nEditDetails and was read nowhere; drop it. Fold renderEditResultInline's\nerror branch into renderGenericToolResultInline (it differed only by\nstripping a redundant \"Error: \" prefix), and use strings.CutPrefix for\nthe BOM check.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor: drop dead Edit hook map and dedupe error render",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7e3c14f8d4cb7dd4fb937d73c4918d09c971d292",
          "body": "Deferring the \"❭\" display to the agent's ingest echo left a released\nmessage invisible between the queue and the conversation: it was\ndequeued instantly but only shown once the agent ingested it, which\nmid-turn lags a full inference step (drainInbox is non-blocking, so the\nmessage sits in the inbox \n[…]\nsses it (live is one step\nahead of where a resumed transcript places it) — a cosmetic ordering\ndifference in exchange for no gap and a uniform display path.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix: show released queued message at release time, not on ingest echo",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6e2e3862d1518edf869acc4fdd93f1c365a1a2a0",
          "body": "The step-boundary and turn-boundary drains both popped the same user\nqueue with duplicated edit-hold guards and image-block handling, and\ndiverged only in how they displayed the released message. Extract the\nshared release into releaseHeadQueued and route both through it, so a\nreleased queue message\n[…]\nrain (persistence is unaffected —\n  it rides the agent's OnAppend, not conv display)\n- rename stepDrainPending -> awaitingIngestEcho now that it serves both\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor: unify step and turn queue drains into releaseHeadQueued",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d18b10908f092f9ea168239f4990271c987bffe5",
          "body": "The agent-side wait (a UI-semantics atomic.Bool + a 200ms timer in\ncore.drainInbox) only bought one inference step of steer latency: a\nmid-turn queued message still arrives mid-turn without it, just at the\nnext drainInbox rather than the immediate one. Remove it so the core\nloop stays UI-agnostic an\n[…]\n message ID (minted at\n  release, threaded through the new Session.SendMessage) instead of by\n  payload equality, so identical queued text can't cross-match\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor: drop pendingInput step-boundary wait, correlate by ID",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3d1d9b297eda74f7876f98506b840e3c07dc0cda",
          "body": "- add setting.filePathArg as the single source of truth for the Edit\n  (\"path\") vs Read/Write/NotebookEdit (\"file_path\") argument, replacing\n  four inline copies across the permission and suggestion rules\n- gate the per-step conversation walk on InputLimit() > 0, so a model\n  with no input limit skips work that can never trigger compaction\n- add CompactState.Clear() to dedupe the in-progress-indicator reset\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor: consolidate Edit path-key mapping and trim compaction waste",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff6229e94377acbb6bbe5cacc26548355d00fd0d",
          "body": "- remove the computed-but-unread FirstChangedLine from EditDetails, the\n  HookResponse editResult map, and applyEdits' return signature\n- restore the ToolResult doc comment displaced onto EditDetails\n- render \"<Tool> → failed\" instead of repeating the error's first line,\n  which the always-shown expanded body already displays\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor: drop unused Edit metadata and dedupe error summary",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "26110b35e6d6d5236066d3183d775772ae191eea",
          "body": "A message typed while the agent is mid-turn now reaches it at the next\nstep — its drainInbox waits a brief bounded window (pendingInput) for the\nUI to release the head queued message — instead of waiting for the whole\nturn to end. So the message steers the run as its own step and stays\neditable in the queue right up to that boundary. Subagents never set\nPendingInput, so their drainInbox stays non-blocking.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat: release queued user messages at step boundaries",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1fdcd3c027d64fbfb449702e147369577e9c7a4a",
          "body": "- Task-completion notices inline the full result (up to 20000 bytes) or,\n  when larger, point to the output file instead of a truncated preview,\n  so the reader gets the whole report in one read.\n- Relayed background-agent messages (completions, interim reports) render\n  as a distinct accent-toned n\n[…]\nthan a plain system line.\n- On resume, injected <task-notification>/<agent-message> envelopes\n  collapse to that one-line notice instead of dumping raw XML.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat: clearer background-agent output in the conversation",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "edf10a81a69f01cf8121addc90a29aab997cd9ea",
          "body": "The Edit tool now sends \"path\" instead of \"file_path\", but\nGenerateSuggestions still read \"file_path\" for Edit, so allow-rule\nsuggestions on an Edit permission prompt came back empty. Split Edit\n(path) from Write (file_path), matching permission.BuildRule, and feed\neach tool its real arg key in the test so the mismatch can't recur.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix: read Edit path arg for permission-rule suggestions",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae1ca0cbb8c12b86460513d6a940b9d1d445741a",
          "body": "The reasoning summary streams as discrete parts with no separator between\nthem. Each part is a bold \"**headline**\" section, so concatenating them\ndirectly collided adjacent parts (…truncation****Updating…). Insert a blank\nline between parts in both the live stream and the round-tripped reasoning\nitem.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix: separate OpenAI reasoning summary parts",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8debc61e1b558b1567fc67186a15a8437d0ff653",
          "body": "Auto-compaction ran a multi-second blocking summarization call with no UI\nfeedback, so it looked frozen. Emit a CompactStart event before the call\nso the UI shows the same \"Compacting N messages…\" line and spinner as\nmanual /compact, and clear it on completion or when the next inference\nstarts (covering the compaction-failure retry path).\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix: show progress during auto-compaction",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d482fce8d676a0bd1e78c41905302492ba2f354d",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat: align Edit tool with Pi format",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "48280642e4d98e2b8eb07a58f8368f25506189d0",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat: support batched file edits",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "92691f336fd548790ec8c3b1bb6a08d3ee949dda",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "docs: clarify README and tool feedback",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c6bed49dbb650d2cf3f286a54fed0b234da40c95",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "docs: simplify subagent model override description",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3f500460161a5abc9a6e777bd72a463ff7280767",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix: inherit subagent model when override unavailable",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a496104eb4e168926f3ce45dbf469a5d7746de42",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "perf: avoid repeated conversation and agent rendering work",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T17:14:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e8eb64af98ab1156fd5c37f900042899c4cd034d",
          "body": "The transcript index is re-serialized and rewritten in full at every turn\nboundary. Two things made that write larger than necessary: it was\npretty-printed (MarshalIndent), and Title/LastPrompt stored the full user\ntext, so a long paste bloated an entry that gets rewritten every turn.\n\nStore a bound\n[…]\nal compact. On a real\n328-session project this shrank the per-turn index write from 811 KB to\n160 KB, and the entry size no longer grows with prompt length.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "perf(session): cap index preview text and compact the index write",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T10:11:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a31792e1df825669df2aab8f16fe94612ff0ac2b",
          "body": "The index flush was hand-placed in QuitWithCancel, so the /exit and\n/quit slash commands — which run the same shutdown sequence but never\nreach that handler — quit without persisting their staged index\nmutations, defeating the deferral for those paths. Move the flush to\nthe single post-Run teardown \n[…]\n Setup.FlushIndex facade instead of reaching through\nGetStore, so all exit paths flush exactly once. Also drop an\nunreachable nil check in flushIndexLocked.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "perf(session): flush the transcript index on every quit path",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T09:56:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb80a38f8c974d250b6398127299d6838012a3ec",
          "body": "The active tail is re-rendered on every frame — every 360ms spinner tick,\nfor the whole duration a tool runs — and any assistant message carrying tool\ncalls falls out of the plain-wrap fast path into the full glamour + chroma\npipeline. That re-ran on byte-identical content several times a second.\n\nM\n[…]\nhe map is bounded so a long session's\none-shot renders can't grow it without limit. A cache hit is ~10ns / 0 allocs\nversus ~640µs / 418KB for a full render.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "perf(conv): memoize markdown rendering across frames",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T09:56:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "360503397025c315a0069318d3af7a83ddf5bea4",
          "body": "The read-side index cache (5071c2aa) left the write side untouched: every\nmessage append and state patch still re-serialized and rewrote the whole\ntranscripts-index.json — O(sessions) work, ~7-12 full-file writes per turn,\nall under the store-global lock (and amplified by subagent message dumps).\n\nH\n[…]\n after a crash mid-first-turn. The\nindex is a pure derived cache, so an unflushed update is recovered by the\nrebuild-from-transcripts path on the next List.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "perf(session): defer transcript-index writes to turn boundaries",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T09:56:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb706d1c5bc47e6df7f0c97a459cac91b89b7e54",
          "body": "Now that the Entry layer is gone, give the message-conversion helpers and files\na deliberate, parallel scheme:\n\n- MessageBlocks -> MessageToBlocks, matching its sibling *ToBlocks converters\n  (userContentToBlocks / assistantContentToBlocks / toolResultToBlocks) and\n  stating the action.\n- FileStore.\n[…]\nso collided with the\n  transcript package's own Project() concept.\n\nAlso drops a stale doc reference to the deleted messageToTranscript. No behavior\nchange.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor(session): sharpen conversion-layer names",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T09:56:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42872462ea5e3d5c8d5ca96df26eb5343203cb6f",
          "body": "Session content was modeled four times end to end — core.Message,\nsession.Entry, transcript.Node, transcript.Record — with Entry carrying the\nlegacy Claude-Code on-disk schema in json tags that were never serialized. It\nsurvived only as an in-memory intermediate, forcing two near-identity converter\n\n[…]\n (verified by a golden node diff over\nreminder / command / image / thinking / tool-call / tool-result messages); full\ntest suite and the race detector pass.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor(session): drop the vestigial Entry layer",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T09:56:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0c0f99b72e4b9c571626ae70f23e240a481fcdc9",
          "body": "Every message append and state patch ran through upsertIndexEntryLocked, which\nre-read and re-parsed the entire transcripts-index.json (loadIndexLocked) before\nrewriting it — an O(sessions) unmarshal on every append. Cache the parsed index\non the FileStore: saveIndexLocked (the sole writer of the fi\n[…]\ny saveIndexLocked does, under the\nwrite lock), keeping it a pure read that is safe under the read lock in\nlistIndexEntries. Verified with the race detector.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "perf(session): cache the transcript index in memory",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T09:56:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3d4419203048509767c04bc5851ee319412e4c5e",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(llm): sync provider model metadata",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T06:03:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "71a14074e31e7ef0d73d4e18419b7703578d76c1",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(app): align bash prompt with result marker",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T06:03:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aa5750729827c6160098116a905bceec7e031c67",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(app): inset bash prompt marker",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T06:03:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b6bc6ed1f3ea5745c39e7b5c648ed934096012c4",
          "body": "Add a reverse invariant test so registering a built-in but forgetting to\nadd it to builtinToolOrder — a tool that executes yet stays invisible to\nthe model — fails in CI instead of shipping silently. It resolves each\nregistry entry to its canonical Schema().Name so deprecated aliases fold\nonto the t\n[…]\nat runtime; document the defensive !ok skip.\n- Clean up the leaked TestPermissionAwareTool registration that polluted\n  the global registry for later tests.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "test(tool): guard builtinToolOrder covers every registered tool",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T03:46:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6b117459da32c83ffc8d016eb3a5feb10d92d3a5",
          "body": "Each built-in tool's LLM schema lived as a package-level var in the tool\npackage (schema_base/schema_task/schema_agent), divorced from its\nimplementation and joined to it by a name string in AdaptToolRegistry.\nThis let the two drift (every tool carried two divergent descriptions) and\nleft core.Tool.\n[…]\nma (the tool is intentionally\nunregistered) and the unused filterSchemas. Schema output is byte-identical\nto before, verified by a golden diff against main.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor(tool): make built-in tools self-describing via Schema()",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T03:46:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c7285565929f129ca26f25cc32c9a6a94c1118fe",
          "body": "llm.CompletionResponse was a field-for-field twin of core.InferResponse,\nbridged by toInferResponse on every inference. Alias it to core.InferResponse\nso the provider streaming layer and the agent loop share one response type\nwith no conversion and no way to drift; the logging accessors move onto\nco\n[…]\nelds.\n\nNo behavior change: StopReason values and response fields are identical and the\nremoved chunks had no consumer. Full build, vet, and test suite pass.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor(llm): unify the provider response type onto core.InferResponse",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-19T03:36:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9d82666199819e89a9974082e51218fe50ec524c",
          "body": "* fix(app): inset bash prompt marker\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n* fix(app): align bash prompt with result marker\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n* chore: bump version to 1.21.8\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.21.8 (#330)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T17:07:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d5edcc1480c0d115495208da77f553296c317c41",
          "body": "…#329)\n\n* fix(app): snapshot permission audit input before releasing the gate\n\nAgent tools decorate their shared input map with runtime callbacks as\nsoon as the permission response wakes them. Serializing that map after\nreleasing the gate could race the write and crash the process with a\nconcurrent \n[…]\nwo, and rename the helper and\nlocal to the file's perm* convention (permDecisionRecord / permRecord).\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(app): snapshot permission audit input before releasing the gate (…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T16:57:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d9af0e10006973fb3eea96a2d99e61de6a556105",
          "body": "* chore: bump version to 1.21.7\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n* fix(app): align bash command and result columns\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n* fix(app): inset bash prompt marker\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n* fix(app): align bash prompt with result mark\n[…]\ne().\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n* fix(app): sync hooks with restored operation mode\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "chore(release): v1.21.7 (#328)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T16:40:45Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b40d63e1049f784ea5531f95854f5a6f6b0fe400",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "fix(app): preserve live context across agent restarts",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T14:26:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8047dc05b96b4428c6d61e2182320b0977723335",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "style(agent): format session test",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T14:26:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "952276c996edac5dd7060c609c576ae0a99996b1",
          "body": "A mid-conversation agent rebuild (self-learn capability drift, /evolve save,\nagent toggle) reseeded the replacement agent from m.conv — the UI conversation\nmodel. When that model and the agent's live chain diverge, the reseed comes back\nempty, so the rebuilt agent starts with no history: the model s\n[…]\nes() surfaces the seeded chain with ids; nil when inactive\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_014Myxco9T1v4JbPsuKqa8kc",
          "is_bot": false,
          "headline": "fix(app): carry the agent's own chain into a rebuilt session",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T14:26:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "31db935d90f42bd931e9b74d8fff0f37d1454c5d",
          "body": "Review follow-ups on the flat spawn→result subagent work:\n\n- Project instructions now reach any worker that can edit the workspace,\n  not just edit/bypass modes: a default-mode worker whose allow_tools\n  grants an edit-class tool (Edit/Write/NotebookEdit) gets them too, so its\n  edits follow project\n[…]\ntMessages — its only caller\n  was the removed resume path.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_015fRqq5ZarHvEMng7EGoQdS",
          "is_bot": false,
          "headline": "fix(subagent): give allow_tools edit workers project instructions",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T14:26:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d4fe2db4aa034db756f0c75997a5f761398cecbd",
          "body": "… activity naming\n\n- broker: introduce the Deliver type and have it return bool, so Send\n  reports whether a message was actually accepted; a full recipient inbox\n  is now distinguishable from a silent drop. Threaded through the main,\n  task-completion, and subagent delivery callbacks.\n- tool: extra\n[…]\nand comments.\n- docs + system testdata refreshed to match.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_014Myxco9T1v4JbPsuKqa8kc",
          "is_bot": false,
          "headline": "refactor(subagent): broker delivery reporting + shared XML escaping +…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T14:26:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "63142c30be4788023fed9ad3a16a1ec0b99c04a9",
          "body": "Subagent worktree isolation created a git worktree under\n.git/agent-worktrees/<slug> for each isolated run. That hard-fails when\nSan itself runs inside a linked worktree (where .git is a file, not a\ndirectory): `git worktree add` errors with \"Not a directory\", so every\nisolated subagent died before \n[…]\nrentOnlyTools excludes Agent from every subagent tool set.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_014Myxco9T1v4JbPsuKqa8kc",
          "is_bot": false,
          "headline": "refactor(subagent): drop worktree isolation; run in session cwd",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T14:26:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b5e1b84a89500ec8e9bd1647b34d9bebd35f7e6f",
          "body": "… reuse notifyMain\n\nFollow-up cleanups on the spawn→result / broker rework:\n\n- Extract finalizeResult() shared by buildAgentResult and\n  buildCancelledAgentResult. They differed only in Success/Error but\n  duplicated the whole settle/persist/hook flow and a 15-field AgentResult\n  literal that had to\n[…]\nve the now-redundant concepts/agent-communication.md and align\ndata-flow / permission-model / writing-a-subagent / broker / subagent with the\nshipped model.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor(subagent): dedup result builders, drop double worktree note,…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T14:26:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bbde76461edb5156608e31846baff27de3def7a1",
          "body": "Rework subagent communication down to the essentials and route all\ninter-agent messages through one small broker.\n\nSubagents:\n- spawn → result: foreground returns the tool result; background runs in\n  parallel and sends a completion when done. One-shot (no resume).\n- flat: only the main conversation\n[…]\np/hub\nreferences scrubbed across architecture/app/data-flow/package-map.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_015fRqq5ZarHvEMng7EGoQdS",
          "is_bot": false,
          "headline": "feat(subagent): flat spawn→result model + broker message routing",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T14:26:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7ef9f39ea11b05e9a341e342c8fa969c2d50e445",
          "body": "Signed-off-by: hchenxa <hchenxa1986@qq.com>",
          "is_bot": false,
          "headline": "feat: add json version output (#324)",
          "author_name": "Hui Chen",
          "author_login": "hchenxa",
          "committed_at": "2026-07-18T09:55:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "021569b4701cb56fae2eb9c4c0255747cf460149",
          "body": "InputLimit and the output-token cap resolve from the provider's ListModels,\nwhich is a live /v1/models round-trip for OpenAI-compatible providers\n(Anthropic/Google cache internally). They were called on every inference step\n— the pre-infer compaction check and every Infer/Stream — so a 20-step turn\n\n[…]\n resolved input/output\nlimits per model on the Client. Only a successful (non-zero) lookup is cached;\na transient failure retries rather than sticking at 0.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "perf(llm): memoize model token limits per client (#322)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-18T00:41:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5068221a5bbf56ed062a7899599e8105de69c893",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.21.6 (#321)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-17T17:03:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "120e9bb72263db751a238ad9d9e23b87b1b941e6",
          "body": "A disciplined senior-engineer persona for developing San: think before coding,\nask instead of assuming, write the minimum that solves the problem, change only\nwhat the task requires, and verify before claiming done.\n\nShips project-scoped — .gitignore gains `!.san/personas/` alongside the existing\n`!\n[…]\n from\nSan's own Apache-2.0 simplify skill. NOTICE records the provenance. Canonical\ncopy lives in genai-io/personas.\n\nSigned-off-by: Meng Yan <ben@stark.fund>\nCo-authored-by: Meng Yan <ben@stark.fund>",
          "is_bot": false,
          "headline": "feat: add project-scoped software-engineer persona (#318)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-17T16:58:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9925789a3730613ce955db75cac9b019b10f0c03",
          "body": "…#319)\n\nRender a multi-line Bash tool call — or a single line too long for the\ncompact Bash(cmd) label — as a terminal-style block below the \"● Bash\"\nheader: a dim shell \"$\" prompt sitting in the same column as the \"⎿\"\nresult trailer, with wrapped and continued lines hanging under the command\ntext s\n[…]\n up in one column. Short single-line commands\nkeep the compact label, and commands soft-wrap in full rather than\ntruncate, so the command is always visible.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat(bash): render multi-line commands as a $-prompt terminal block (…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-17T16:20:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "11e5100dcbd62633cd77d1d7a1da4e37d7d4c403",
          "body": "…lt (#317)\n\nallowBypass now defaults to enabled: Bypass Permissions is reachable via\nShift+Tab (and as a settings defaultMode) unless the user explicitly sets\n\"allowBypass\": false to lock it out. Previously it required opting in.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat(setting): make Bypass Permissions opt-out, in the cycle by defau…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-17T12:14:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "041f4998ecd2aea9c8dd1ec579fe17e8786acd37",
          "body": "…#316)\n\nThe status line already shows real context-window occupancy as\n\"ctx used/limit\". A second per-turn \"↑… ↓…\" token summary above the\ninput area used a different scope (turn accumulation), so the two\nfigures conflicted and confused readers. Remove the top summary and\neverything that fed only it\n[…]\nts: cached-token split for the Responses stream, latest-call-only\nctx accounting across two OnTokenUsage calls, status line shows ctx\nwithout the \"↑…↓…\" arrows, and unit coverage for SplitInputTokens.",
          "is_bot": false,
          "headline": "fix(app,llm): drop turn-usage line, fix OpenAI cached-token mapping (…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-17T11:41:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6399682f001db604ef142e546ba26401ca0d1b5a",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.21.5",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-17T09:49:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b40660705a659d376dec0e3638f2f6fa4222a5c2",
          "body": "…#311)\n\nGive self-learning its own /evolve overlay (skills + memory), split out of\n/config, and drive it entirely by the model rather than by cadence/rules.\n\nTrigger: when self-learning is active the main agent gets one safe Evolve\ntool. Calling it queues a background review at turn end — no cadence\n[…]\nllowed; memory opt-in). The\nskills JSON keeps an explicit `enabled` marker so legacy opt-outs stay off.\n\ngo build / vet / test ./... / layercheck all green.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat(selflearn): dedicated /evolve panel with model-decided trigger (…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-17T09:18:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3d4998cef769e4cbf0174dbf43832ea42f387d95",
          "body": "Queued messages now read as part of the conversation instead of a\nstatus-bar footnote:\n\n- Render each queued item as a dim \"❭\" shadow prompt above the input\n  separator, mirroring the live prompt below — no more \"1. 2. 3.\"\n  numbering.\n- Drop the \"[N queued]\" status-bar badge; the queue block is the\n[…]\nng it when a dequeued\n  item carries images the active model can't accept.\n- Preserve an unrelated textarea draft across an idle drain, and restore\n  the pre-edit stash before ctrl+u clears the queue.",
          "is_bot": false,
          "headline": "feat(queue): redesign queued-message interaction (#312) (#313)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-17T06:43:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fb445181b5fdd9eea504c6642c4d3600e6d0882e",
          "body": "Add CONTRIBUTOR_LADDER.md defining the Contributor -> Reviewer ->\nApprover -> Maintainer roles mapped to the OWNERS file, following the\nCNCF contributor-ladder conventions, and link it from CONTRIBUTING.md.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "docs: add contributor ladder (#301)",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-13T16:24:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a96f9bf0513ad8deee3c28c59832044e728d530d",
          "body": "Bumps [actions/stale](https://github.com/actions/stale) from 10.3.0 to 10.4.0.\n- [Release notes](https://github.com/actions/stale/releases)\n- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)\n- [Commits](https://github.com/actions/stale/compare/eb5cf3af3ac0a1aa4c9c45633dd1ae542a27\n[…]\nirect:production\n  update-type: version-update:semver-minor\n...\n\nSigned-off-by: dependabot[bot] <support@github.com>\nCo-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "ci(deps): bump actions/stale from 10.3.0 to 10.4.0 (#306)",
          "author_name": "dependabot[bot]",
          "author_login": "dependabot[bot]",
          "committed_at": "2026-07-13T15:44:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3438c2c6d24364d776844b7e7157b0e801d0c479",
          "body": "Signed-off-by: hchenxa <hchenxa1986@qq.com>",
          "is_bot": false,
          "headline": "feat: add session naming features",
          "author_name": "hchenxa",
          "author_login": "hchenxa",
          "committed_at": "2026-07-13T15:24:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "66102d0b187ff772efaa6b043b98f538827d73c1",
          "body": "Signed-off-by: hchenxa <hchenxa1986@qq.com>",
          "is_bot": false,
          "headline": "fix: agent time out issue",
          "author_name": "hchenxa",
          "author_login": "hchenxa",
          "committed_at": "2026-07-13T15:12:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1c879ae861ba5092f20f824cda2ecb69a764329c",
          "body": "Signed-off-by: hchenxa <hchenxa1986@qq.com>",
          "is_bot": false,
          "headline": "fix: fix the instllation issues when ratelimit reached",
          "author_name": "hchenxa",
          "author_login": "hchenxa",
          "committed_at": "2026-07-13T06:41:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8a7dd0135980279fa8acfea34fdbe02fb2c32bf0",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.21.4",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-10T18:40:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0f6af4ef825eb37372b004ef55c5fb2a5ad56a97",
          "body": "- extract Store.ResolveAuthMethod: the model-auth fallback (use the stored\n  connection's auth when the model carries none) was copy-pasted in both\n  reasoningCapabilityForModel and kit.GetModelTokenLimits; both now call it.\n- CachedModelReasoningForProvider returns the cached *ReasoningCapability\n \n[…]\nf rebuilding it with NewReasoningCapability on every lookup;\n  the value was already normalized at write time and this runs on the\n  status-bar render path.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor(llm): dedup auth resolution and drop redundant re-normalization",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-10T18:27:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5e7d6b5612000493d3c3a5d8404fe8431d402836",
          "body": "Carry ModelInfo.Description through to the model picker and trail the model\nname with a dimmed, width-truncated blurb when present. Populate it from the\nChatGPT Codex catalog's top-level per-model \"description\" (verified against\nthe codex ModelInfo wire struct); it stays blank for catalogs that omit it,\nso the row is unchanged for those.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat(provider): show the model description dimmed in the picker",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-10T18:27:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3732886b9e4964f7ab3af491a256da4440097189",
          "body": "- rename ReasoningCapability.Efforts -> SupportedEfforts (json supportedEfforts)\n  so it reads as a pair with DefaultEffort and mirrors the codex wire field\n  supported_reasoning_levels; the field is new in this branch, so no released\n  cache carries the old key.\n- inline the vestigial openAIDefaultThinkingEffort helper back into the\n  DefaultThinkingEffort method now that openAIModelInfo no longer calls it.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor(llm): name the reasoning-capability field SupportedEfforts",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-10T18:27:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f2557f1e3818b356b8fb43c3706ad728dfd8144b",
          "body": "…d guesses\n\n- openAIModelInfo no longer sets ModelInfo.Reasoning; only live catalogs\n  (the ChatGPT subscription /models response) attach it. /v1/models entries\n  fall back to the provider's static ThinkingEffortProvider rules at\n  resolution time, so a binary's updated static rules are no longer ma\n[…]\n by the TTL-ignoring reasoning cache read.\n- drop the now-unused ResolveThinkingEffort / NextThinkingEffort helpers,\n  superseded by the *ForModel variants.\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "refactor(openai): resolve reasoning capabilities live, not from cache…",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-10T18:27:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f67f5bac15b47251031457021d6f4fe435c6df34",
          "body": "Signed-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "feat(openai): discover model reasoning capabilities",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-10T18:27:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "55e607b6a3537ef04a55ca72292d0b936c719b4f",
          "body": "Adds hchenxa to OWNERS as reviewer/approver (see #285).\n\nSigned-off-by: hchenxa <hchenxa1986@qq.com>",
          "is_bot": false,
          "headline": "feat: add hchenxa as reviewers (#295)",
          "author_name": "Hui Chen",
          "author_login": "hchenxa",
          "committed_at": "2026-07-10T15:40:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e1ae0167cd755e00bf12671df89d6cccb4516bb9",
          "body": "* fix: handle paste in autopilot overlay\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n* chore: bump version to 1.21.3\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>\n\n---------\n\nSigned-off-by: Meng Yan <yanmxa@gmail.com>",
          "is_bot": false,
          "headline": "chore: bump version to 1.21.3",
          "author_name": "Meng Yan",
          "author_login": "yanmxa",
          "committed_at": "2026-07-10T14:25:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 100,
      "commits_last_year": 979,
      "latest_release_at": "2026-07-21T16:26:44Z",
      "latest_release_tag": "v1.21.11",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 28,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 1.3
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 87,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/genai-io/san",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/genai-io/san",
          "is_deprecated": false,
          "latest_version": "v1.21.11",
          "repository_url": "https://github.com/genai-io/san",
          "versions_count": 123,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-21T15:28:52Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 32,
      "stars": 70,
      "watchers": 3,
      "fork_history": {
        "days": [
          {
            "date": "2025-04-03",
            "count": 1
          },
          {
            "date": "2026-02-09",
            "count": 1
          },
          {
            "date": "2026-03-05",
            "count": 1
          },
          {
            "date": "2026-05-13",
            "count": 1
          },
          {
            "date": "2026-05-14",
            "count": 1
          },
          {
            "date": "2026-05-23",
            "count": 1
          },
          {
            "date": "2026-05-26",
            "count": 1
          },
          {
            "date": "2026-05-27",
            "count": 1
          },
          {
            "date": "2026-05-28",
            "count": 1
          },
          {
            "date": "2026-06-01",
            "count": 1
          },
          {
            "date": "2026-06-04",
            "count": 1
          },
          {
            "date": "2026-06-05",
            "count": 9
          },
          {
            "date": "2026-06-06",
            "count": 2
          },
          {
            "date": "2026-06-08",
            "count": 1
          },
          {
            "date": "2026-06-11",
            "count": 1
          },
          {
            "date": "2026-06-12",
            "count": 3
          },
          {
            "date": "2026-06-13",
            "count": 1
          },
          {
            "date": "2026-06-17",
            "count": 1
          },
          {
            "date": "2026-06-21",
            "count": 1
          },
          {
            "date": "2026-07-07",
            "count": 1
          },
          {
            "date": "2026-07-16",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 32,
        "total_forks": 32
      },
      "star_history": {
        "days": [
          {
            "date": "2024-11-04",
            "count": 1
          },
          {
            "date": "2024-11-06",
            "count": 1
          },
          {
            "date": "2025-02-28",
            "count": 1
          },
          {
            "date": "2025-04-14",
            "count": 1
          },
          {
            "date": "2025-05-20",
            "count": 1
          },
          {
            "date": "2026-01-16",
            "count": 1
          },
          {
            "date": "2026-02-03",
            "count": 1
          },
          {
            "date": "2026-02-09",
            "count": 1
          },
          {
            "date": "2026-04-10",
            "count": 1
          },
          {
            "date": "2026-04-22",
            "count": 1
          },
          {
            "date": "2026-04-28",
            "count": 1
          },
          {
            "date": "2026-05-01",
            "count": 1
          },
          {
            "date": "2026-05-13",
            "count": 7
          },
          {
            "date": "2026-05-14",
            "count": 8
          },
          {
            "date": "2026-05-15",
            "count": 6
          },
          {
            "date": "2026-05-19",
            "count": 1
          },
          {
            "date": "2026-05-28",
            "count": 1
          },
          {
            "date": "2026-06-01",
            "count": 1
          },
          {
            "date": "2026-06-03",
            "count": 1
          },
          {
            "date": "2026-06-04",
            "count": 1
          },
          {
            "date": "2026-06-05",
            "count": 7
          },
          {
            "date": "2026-06-06",
            "count": 1
          },
          {
            "date": "2026-06-07",
            "count": 2
          },
          {
            "date": "2026-06-08",
            "count": 1
          },
          {
            "date": "2026-06-09",
            "count": 1
          },
          {
            "date": "2026-06-10",
            "count": 3
          },
          {
            "date": "2026-06-11",
            "count": 2
          },
          {
            "date": "2026-06-12",
            "count": 3
          },
          {
            "date": "2026-06-13",
            "count": 2
          },
          {
            "date": "2026-06-14",
            "count": 1
          },
          {
            "date": "2026-06-17",
            "count": 1
          },
          {
            "date": "2026-06-24",
            "count": 1
          },
          {
            "date": "2026-06-26",
            "count": 1
          },
          {
            "date": "2026-06-28",
            "count": 1
          },
          {
            "date": "2026-07-07",
            "count": 1
          },
          {
            "date": "2026-07-13",
            "count": 1
          },
          {
            "date": "2026-07-14",
            "count": 1
          },
          {
            "date": "2026-07-16",
            "count": 1
          },
          {
            "date": "2026-07-19",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 70,
        "total_stars": 70
      },
      "open_issues_and_prs": 11
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 49529,
      "source_files_sampled": 622,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "AGENTS.md",
        "docs/packages/2-feature/agent.md"
      ],
      "agent_instruction_max_bytes": 3518
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": "repository_graph",
        "source": "osv",
        "findings": [
          {
            "name": "golang.org/x/crypto",
            "direct": false,
            "version": "v0.40.0",
            "severity": "critical",
            "ecosystem": "go",
            "cvss_score": 10,
            "advisory_ids": [
              "GHSA-45gg-vh54-h5m9",
              "GHSA-5cgq-3rg8-m6cv",
              "GHSA-78mq-xcr3-xm33",
              "GHSA-89gr-r52h-f8rx",
              "GHSA-9m57-25v3-79x9",
              "GHSA-f5wc-c3c7-36mc",
              "GHSA-f6x5-jh6r-wrfv",
              "GHSA-j5w8-q4qc-rx2x",
              "GHSA-jppx-rxg9-jmrx",
              "GHSA-q4h4-gmj2-qvw2"
            ],
            "fixed_version": "0.52.0",
            "advisory_count": 32,
            "oldest_advisory_days": 250
          },
          {
            "name": "google.golang.org/grpc",
            "direct": false,
            "version": "v1.66.2",
            "severity": "critical",
            "ecosystem": "go",
            "cvss_score": 9.1,
            "advisory_ids": [
              "GHSA-hrxh-6v49-42gf",
              "GHSA-p77j-4mvh-x3m3",
              "GO-2026-4762"
            ],
            "fixed_version": "1.82.1",
            "advisory_count": 3,
            "oldest_advisory_days": 125
          },
          {
            "name": "golang.org/x/net",
            "direct": false,
            "version": "v0.41.0",
            "severity": "moderate",
            "ecosystem": "go",
            "cvss_score": 6.5,
            "advisory_ids": [
              "GHSA-5cv4-jp36-h3mw",
              "GO-2026-4440",
              "GO-2026-4441",
              "GO-2026-4918",
              "GO-2026-5025",
              "GO-2026-5026",
              "GO-2026-5027",
              "GO-2026-5028",
              "GO-2026-5029",
              "GO-2026-5030"
            ],
            "fixed_version": "1.26.3",
            "advisory_count": 11,
            "oldest_advisory_days": 166
          },
          {
            "name": "github.com/yuin/goldmark",
            "direct": false,
            "version": "v1.7.13",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5320"
            ],
            "fixed_version": "1.7.17",
            "advisory_count": 1,
            "oldest_advisory_days": 14
          },
          {
            "name": "golang.org/x/text",
            "direct": false,
            "version": "v0.30.0",
            "severity": "unknown",
            "ecosystem": "go",
            "cvss_score": null,
            "advisory_ids": [
              "GO-2026-5970"
            ],
            "fixed_version": "0.39.0",
            "advisory_count": 1,
            "oldest_advisory_days": 7
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "unknown": 2,
          "critical": 2,
          "moderate": 1
        },
        "advisory_count": 48,
        "affected_count": 5,
        "assessed_count": 78,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "charm.land/bubbles/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.1.0"
        },
        {
          "name": "charm.land/bubbletea/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.0.7"
        },
        {
          "name": "charm.land/glamour/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.0.1"
        },
        {
          "name": "charm.land/lipgloss/v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.0.4"
        },
        {
          "name": "github.com/JohannesKaufmann/html-to-markdown",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.0"
        },
        {
          "name": "github.com/PuerkitoBio/goquery",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.9.2"
        },
        {
          "name": "github.com/anthropics/anthropic-sdk-go",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.27.1"
        },
        {
          "name": "github.com/bmatcuk/doublestar/v4",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v4.9.2"
        },
        {
          "name": "github.com/charmbracelet/x/ansi",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.11.7"
        },
        {
          "name": "github.com/creack/pty",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.24"
        },
        {
          "name": "github.com/hexops/gotextdiff",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.3"
        },
        {
          "name": "github.com/joho/godotenv",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.5.1"
        },
        {
          "name": "github.com/mattn/go-runewidth",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.0.23"
        },
        {
          "name": "github.com/openai/openai-go/v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.32.0"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.8.1"
        },
        {
          "name": "go.uber.org/zap",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.27.0"
        },
        {
          "name": "golang.org/x/term",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.40.0"
        },
        {
          "name": "google.golang.org/genai",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.58.0"
        },
        {
          "name": "gopkg.in/natefinch/lumberjack.v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v2.2.1"
        },
        {
          "name": "gopkg.in/yaml.v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        },
        {
          "name": "mvdan.cc/sh/v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.13.0"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "charm.land/bubbles/v2",
            "direct": true,
            "version": "v2.1.0",
            "ecosystem": "go"
          },
          {
            "name": "charm.land/bubbletea/v2",
            "direct": true,
            "version": "v2.0.7",
            "ecosystem": "go"
          },
          {
            "name": "charm.land/glamour/v2",
            "direct": true,
            "version": "v2.0.1",
            "ecosystem": "go"
          },
          {
            "name": "charm.land/lipgloss/v2",
            "direct": true,
            "version": "v2.0.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/anthropics/anthropic-sdk-go",
            "direct": true,
            "version": "v1.27.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/bmatcuk/doublestar/v4",
            "direct": true,
            "version": "v4.9.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/ansi",
            "direct": true,
            "version": "v0.11.7",
            "ecosystem": "go"
          },
          {
            "name": "github.com/creack/pty",
            "direct": true,
            "version": "v1.1.24",
            "ecosystem": "go"
          },
          {
            "name": "github.com/hexops/gotextdiff",
            "direct": true,
            "version": "v1.0.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/johanneskaufmann/html-to-markdown",
            "direct": true,
            "version": "v1.6.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/joho/godotenv",
            "direct": true,
            "version": "v1.5.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/mattn/go-runewidth",
            "direct": true,
            "version": "v0.0.23",
            "ecosystem": "go"
          },
          {
            "name": "github.com/openai/openai-go/v3",
            "direct": true,
            "version": "v3.32.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/puerkitobio/goquery",
            "direct": true,
            "version": "v1.9.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/spf13/cobra",
            "direct": true,
            "version": "v1.8.1",
            "ecosystem": "go"
          },
          {
            "name": "go.uber.org/zap",
            "direct": true,
            "version": "v1.27.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/term",
            "direct": true,
            "version": "v0.40.0",
            "ecosystem": "go"
          },
          {
            "name": "google.golang.org/genai",
            "direct": true,
            "version": "v1.58.0",
            "ecosystem": "go"
          },
          {
            "name": "gopkg.in/natefinch/lumberjack.v2",
            "direct": true,
            "version": "v2.2.1",
            "ecosystem": "go"
          },
          {
            "name": "gopkg.in/yaml.v3",
            "direct": true,
            "version": "v3.0.1",
            "ecosystem": "go"
          },
          {
            "name": "mvdan.cc/sh/v3",
            "direct": true,
            "version": "v3.13.0",
            "ecosystem": "go"
          },
          {
            "name": "cloud.google.com/go",
            "direct": false,
            "version": "v0.116.0",
            "ecosystem": "go"
          },
          {
            "name": "cloud.google.com/go/auth",
            "direct": false,
            "version": "v0.9.3",
            "ecosystem": "go"
          },
          {
            "name": "cloud.google.com/go/auth/oauth2adapt",
            "direct": false,
            "version": "v0.2.4",
            "ecosystem": "go"
          },
          {
            "name": "cloud.google.com/go/compute/metadata",
            "direct": false,
            "version": "v0.5.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/alecthomas/chroma/v2",
            "direct": false,
            "version": "v2.20.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/andybalholm/cascadia",
            "direct": false,
            "version": "v1.3.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/atotto/clipboard",
            "direct": false,
            "version": "v0.1.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/aymerick/douceur",
            "direct": false,
            "version": "v0.2.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/colorprofile",
            "direct": false,
            "version": "v0.4.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/ultraviolet",
            "direct": false,
            "version": "v0.0.0-20260525132238-948f4557a654",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/exp/slice",
            "direct": false,
            "version": "v0.0.0-20250327172914-2fdc97757edf",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/term",
            "direct": false,
            "version": "v0.2.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/termios",
            "direct": false,
            "version": "v0.1.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/charmbracelet/x/windows",
            "direct": false,
            "version": "v0.2.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/clipperhouse/displaywidth",
            "direct": false,
            "version": "v0.11.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/clipperhouse/uax29/v2",
            "direct": false,
            "version": "v2.7.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/dlclark/regexp2",
            "direct": false,
            "version": "v1.11.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/felixge/httpsnoop",
            "direct": false,
            "version": "v1.0.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-logr/logr",
            "direct": false,
            "version": "v1.4.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/go-logr/stdr",
            "direct": false,
            "version": "v1.2.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/golang/groupcache",
            "direct": false,
            "version": "v0.0.0-20210331224755-41bb18bfe9da",
            "ecosystem": "go"
          },
          {
            "name": "github.com/google/go-cmp",
            "direct": false,
            "version": "v0.7.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/google/s2a-go",
            "direct": false,
            "version": "v0.1.8",
            "ecosystem": "go"
          },
          {
            "name": "github.com/googleapis/enterprise-certificate-proxy",
            "direct": false,
            "version": "v0.3.4",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gorilla/css",
            "direct": false,
            "version": "v1.0.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/gorilla/websocket",
            "direct": false,
            "version": "v1.5.3",
            "ecosystem": "go"
          },
          {
            "name": "github.com/inconshreveable/mousetrap",
            "direct": false,
            "version": "v1.1.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/lucasb-eyer/go-colorful",
            "direct": false,
            "version": "v1.4.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/microcosm-cc/bluemonday",
            "direct": false,
            "version": "v1.0.27",
            "ecosystem": "go"
          },
          {
            "name": "github.com/muesli/cancelreader",
            "direct": false,
            "version": "v0.2.2",
            "ecosystem": "go"
          },
          {
            "name": "github.com/rivo/uniseg",
            "direct": false,
            "version": "v0.4.7",
            "ecosystem": "go"
          },
          {
            "name": "github.com/spf13/pflag",
            "direct": false,
            "version": "v1.0.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/tidwall/gjson",
            "direct": false,
            "version": "v1.18.0",
            "ecosystem": "go"
          },
          {
            "name": "github.com/tidwall/match",
            "direct": false,
            "version": "v1.1.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/tidwall/pretty",
            "direct": false,
            "version": "v1.2.1",
            "ecosystem": "go"
          },
          {
            "name": "github.com/tidwall/sjson",
            "direct": false,
            "version": "v1.2.5",
            "ecosystem": "go"
          },
          {
            "name": "github.com/xo/terminfo",
            "direct": false,
            "version": "v0.0.0-20220910002029-abceb7e1c41e",
            "ecosystem": "go"
          },
          {
            "name": "github.com/yuin/goldmark",
            "direct": false,
            "version": "v1.7.13",
            "ecosystem": "go"
          },
          {
            "name": "github.com/yuin/goldmark-emoji",
            "direct": false,
            "version": "v1.0.6",
            "ecosystem": "go"
          },
          {
            "name": "go.opencensus.io",
            "direct": false,
            "version": "v0.24.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc",
            "direct": false,
            "version": "v0.54.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",
            "direct": false,
            "version": "v0.54.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel",
            "direct": false,
            "version": "v1.29.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel/metric",
            "direct": false,
            "version": "v1.29.0",
            "ecosystem": "go"
          },
          {
            "name": "go.opentelemetry.io/otel/trace",
            "direct": false,
            "version": "v1.29.0",
            "ecosystem": "go"
          },
          {
            "name": "go.uber.org/multierr",
            "direct": false,
            "version": "v1.10.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/crypto",
            "direct": false,
            "version": "v0.40.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/net",
            "direct": false,
            "version": "v0.41.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/oauth2",
            "direct": false,
            "version": "v0.30.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/sync",
            "direct": false,
            "version": "v0.20.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/sys",
            "direct": false,
            "version": "v0.45.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/text",
            "direct": false,
            "version": "v0.30.0",
            "ecosystem": "go"
          },
          {
            "name": "golang.org/x/time",
            "direct": false,
            "version": "v0.6.0",
            "ecosystem": "go"
          },
          {
            "name": "google.golang.org/api",
            "direct": false,
            "version": "v0.197.0",
            "ecosystem": "go"
          },
          {
            "name": "google.golang.org/genproto/googleapis/rpc",
            "direct": false,
            "version": "v0.0.0-20240903143218-8af14fe29dc1",
            "ecosystem": "go"
          },
          {
            "name": "google.golang.org/grpc",
            "direct": false,
            "version": "v1.66.2",
            "ecosystem": "go"
          },
          {
            "name": "google.golang.org/protobuf",
            "direct": false,
            "version": "v1.34.2",
            "ecosystem": "go"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 78,
        "direct_count": 21,
        "indirect_count": 57
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 3,
        "merged_prs": 296,
        "open_issues": 8,
        "closed_ratio": 0.814,
        "closed_issues": 35,
        "closed_unmerged_prs": 35
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "yanmxa",
          "commits": 902,
          "avatar_url": "https://avatars.githubusercontent.com/u/19286664?v=4"
        },
        {
          "type": "User",
          "login": "hchenxa",
          "commits": 15,
          "avatar_url": "https://avatars.githubusercontent.com/u/10266685?v=4"
        },
        {
          "type": "User",
          "login": "ldpliu",
          "commits": 13,
          "avatar_url": "https://avatars.githubusercontent.com/u/56991288?v=4"
        },
        {
          "type": "User",
          "login": "zhfeng",
          "commits": 10,
          "avatar_url": "https://avatars.githubusercontent.com/u/1246139?v=4"
        },
        {
          "type": "User",
          "login": "zhujian7",
          "commits": 9,
          "avatar_url": "https://avatars.githubusercontent.com/u/36154065?v=4"
        },
        {
          "type": "User",
          "login": "wangke19",
          "commits": 7,
          "avatar_url": "https://avatars.githubusercontent.com/u/58931801?v=4"
        },
        {
          "type": "User",
          "login": "lonicerae",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/322491?v=4"
        },
        {
          "type": "User",
          "login": "onyx679",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/126763931?v=4"
        },
        {
          "type": "User",
          "login": "Karry2019web",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/51736839?v=4"
        },
        {
          "type": "User",
          "login": "Shaw529",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/39801161?v=4"
        }
      ],
      "contributors_sampled": 13,
      "top_contributor_share": 0.934
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "pages.yml",
        "release.yml",
        "stale.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": null,
            "reason": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 10,
            "reason": "all changesets reviewed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 5 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 24 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": 3,
            "reason": "dependency not pinned by hash detected -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "31 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "445f0c7a6a4ff2c716a2e508d4364ab000ac06c4",
        "ran_at": "2026-07-22T09:31:15Z",
        "aggregate_score": 5.8,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-22T06:07:11Z",
      "oldest_open_prs": [
        {
          "number": 266,
          "created_at": "2026-07-02T15:22:11Z",
          "last_comment_at": "2026-07-21T11:29:35Z",
          "last_comment_author": "san-ci"
        },
        {
          "number": 378,
          "created_at": "2026-07-22T05:12:36Z",
          "last_comment_at": "2026-07-22T05:12:54Z",
          "last_comment_author": "san-ci"
        },
        {
          "number": 380,
          "created_at": "2026-07-22T09:22:55Z",
          "last_comment_at": "2026-07-22T09:23:11Z",
          "last_comment_author": "san-ci"
        }
      ],
      "last_merged_pr_at": "2026-07-21T15:28:53Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 46,
          "created_at": "2026-05-23T00:48:01Z",
          "last_comment_at": "2026-05-24T15:53:17Z",
          "last_comment_author": "yanmxa"
        },
        {
          "number": 88,
          "created_at": "2026-06-03T10:23:47Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 156,
          "created_at": "2026-06-07T14:33:30Z",
          "last_comment_at": "2026-06-22T10:58:39Z",
          "last_comment_author": "yanmxa"
        },
        {
          "number": 209,
          "created_at": "2026-06-14T07:36:24Z",
          "last_comment_at": "2026-06-14T07:49:52Z",
          "last_comment_author": "yanmxa"
        },
        {
          "number": 297,
          "created_at": "2026-07-10T15:33:32Z",
          "last_comment_at": "2026-07-13T14:10:09Z",
          "last_comment_author": "hchenxa"
        },
        {
          "number": 309,
          "created_at": "2026-07-13T14:08:26Z",
          "last_comment_at": "2026-07-20T07:57:02Z",
          "last_comment_author": "hchenxa"
        },
        {
          "number": 310,
          "created_at": "2026-07-14T18:55:06Z",
          "last_comment_at": "2026-07-16T05:34:07Z",
          "last_comment_author": "yanmxa"
        },
        {
          "number": 314,
          "created_at": "2026-07-17T06:46:24Z",
          "last_comment_at": "2026-07-22T02:39:22Z",
          "last_comment_author": "yanmxa"
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/genai-io/san",
    "host": "github.com",
    "name": "san",
    "owner": "genai-io"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 73,
      "inputs": {
        "security": 66,
        "vitality": 86,
        "community": 66,
        "governance": 63,
        "engineering": 81
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 86,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 83,
            "inputs": {
              "commits_last_year": 979,
              "human_commit_share": 0.98,
              "days_since_last_push": 0,
              "active_weeks_last_year": 28
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "28/52 weeks with commits",
                "points": 19.4,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 28
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "979 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 979
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 24 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "releases_count": 100,
              "latest_release_tag": "v1.21.11",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 1.3
            },
            "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 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~1.3 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 1.3
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 0,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 0 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "moderate",
        "name": "Community & Adoption",
        "value": 66,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 44,
            "inputs": {
              "forks": 32,
              "stars": 70,
              "watchers": 3,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "below_threshold"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "70 stars",
                "points": 29.8,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 70
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "32 forks",
                "points": 12.4,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 32
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "3 watchers",
                "points": 1.7,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "excellent",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 92,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": true,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (Apache-2.0)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "Apache-2.0"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 13.5,
                "status": "met",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 63,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 34,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 13,
              "top_contributor_share": 0.934
            },
            "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 93% of commits",
                "points": 1.5,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 93
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "13 contributors",
                "points": 13.5,
                "status": "met",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 13
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 87,
            "inputs": {
              "merged_prs": 296,
              "open_issues": 8,
              "closed_issues": 35,
              "issue_closed_ratio": 0.814,
              "closed_unmerged_prs": 35
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "81% of issues closed",
                "points": 38.1,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 81
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "296/331 decided PRs merged",
                "points": 34.2,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 296,
                      "decided": 331
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "all changesets reviewed",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 45,
            "inputs": {
              "followers": 6,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "genai-io",
              "public_repos": 13,
              "account_age_days": 82
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "6 followers of genai-io",
                "points": 6.1,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 6,
                      "login": "genai-io"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "13 public repos, account ~0 yr old",
                "points": 8.8,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 13
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/genai-io/san"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "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 0 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "123 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 123
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 81,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "4 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "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": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "topics": [
                "ai-agents",
                "provider-agnostic",
                "llm",
                "coding-agent",
                "agent-harness",
                "claude-code",
                "cli",
                "golang",
                "mcp",
                "terminal",
                "tui"
              ],
              "has_wiki": true,
              "homepage": "https://genai-io.github.io/san/",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://genai-io.github.io/san/",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "11 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 11
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 66,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Branch-Protection, Packaging. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "branch_protection",
                    "packaging"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 58,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 5.8
            },
            "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": "internal error: error during branchesHandler.setup: internal error: some github tokens can't read classic branch protection rules: https://github.com/ossf/scorecard-action/blob/main/docs/authentication/fine-grained-auth-token.md",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "28 out of 28 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "all changesets reviewed",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 24 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 3",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "31 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): Indirect dependencies free of known advisories, No advisories left outstanding. Remaining weights renormalized. Matched 78 resolved dependencies against OSV. This repository publishes no package the index resolves, so the repository dependency graph was assessed instead. That graph mixes development and test pins with shipped dependencies, so only the declared runtime dependencies are scored; transitive findings are reported as context and excluded from the score. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "indirect_dependencies_free_of_known_advisories",
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_repository",
                "params": {
                  "assessed": 78
                }
              },
              {
                "code": "advisories_repo_graph_caveat",
                "params": {}
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 48,
              "affected_packages": 5,
              "assessed_packages": 78,
              "unassessed_packages": 0,
              "affected_by_severity": "critical 2, moderate 1, unknown 2",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "transitive set not separable from development and test dependencies in this scope",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_scope_not_separable",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 78,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 6
            },
            "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": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [
                "AGENTS.md",
                "docs/packages/2-feature/agent.md"
              ],
              "agent_instruction_max_bytes": 3518
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, docs/packages/2-feature/agent.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, docs/packages/2-feature/agent.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "98 of 98 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 98,
                      "sampled": 98
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.05,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0.02
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "5 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 5,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "2 of the last 100 commits are automated dependency updates",
                "points": 8,
                "status": "met",
                "details": [
                  {
                    "code": "dependency_bot_commits",
                    "params": {
                      "count": 2,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 49529,
              "source_files_sampled": 622,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/622 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 622,
                      "oversized": 0
                    }
                  }
                ],
                "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": [],
  "report_type": "repository",
  "generated_at": "2026-07-22T09:31:37.439685Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/g/genai-io/san.svg",
  "full_name": "genai-io/san",
  "license_state": "standard",
  "license_spdx": "Apache-2.0"
}

评分是信号,而非担保。 评分反映的是 GitHub 上公开可见的实践——不是代码审计,也不是安全保证。

缺失数据将被剔除并重新归一化权重,绝不按零分计。方法论已版本化并公开:指标 v1.13.0、模式 v0.26.0—— 完整方法论 · 指标知识库.

单项结果在整体记录中的位置: 汇总统计Go.