公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-26 22:42 UTC

andreicstoica / kit

Manage isolated Liftoff feature worktrees with a Bubble Tea TUI

Go自定义许可证★ 1 星标⑂ 0 复刻始于 2026年5月在 GitHub 上查看 ↗

andreicstoica/kit 的健康指数为 100 分中的 44 分,处于「存在风险」区间。 其得分最高的类别是Vitality(76/100),最低的是Security(13/100)。 最近一次更新在 2 天前。 近期的大部分工作由 1 位贡献者完成。

44
总分 / 100
存在风险

软件健康指数

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

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

评分画像

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

所有权

Andrei Stoica个人账户
13 关注者38 个公开仓库始于 2020年7月

该仓库由个人账户拥有。相较于组织支持的项目,单一所有者项目的延续性风险更高。

软件包生态系统

注册表软件包版本月下载量版本数最近发布
Gogithub.com/andreicstoica/kitv0.3.3-212 天前

按类别列示的指标

活力

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

76良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 2 天前
6.2/36提交节奏 — 52 周中有 9 周有提交
17.8/18提交量 — 最近一年 96 次提交
0/10OpenSSF Scorecard:Maintained — project was created within the last 90 days. Please review its contents carefully
所用输入
commits_last_year96
human_commit_share1
days_since_last_push2
active_weeks_last_year9

发布纪律

100优秀
评分方式
27/27有发布版本 — 已发布 12 个发布版本
36/36发布时效 — 最近一次发布版本于 47 天前
27/27发布节奏 — 约每 1.4 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count12
latest_release_tagv0.2.5
releases_from_tags
days_since_latest_release47
mean_days_between_releases1.4
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

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

21危急 · 占总体的 18%
评分方式
0/60星标 — 1 个星标
0/25复刻 — 0 个复刻
0/15关注者 — 0 位关注者
所用输入
forks0
stars1
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

44存在风险
评分方式
22.5/22.5README
16.9/22.5许可证 — 存在许可证文件,但不是可识别的许可证
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template

可持续性与治理

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

54中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
0/10OpenSSF Scorecard:Contributors — project has 0 contributing companies or organizations -- score normalized to 0
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
0/46.8议题解决 — 没有议题或无数据
38.2/38.3PR 接受 — 已裁定的 PR 中 13/13 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs13
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
已排除计分(无数据或不适用):议题解决。 其余权重已重新归一化。
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
8.2/25所有者影响力 — andreicstoica 有 13 位关注者
23.6/25既往记录 — 38 个公开仓库,账户约 6 年
所用输入
followers13
owner_typeUser
is_verified
owner_loginandreicstoica
public_repos38
account_age_days2,198
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — go 上有 1 个软件包
35/35发布时效 — 最近一次发布于 2 天前
20/20版本历史 — 21 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesgithub.com/andreicstoica/kit
ecosystemsgo
any_deprecated
min_days_since_publish2

工程质量

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

40存在风险 · 占总体的 20%

工程实践

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

文档

65中等
评分方式
30/30README
25/25文档目录
0/15文档 / 主页站点
10/10仓库描述
0/10主题标签
0/10Wiki
所用输入
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

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

13危急 · 占总体的 16%

安全态势

13危急
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 0 out of 8 merged PRs checked by a CI test -- score normalized to 0
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
0/10Dangerous-Workflow — 无数据
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.2/2.5许可证 — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — 无数据
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — 无数据
0/7.5Token-Permissions — 无数据
0/7.5Vulnerabilities — 12 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated14
scorecard_versionv5.5.0
checks_inconclusive4
scorecard_aggregate1.3
已排除计分(无数据或不适用):dangerous_workflow, packaging, signed_releases, token_permissions。 其余权重已重新归一化。

AI 就绪度

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

65中等 · 占总体的 0%
评分方式
0/45代理指令 — 没有 CLAUDE.md / AGENTS.md / 编辑器规则
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 96 次人类提交中有 93 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.969
agent_instruction_files
agent_instruction_max_bytes
评分方式
18/18一条命令的引导启动 — Makefile
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — Go(静态类型)
10/10可复现环境 — lockfile
10/10已体现的代理实践 — 最近 96 次提交中有 66 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
所用输入
has_nix
has_tests
lockfilesgo.sum
has_dockerfile
typed_language
bootstrap_filesMakefile
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0.688
toolchain_manifestsgo.mod
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — Go(静态类型)
55/55可控的文件大小 — 采样的 120 个源文件中有 0 个超过 60KB
所用输入
primary_languageGo
largest_source_bytes22,092
source_files_sampled120
oversized_source_files0

关键数据

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

数据采集警告

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

更多细节

OpenSSF Scorecard 1.3 / 10
1.3综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
0CI-Tests0 out of 8 merged PRs checked by a CI test -- score normalized to 0
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
不适用Dangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
9Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
不适用Packagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
不适用Token-PermissionsNo tokens found
0Vulnerabilities12 existing vulnerabilities detected
直接依赖 10
注册表软件包版本约束清单文件
Gogithub.com/BurntSushi/tomlv1.6.0go.mod
Gogithub.com/charmbracelet/bubblesv1.0.0go.mod
Gogithub.com/charmbracelet/bubbleteav1.3.10go.mod
Gogithub.com/charmbracelet/fangv1.0.0go.mod
Gogithub.com/charmbracelet/glamourv1.0.0go.mod
Gogithub.com/charmbracelet/harmonicav0.2.0go.mod
Gogithub.com/charmbracelet/huhv1.0.0go.mod
Gogithub.com/charmbracelet/lipglossv1.1.1-0.20250404203927-76690c660834go.mod
Gogithub.com/spf13/cobrav1.10.2go.mod
Gogolang.org/x/termv0.43.0go.mod
全部依赖 未采集

本报告未能采集到解析后的依赖集合:GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 2962,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Go": 488276,
        "Shell": 2376,
        "Makefile": 1263
      },
      "pushed_at": "2026-07-24T21:51:28Z",
      "created_at": "2026-05-08T19:23:28Z",
      "owner_type": "User",
      "updated_at": "2026-07-24T21:51:30Z",
      "description": "Manage isolated Liftoff feature worktrees with a Bubble Tea TUI",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": "NOASSERTION",
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": "https://andrei.bio/",
      "name": "Andrei Stoica",
      "type": "User",
      "login": "andreicstoica",
      "company": null,
      "location": "NYC",
      "followers": 13,
      "avatar_url": "https://avatars.githubusercontent.com/u/68513477?v=4",
      "created_at": "2020-07-19T18:06:06Z",
      "is_verified": null,
      "public_repos": 38,
      "account_age_days": 2198
    },
    "license": {
      "state": "custom",
      "spdx_id": null,
      "raw_spdx": "NOASSERTION",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.2.5",
          "kind": "patch",
          "published_at": "2026-06-09T15:53:54Z"
        },
        {
          "tag": "v0.2.4",
          "kind": "patch",
          "published_at": "2026-06-05T18:14:27Z"
        },
        {
          "tag": "v0.2.3",
          "kind": "patch",
          "published_at": "2026-06-05T17:28:59Z"
        },
        {
          "tag": "v0.2.2",
          "kind": "patch",
          "published_at": "2026-06-05T17:01:16Z"
        },
        {
          "tag": "v0.1.9",
          "kind": "patch",
          "published_at": "2026-06-03T17:53:53Z"
        },
        {
          "tag": "v0.1.8.1",
          "kind": "other",
          "published_at": "2026-06-02T14:52:31Z"
        },
        {
          "tag": "v0.1.8",
          "kind": "patch",
          "published_at": "2026-06-02T14:40:40Z"
        },
        {
          "tag": "v0.1.6.1",
          "kind": "other",
          "published_at": "2026-05-29T15:17:54Z"
        },
        {
          "tag": "v0.1.6",
          "kind": "patch",
          "published_at": "2026-05-29T15:05:08Z"
        },
        {
          "tag": "v0.1.5",
          "kind": "patch",
          "published_at": "2026-05-27T20:02:04Z"
        },
        {
          "tag": "v0.1.4",
          "kind": "patch",
          "published_at": "2026-05-27T16:07:05Z"
        },
        {
          "tag": "v0.1.3",
          "kind": "patch",
          "published_at": "2026-05-27T13:16:45Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "8bc26d12c7c9aea6b81ab422ff30a22a0268856b",
          "body": "`kit open` went straight to Herdr, so opening a worktree just to read code\nmeant starting a Herdr session. It now offers the same editor picker the rest\nof Kit uses — Zed first, then Cursor, the Ghostty workspace, and the Herdr\nspace last — and launches the chosen editor rooted at the worktree's che\n[…]\nand any agent inside it) starts on the right project.\n\n--editor/-e and --herdr skip the picker; --herdr preserves the old behaviour.\n\nCo-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(open): pick an editor or the Herdr space",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-07-24T21:51:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6a92978668942355fb94bc0227ae2e48650835f4",
          "body": "herdr 0.7.x returns `{\"id\":…,\"result\":{\"snapshot\":{…}}}`, but ReadHerdrState\nunmarshalled HerdrState from the top level. encoding/json ignores unknown\nfields, so it returned an empty state with no error — every workspace lookup\nmissed. Two visible symptoms:\n\n- `kit open`/`kit focus` reported \"Herdr \n[…]\nd\ntreats an envelope it cannot read as an error rather than an empty state so a\nfuture format change can't regress to a silent miss.\n\nCo-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(herdr): parse the enveloped `herdr api snapshot` response",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-07-24T21:44:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bb01ef5a0dca166431f959a8448cb9ffad801bf8",
          "body": "…ecovery\n\nrestart: after StopService, kill whatever still holds the service's port. A\n`uvicorn --reload` / Vite worker re-execs out of its recorded pid's process\ngroup, so StopService skipped the group-kill and only dropped the pid file,\nleaving the port bound. RunPlay then saw the port up, reported\n[…]\nokup.\nFallbacks run only after the existing path checks fail, so the happy path is\nunchanged. Adds parseWorktreePorcelain + tests.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: restart reaps reloaded servers; editor cleanup + lost-worktree r…",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-07-24T18:21:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "114db37dbb2222888abff9b6abf426a0b3f3222b",
          "body": "Use emoji and worktree names for Herdr root tabs.",
          "is_bot": false,
          "headline": "fix: match Herdr shell tab labels (#13)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-07-13T18:19:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f70e6df962bab0e2f541550e7fba1203c9a7fb8a",
          "body": "Integrate persistent Herdr workspaces behind Kit and update CLI/docs.",
          "is_bot": false,
          "headline": "feat: make Kit own Herdr workspaces (#12)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-07-13T16:26:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "79fca69d49813bfc8dabbfa391f96fefefa79c4f",
          "body": "RunSelect used a huh.Select that only supported arrows/enter, so the\nshort menus (root menu, Ghostty layout) behaved differently from the list\npickers — you couldn't press a number to choose. Replace it with a small\ninline bubbletea model matching listPicker: numbered option labels (1-9)\nplus 1-9 digit quick-pick, up/down/j/k, enter, esc/ctrl+c. Cancel still\nreturns huh.ErrUserAborted so callers' special-casing is unchanged.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(tui): numbered quick-pick in select menus",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-07-10T21:25:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5bbd06b534a7e79d2fbaadd2f1615d2462127c3f",
          "body": "Three bugs in the play/pause path:\n\n- `kit play --only celery` started the worker but not beat (the celery/\n  beat pairing was lost when --only overrode the toggle defaults). Now\n  selecting celery always carries beat, matching the toggle UI.\n- `kit pause --only celery` stopped the worker but orphan\n[…]\nis stale but the port is still bound. PausePlan carries\n  Ports for this.\n\nAlso dedupe parseServiceList so `--only app,app` can't double-start.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(play,pause): pair celery+beat, stop reloaded backends by port",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-07-10T21:25:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bf447cddafdbcff6cc074e3bc042877ff39f8e0c",
          "body": "Upstream liftoff-app switched Python dependency installs from pip to uv\n(#7677) and replaced black/isort/flake8 with ruff (#7676). Update kit to\nmatch:\n\n- InstallBackend runs `uv pip install --python <venv> …` instead of the\n  venv pip; the design step is now \"uv install backend\".\n- doctor gains a `\n[…]\n  `ruff` check (CheckWarn — kit doesn't invoke it, but backend dev/CI do).\n- README/ONBOARDING updated (requirements, setup walk, design step).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(design,doctor): use uv for backend installs + add uv/ruff checks",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-07-10T21:24:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "274d8039ce96f6c2b476c3a3fa41af133c372a30",
          "body": "Restart now rm -rf's a frontend's node_modules/.vite after stopping it\nand before re-spawning, so a stale dep-optimizer cache can't survive the\nbounce. That stale cache is the usual reason hot-module reload stays\nbroken — bouncing the process alone never cleared it. --keep-cache opts\nback into a pla\n[…]\nss\nworktrees; clearing it re-optimizes deps on the next dev start (and is\nwhy concurrent worktrees wedged HMR in the first place).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(restart): clear frontend Vite cache before bounce (#11)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-25T13:14:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bd634eddbd0e0ac8982b5cf2b076fc3d5d480f7f",
          "body": "Switch the default interactive diff viewer from lumen to hunk\n(github.com/modem-dev/hunk) — a desktop-style side-by-side viewer\nbuilt for agent-authored changesets.\n\n- diff: drive `hunk diff <ref>`, fall back to plain `git diff`\n- doctor: check for hunk (brew modem-dev/tap/hunk) in place of lumen\n- setup: offer to `brew uninstall lumen` when migrating\n- docs: update README references\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: use hunk instead of lumen for kit diff (#10)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-09T15:53:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0313cc549f05475b983c1cb69b8b3032e261f533",
          "body": "The Slack/README install steps weren't self-healing: `go install` puts\nkit in $(go env GOPATH)/bin, which isn't on PATH, so a bare `kit setup`\nhit \"command not found\" — and re-running the same steps looped, since\nnothing wired PATH. Add install.sh (curl | bash): installs Go + kit,\nappends the right \n[…]\nfix (and skipping\nconfig-write + workspace adoption). Track pending-restart fixes, print\na restart hint, and exclude them from the exit-1 gate.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(setup): one-line installer + don't fail on pending PATH fixes",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-05T18:13:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "04257956cc9b87e33460315a66a23e1862d678e6",
          "body": "Setup hardcoded ~/.zshrc, so bash users (whose login shell reads\n~/.bash_profile) never got the brew shellenv line. Detect the login\nshell via $SHELL and write to the matching rc; honor $ZDOTDIR for zsh.\n\nAdd a kit-path doctor check + fix: kit installs to ~/.local/bin /\nGOPATH-bin via go install / m\n[…]\nas a Claude Code session. New AppOnly field on\nEditorCandidate models app-only launch explicitly instead of relying\non a fake PATH binary name.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(setup): shell-aware PATH wiring + Claude Code desktop editor",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-05T17:28:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "358a8a189048393d9b3651f072bb5620860a53b6",
          "body": "Check alembic current after gt sync and upgrade when the liftoff DB is\nbehind head, not only when new migration files land in this sync. End\nkit sync with a one-line migration summary like the merged-wash check.\n\nCo-authored-by: Cursor <cursoragent@cursor.com>",
          "is_bot": false,
          "headline": "feat(sync): upgrade when DB behind, print status",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-05T16:59:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9d106e6d4cd345dce2f4990423d2f55fd8952130",
          "body": "Amp-Thread-ID: https://ampcode.com/threads/T-019e9340-61e5-705b-b924-e2abd5c8675a\nCo-authored-by: Amp <amp@ampcode.com>",
          "is_bot": false,
          "headline": "fix(update): quiet annotated tag checkout",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-04T16:04:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a9a46686adcc009bf885043bd8227470f6534ab0",
          "body": "Amp-Thread-ID: https://ampcode.com/threads/T-019e9340-61e5-705b-b924-e2abd5c8675a\nCo-authored-by: Amp <amp@ampcode.com>",
          "is_bot": false,
          "headline": "feat(tui): simplify workspace prompts",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-04T16:00:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eac75694d5455f32854864e01b5c040f3f8c8b42",
          "body": "Amp-Thread-ID: https://ampcode.com/threads/T-019e9340-61e5-705b-b924-e2abd5c8675a\nCo-authored-by: Amp <amp@ampcode.com>",
          "is_bot": false,
          "headline": "fix(sync): guard master alembic upgrade",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-04T15:37:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59f1ddbb3ae9187d3efb176e4bdfe053a31fd2a5",
          "body": "After `gt sync`, compare master HEAD before/after. If the\nfast-forward landed new Alembic version files\n(backend/api/migrations/versions), run `alembic upgrade head` in\nmaster's backend so the local master DB mirrors remote master and\nstays a clean base for worktree DB clones.\n\nDetection is a local \n[…]\n Alembic resolves via the existing venv (venvBin).\nAdd --no-migrate to skip; upgrade failure is surfaced without\naborting the merged-wash flow.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(sync): auto-run alembic upgrade head on new master migrations",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-04T15:27:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bd23a995077391be4514dfbe09d5913edfc4aa3a",
          "body": "…tion (#9)\n\nOnboarding\n- Add ONBOARDING.md walking any Liftoff employee (eng, designer, etc.)\n  through install -> kit setup -> doctor -> first kit design.\n- Add \"Open in Claude Code\" onboarding badge + pointer at top of README.\n\nDocs & help\n- Value-first README intro; document kit submit and kit sl\n[…]\nw anim.tape/anim.gif previewing the gallery (no worktree side effects).\n- Fix lineup.tape (kit formation -> kit lineup --tree); re-record gifs.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: onboarding guide + README/help refresh + harmonica anim unifica…",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-03T17:52:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "55b87d9867fa1d2a77dce364638d334fdaa9de9b",
          "body": "…ed (#8)\n\nThe previous gate (branchPushed) assumed an unmerged branch was never\npushed, but a worktree pushed before its first commit sits exactly at\nthe main tip with all work still uncommitted. `git branch --merged`\nlists it (its tip is an ancestor of main) and it has an upstream, so\nwash offered \n[…]\nh and masked the bug.\nSwitch it to --no-ff (matching real merge-commit/squash PRs that leave\nmain ahead) and add a pushedEmpty regression case.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(wash): don't flag a pushed branch sitting at the main tip as merg…",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-02T14:50:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f9e5e20be2e65493ba819f60aba17a0fd7b4f7c9",
          "body": "Replace the single penalty-kick \"orb\" with a pluggable Animation\ninterface over a shared fixed-size canvas (everything drawn into the\ngrid, so the box never changes dimensions — no layout shift). One of\nfive animations is picked at random per `kit design`:\n\n- soccer (polished): jumping crowd, ball s\n[…]\n't buried behind a focus-stealing window\n- stability test drives every animation through all phases, asserting\n  constant box size and no panic\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(design): random animation per design run + preview gallery (#7)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-02T14:37:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7378d7e15848a0525d48ce3338f397cc00560462",
          "body": "`git branch --merged` lists every branch whose tip is an ancestor of\nmain, including freshly created worktrees that never diverged — so\n`kit wash` treated a just-made, not-yet-pushed worktree as merged and\noffered to remove it. Gate the local heuristic on the branch having an\nupstream (branchPushed)\n[…]\n) and covers branchPushed,\nmergedBranches, FindMergedWorktrees (the regression), and the\nworktree-location helpers Name/IsMaster/ListWorktrees.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(wash): don't flag unpushed worktrees as merged (#6)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-02T14:36:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d245fa078d11ba6fefb079b31ea2334d6e19d6e5",
          "body": "Master rides slot 0 by convention (master port defaults), but the\n`Slot == 0` guard read that as \"unallocated\" and rejected master with\n\"has no slot — run `kit play master` first\", so a running master could\nnever be bounced.\n\nExtract resolveSlot() which exempts master, and route restart + log\nensurePlaying through it. Add table tests covering master (incl. nil\ncfg), feature worktrees, slot-0, and unknown names.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: kit restart/log reject master worktree",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-06-01T20:19:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "49a56813ea07d73b99d6fde766ce0b306f1935a2",
          "body": "The background update check compared the cached remote tag to the current\nversion with plain string inequality, so a build ahead of a stale cached tag\nprinted a backwards hint: \"kit v0.1.5 available (you have v0.1.6)\". It also\ncompared lexically, so v0.1.10 looked older than v0.1.9.\n\nAdd a field-by-\n[…]\nparseable versions stay silent. `kit update` itself was already correct\n(it sorts tags via git -v:refname); this only fixes the passive banner.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(update): only nudge when the remote tag is actually newer",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-29T15:17:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4ba5949196d39db4d29ae0f5a17b9bb5a80400f1",
          "body": "`celery beat` writes its schedule shelve (celerybeat-schedule.{db,dir,bak})\ninto its working directory, which kit sets to the worktree's backend/. The\nfile then shows up as untracked junk in `git status` after `kit play`.\n\nPass `--schedule` pointing at the kit run dir (~/.config/kit/run/<name>/)\nso beat's state lives alongside the other per-worktree runtime files and\nnever touches the repo.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(play): keep celery beat's schedule file out of the worktree",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-29T14:51:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8809ea4a1bb565ba9eecfda220df596a1fa54093",
          "body": "main() called RenderMarkdownLongs() on every invocation, walking the whole\ncommand tree and spinning up a glamour renderer per command — wasted work on\nthe hot path (`kit play`, `kit log`, shell completion) where no help is shown.\nNow it's a no-op unless argv contains -h/--help/help, and a single gl\n[…]\nuses the shared RunConfirm (last\n  standalone confirm that bypassed it).\n- Makefile build pins CGO_ENABLED=0 for a static, reproducible binary.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf: render help markdown only when help is requested",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-29T14:48:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "16654fda07af46f48d3b0d3ce3917878fb441164",
          "body": "`kit guide` was a static glamour-rendered walkthrough that duplicated the\nREADME and per-command help. Drop it: delete cmd/guide.go, its menu entry,\nits first-run bypass entry, and the README section. glamour stays (help.go\nstill renders command help).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: remove the guide command",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-29T14:48:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "66be2dae7943f6bc4737c0e81c2fa06df623120c",
          "body": "wash built its list with a hand-rolled delegate + title styling and its\nitems carried no emoji, so `kit wash` rendered worktrees noticeably\ndifferently from `kit play`/`pause`. Route it through the shared\nNewListDelegate + StyleList and add the worktree emoji, matching the\nidx → emoji → name layout \n[…]\ntab\ntags) since those differ by intent — but the list chrome, numbering, emoji,\nand keybindings are now identical across every worktree picker.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(tui): unify wash picker chrome with play/pause",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-29T14:41:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ae0d89ed449f13871b14e06cbc6db9d618a0c84d",
          "body": "`wash` (aliases rm/remove/delete) tears down a kit but was missing from the\ninteractive `kit` menu, so it was undiscoverable without knowing the verb.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(menu): add wash (remove) to the root command menu",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-29T14:37:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a25c29fa3dd488f9b06bc6e86dbc6675013a701f",
          "body": "Unify kit's interactive UI behind three shared primitives so the same kind\nof action looks and behaves identically across every command:\n\n- internal/tui/ui.go: central design-language tokens — shared list delegate,\n  title style, and kit huh theme. One place to restyle every prompt.\n- internal/tui/p\n[…]\nAdds tests: list picker key handling, forms first-frame visibility, editor\nresolution/LoneEditor, workspace open routing, and orb layout width.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(tui): consolidate menus, selects, and workspace-open",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-29T14:10:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4d0b33a5c83ce089bcd904b1a3e406f85bd2e570",
          "body": "Play / ports:\n- RunPlay skips services already listening instead of spawning a duplicate\n  that can't bind the port (the cause of the hung `kit play`).\n- PortListening/portBindable now check both 127.0.0.1 and [::1]; Vite binds\n  IPv6 [::1], so the IPv4-only check reported it dead and triggered the \n[…]\nibe suffixes compare by base tag.\n- Daily, cached, TTY-only \"update available\" nudge — silent in scripts,\n  completion, and local dev builds.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(play,update): idempotent play, IPv6-aware ports, self-update",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-27T20:00:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8c1c9f11a641d6951773c1120b11f47328e79751",
          "body": "Safety fixes:\n- StopService refuses to kill a recycled PID (start-time + group-leader\n  guard) so a stale pid file can't nuke an unrelated process group.\n- All config.toml read-modify-writes go through WithConfigLock (flock),\n  preventing slot-collision/clobber under concurrent kit processes.\n- kit \n[…]\n-w/--workspace (+ -d) replaces kit warmup; gtab now a swap alias.\n- prune internals renamed to merged (RunMergedWashTUI, MergedCandidate, …).\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(cli): harden services/config + consolidate commands",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-27T16:06:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8f3227853f359d5e3f236eca88343045d0c38385",
          "body": "Wrap PickGtabLayout select in an explicit huh.Form with WithTheme so\ngroup.WithHeight(rawHeight()) fires at construction time. Without it the\ngroup viewport height stays 0 on the initial frame and options are\ninvisible until the first keypress.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(design): show layout options on first render",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-27T13:16:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "54450369c642245b87d8065da06faae4e2d82353",
          "body": "Both demos showed in-progress Liftoff feature work that shouldn't\nbe public. Tapes stay so a coworker with the repo cloned can\nre-render locally if needed.",
          "is_bot": false,
          "headline": "docs: drop design.gif + lineup.gif",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T22:26:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aefff18dba81b2d3df0f64ed94b784edcef18442",
          "body": "Removed demo GIF from README.",
          "is_bot": false,
          "headline": "Remove demo GIF from README",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T22:24:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "38e7eccbbe7da27fa022368f16781260ad9eddb7",
          "body": "NewPlayModel + buildPauseItems were calling WorktreePath/LegacyWorktreePath\ndirectly, which produce $ROOT/master and $ROOT/liftoff-master — neither\nactually exists. Master lives at layout.Master. Switched to the shared\nLayout.ResolveWorktreePath helper so `kit play master` and `kit pause\nmaster` work as expected.",
          "is_bot": false,
          "headline": "fix(play,pause): resolve master path correctly when passed as arg",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:55:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fa2c9b70ef7830639b06474cc8ffb77e5d4501b8",
          "body": "Lineup view, tree view, play picker, and gtab tab title all rendered\nmaster with different emojis (🚀 hardcoded vs 🧊 from EmojiFor's\nhash). Centralized via liftoff.MasterEmoji + an early-return in\nEmojiFor(\"master\") so every surface agrees on 🧊.\n\nAlso dropped 🪲 from the random-fun hash pool. ew.",
          "is_bot": false,
          "headline": "fix(emoji): consistent 🧊 for master; drop 🪲 from hash pool",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:46:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7ffe456558e2345ab49642871ee1b41be4339feb",
          "body": null,
          "is_bot": false,
          "headline": "fix(swap): give master the same gtab layout pick as worktrees",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:42:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "049f24af9092435a982dda0356ed781084210caa",
          "body": "Ghostty launches gtab tabs with `bash --noprofile --norc`, which\nskips ~/.zshrc / .bashrc — so the user's `~/.local/bin` (or\n`$(go env GOPATH)/bin`) PATH addition never loads, and a bare\n\\`kit log <name> --wait\\` errors with \\\"kit: not found\\\".\n\nResolve the running binary via os.Executable() at temp\n[…]\nate-write\ntime and embed the absolute path in both the simple and detailed\ngtab templates. Falls back to bare \\`kit\\` if Executable() fails\n(better-than-nothing for users whose system PATH covers it).",
          "is_bot": false,
          "headline": "fix(gtab): use absolute kit path so logs tab finds the binary",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:30:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "16c08eb9b66d18fe075877a93a5e9d21c664433d",
          "body": null,
          "is_bot": false,
          "headline": "ux(swap): label Ghostty option as '(pick layout next)'",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:28:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e0c82578e6890ff556c943133c08c7248d3e2ec0",
          "body": "- Restore master in the play + pause pickers. Master has slot 0 by\n  design (ports 3000/3001/9000/9001/9002); play special-cases name\n  == \"master\" to skip the adopt prompt and use those ports directly.\n- Split resolveArgOrCwd master handling: play/pause skip master from\n  cwd (so running from the m\n[…]\nvice .log files to tail.\n- README: added an ELI5 services table for designers — what each of\n  app/admin frontend, app/admin backend, celery, beat, mcp actually\n  is and which port pattern it runs on.",
          "is_bot": false,
          "headline": "feat(swap,play): master in play + gtab layout pick on swap→Ghostty",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:25:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a6cec3c3f435c458fe2e65fb8e708a0f63e8a1b8",
          "body": null,
          "is_bot": false,
          "headline": "docs(vhs): re-render design.gif with full wizard + follow-up prompt",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:22:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2cf6b5933af56a5ed13915452d368d12a0750605",
          "body": "A previous commit dropped master from collectPlayWtItems to keep it\nout of the play picker, but that helper is also the source for the\ngeneric worktree picker (swap, warmup, links, log) — so master\nsilently disappeared from every list.\n\nRestore the original semantics: collectPlayWtItems includes master\n(with the 🚀 emoji + \"master\" name). Play and pause now pass a\ndropMaster filter; the generic picker passes nil and gets master\nback.",
          "is_bot": false,
          "headline": "fix(pickers): keep master in swap/warmup/links/log lists",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:20:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "959d08bff32a3c03d3f6b8939ee603cf911e801d",
          "body": "readme:\n- cheatsheet column-aligned to col 26; new `--detailed` warmup hint\n- design step list matches the current 4-prompt form (dropped the\n  stale backend-deps / gtab prompts); names the follow-up flow\n- play output block adds the celery beat row that's emitted now\n- log keys promoted to an align\n[…]\nns with defaults), hides the\n  long dress steps, then captures the simple/detailed/skip prompt\n  + play prompt. Leaves a real `vhs-demo` worktree; comment notes\n  the `kit wash vhs-demo` cleanup step.",
          "is_bot": false,
          "headline": "docs(readme,vhs): trim, realign, capture full design wizard",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:18:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b8666f48cb075de5d20eac4ceb1b8a3a7a2fa0c9",
          "body": "Four call sites (diff, submit, swap, warmup) duplicated the same\nmaster/canonical/legacy fallback dance for resolving a kit name to\nits on-disk dir. Pulled into a single Layout method so the rules\nlive in one place and callers shrink to a one-liner.",
          "is_bot": false,
          "headline": "refactor(paths): extract Layout.ResolveWorktreePath",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:12:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7622aaa5e47c6065ae84450e70076e53e5d8f0cb",
          "body": "- ensureRunDir now iterates liftoff.DisplayServices instead of a\n  hardcoded literal that drifted from the canonical list.\n- offerNextSteps uses huh.NewSelect[liftoff.GtabLayout] directly\n  with GtabSimple/GtabDetailed/\"\" instead of stringly-typed\n  \"simple\"/\"detailed\"/\"skip\" + a re-translation step\n[…]\n can't drift.\n- Drop the dead `_ = time.Second` (and the now-unused time import)\n  in washflow.\n- Refresh collectPlayWtItems doc comment to match current behavior\n  (master is dropped, not folded in).",
          "is_bot": false,
          "headline": "chore: review fixups — dedupe service list, type the gtab choice",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:08:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7889978d5e6ff2d567417f513ae40ce41d6ea5c9",
          "body": "The gtab logs tab was a bare `tail -F file1 file2 …` stream. That\nlost the color-coded service tags, search, follow toggle, and tag\nfilter that `kit log` provides. Wired it up to `kit log <name>\n--wait`:\n\n- log.go: new `--wait` flag skips the \"nothing playing\" guard and\n  pre-creates the run dir + e\n[…]\nwhen it doesn't\n  exist yet, so empty pre-touched files behave like real ones once\n  play starts writing.\n- gtab.go: simple + detailed templates both invoke `kit log <name>\n  --wait` for the logs tab.",
          "is_bot": false,
          "headline": "feat(log): --wait flag; gtab logs tab now runs the styled viewer",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T21:02:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "572df1ab03dc99eb67ab0c4269c2bcadcdbaa480",
          "body": "design summary view:\n- skipped steps no longer render at all (was confusing — pending and\n  skipped used very similar markers)\n- next: block removed (the post-success prompts run kit play / open\n  ghostty for you)\n- footer reads \"press enter to continue\" instead of \"exit\" since the\n  next prompt is \n[…]\nplaceholder rows entirely. If the DB\n  doesn't exist or the gtab file is missing, those toggles don't\n  appear. Cursor + toggle keys now map to the visible rows\n  dynamically instead of hardcoded 0/1.",
          "is_bot": false,
          "headline": "ux(design,wash): hide skipped/unneeded rows, simple|detailed gtab prompt",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:56:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "aaff972262d3a2acb6a002feca20cd916175137d",
          "body": "Default stays simple (shell + combined logs). `kit warmup --detailed`\nrestores the per-service tail panes for devs who want to watch each\nservice stream side-by-side, and tacks on a combined logs tab on top.\nREADME updated to describe both layouts.",
          "is_bot": false,
          "headline": "feat(warmup): --detailed flag for 5-tab gtab layout",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:53:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a45ff775c5d2c085ca6404e1acd557950ecccae6",
          "body": "- warmup: always rewrite the .applescript instead of skipping when\n  one exists. The old 4-tab layout was sticking around on existing\n  worktrees and re-running `kit warmup` had no effect.\n- play picker: drop master from the kit list — master has no slot\n  and isn't a valid play target.\n- viewRun: pull the trailing \\n out of StyleDim.Render so the\n  \"replaced …'s celery\" line doesn't bleed wide-padding into the\n  next row's marker.",
          "is_bot": false,
          "headline": "fix(warmup,play): regen gtab + drop master from picker + line fix",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:50:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "10e41342bf0a8383e614d6aacc94a64aa4f4fe4f",
          "body": "`kit play` runs servers in the background and writes their stdout to\n.log files, so the old 4-tab Ghostty layout (root + frontend split +\nbackend split + celery) was just four separate `tail -F` panes. One\ncombined `tail -F` tab covers every service, and frees the root tab\nfor the real work (Claude, git, ad-hoc shells).",
          "is_bot": false,
          "headline": "refactor(gtab): collapse 4 service tabs into 1 combined log tab",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:47:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "477b7b44b519ff70c2352223cd627eb5db08a3f7",
          "body": "design:\n- stopwatch now freezes at completion instead of running forever\n- drop `cd <path>` from the next: cheatsheet (not needed when the\n  follow-up \"open ghostty?\" prompt opens the workspace for you)\n- ask both follow-up yes/no questions up front, then act — was\n  opening ghostty between question\n[…]\npt\n  feel like an interruption\n\nplay/pause/wash: passing `master` as an explicit arg now errors\nwith \"master isn't a kit — pick a worktree instead\" instead of\nthe cryptic \"Worktree not found: master\".",
          "is_bot": false,
          "headline": "ux(design,play): stop timer, batch follow-ups, reject master arg",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:45:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2e71dae78df50cdb7f5990276f67c6db29431807",
          "body": null,
          "is_bot": false,
          "headline": "feat(menu): add formation to root picker",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:42:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2dd80aa26bbd38770f73693c34ddfc46c0da0dc9",
          "body": null,
          "is_bot": false,
          "headline": "chore: trim verbose comments",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:38:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d678e1c8f62f68b9f2ae138a827e114e9cecca84",
          "body": "`kit play` from inside the master dir was resolving cwd to `master`\nand then failing in the play TUI (master has no slot, no isolated\nservices). Same trap on `kit pause` and `kit wash` — master is never\na valid target for any of them. Added a non-master cwd resolver and\nwired play/pause/wash to it s\n[…]\nter now\nfalls through to the picker.\n\n`kit log` used to open the viewer even when no services were alive,\nshowing stale lines that never updated. Now blocks with a hint to\nrun `kit play <name>` first.",
          "is_bot": false,
          "headline": "fix(play,log): skip master from cwd; block log when nothing playing",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:37:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "13bcab337ce98d513fdc29c9a46249abf815f27a",
          "body": "- log viewer: \"follow\" → \"auto-scroll\", \"services\" panel → \"filter\n  services\", celery vs beat now render as distinct rows (\"celery\n  worker\" / \"celery beat\") so it's not two `[celery]` entries.\n- service Label(): full \"frontend\"/\"backend\" everywhere (was\n  `app_front`/`admin_back`). Affects play picker, allocated URL\n  grid, formation tree, pause picker. Bumped padding to fit.\n- README: updated service-name examples + port table.",
          "is_bot": false,
          "headline": "refactor(ui): clearer log/service labels for designers",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:31:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a3bedcc26fac2d2412e1a30bde6f4050cb45d33a",
          "body": "README cheatsheet, subcommands, and roadmap now reference\n`kit formation` (alias `tree`) instead of the deprecated\n`kit lineup --tree` flag. lineup.tape demo updated. New\ndesign.tape captures the wizard intro (aborts before creating\na real worktree).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme,vhs): rename --tree → `kit formation`, add design demo",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:26:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "170b1f2dc8267f6c7e42a04613591691375b8bf8",
          "body": "The post-design huh.MultiSelect was confusing and at least some\noptions didn't fire the way the user expected. Replaced with two\nsequential huh.NewConfirm prompts: \"Open the Ghostty workspace?\"\nthen \"Start dev servers?\". Each defaults Yes. Esc skips remaining\nprompts. Browser-open option dropped — open in the new Ghostty\ntabs or via `kit links` later.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ux(design): sequential yes/no follow-ups instead of multi-select",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:24:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2956fe7cd21e88f8c5abb0f72c44bafe1b38f8d3",
          "body": "`kit lineup --tree` was hidden behind a flag. Promotes the tree to a\nfirst-class command with a soccer-themed verb (formation = how the\nteam lines up positionally) plus a plain `tree` alias for muscle\nmemory. `kit lineup` drops the --tree flag.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: `kit formation` (alias `tree`) — tree view as its own command",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:23:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cbf178322f9923223c66f3b34fd4fcdb550b0074",
          "body": "`t` opens the services-filter overlay, but tagOrder was only\npopulated as log lines streamed in. If a service had no recent\noutput (or kit log was opened before any lines arrived), the panel\nshowed an empty list. Now seeds the panel from the run dir's\n`.log` filenames at startup so every known service appears\nimmediately, all default-on.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(log): pre-populate tag panel from existing .log files",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:20:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f099727a5edd88cd424437982015fd6fceabbf0d",
          "body": "  db        shared (liftoff)     → shared from master\n  frontend  real node_modules    → own copy\n  frontend  symlinked from master → symlinked to master\n\nReads as a relationship to master rather than as kit jargon.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ui(tree): friendlier labels for db / frontend rows",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:19:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7d667c035ea406ad861bbde5f4e4be15e1f02316",
          "body": "`uvicorn --reload` re-execs into a fresh process when a Python file\nchanges, killing the PID kit recorded at startup. lineup's running\ncount was stuck at 3/5 because api + admin_be both showed \"dead PID\"\neven though the backends were healthy on :9010 / :9011.\n\nIsServiceAlive now treats port-listenin\n[…]\n PID\nliveness only fronts for celery/beat (no ports). Recorded PIDs\nremain useful for `kit pause` to know which process to signal.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(lineup): port-listening = truth for service liveness",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:18:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c8ee4964301d9e6db1b895fb5d4e95fafa905f77",
          "body": "Tree view now shows two extra signals per worktree that previously\nrequired running psql / ls -la to discover:\n\n  setup\n  ├── ● db        liftoff_google_agent     (has its own DB)\n  └── ● frontend  symlinked from master    (or `◇ real node_modules`)\n\nAlso fixes liftoff.HasDB — psql needed `-d postgres` to connect when\nthe user's $USER database doesn't exist; that's why the DB column\nwas silently always-false.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(lineup-tree): \"setup\" sub-node — DB ownership + node_modules wiring",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:16:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "479ac429d49e0fe6164dbcb9dd01b518f9ba3794",
          "body": "After a successful kit design, multi-select prompt offers the three\nfollow-ups people usually run next:\n\n  [ ] Open Ghostty workspace  (kit warmup)\n  [ ] Start dev servers       (kit play)\n  [ ] Open frontend URLs in browser\n\nEsc / empty selection skips. Gtab runs first so the workspace is\nopen when servers boot. Browser launches frontend/app + frontend/admin\nURLs from the new slot.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(design): post-success \"anything else?\" prompt",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:13:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "35efefa44cd5851df779f1ffc36572edfb4a6da2",
          "body": "Score was appended to row 0, jutting out next to the goal frame and\ncramping the right edge. Moved it under the grid + centered to the\ngrid width, like the bottom-of-screen scoreboard in old arcade\npenalty kick games.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ui(orb): center the score under the shooter (arcade style)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:08:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f60e4659566a8078d052adc9570ee2dcb25e687f",
          "body": "- pip install was failing because exec.Command(\"pip\", …) hit $PATH\n  and kit's shell doesn't have the venv activated. Now resolves to\n  $KIT_PY_VENV/bin/pip (falls back to bare \"pip\" when the venv path\n  isn't present, so non-Liftoff invocations still work).\n- Orb panel Padding(0,1) → Padding(1,2) so the goal posts breathe\n  inside the rounded border.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: pip via venv path + orb panel padding",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:07:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "53db544e536c493ae12a98211991f3a5ed148d0c",
          "body": "- FetchMain now `git fetch origin <main>` (no refspec). AddWorktree\n  branches off `origin/<main>` rather than the local main ref. Old\n  refspec form failed with exit 128 when local master was checked\n  out (master worktree on a feature branch, etc.).\n- Orb panel width bumped from 30 to 38 (height 14 → 16) so the\n  GOAL!/SAVE! flash next to the grid has room.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(design): robust master fetch + roomier orb",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T20:05:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e367a6fecda96ae0989b459961dca21858f6818e",
          "body": "huh's NewForm groups questions; one group = one screen. Each\nconfirm now lives in its own group so designers see prompts one at\na time instead of a wall of pink/grey buttons.\n\nDefaults:\n- Clone DB: No by default (heavy disk use; opt-in)\n- Backend deps: no longer prompted — always installed automatically\n- Symlink node_modules: Yes (unchanged)\n- Track in graphite: Yes (unchanged)\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ux(design): one prompt per screen + saner defaults",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T19:59:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "58b7598781d0af2e2735775e4169912987aef892",
          "body": "Source-available license that allows internal business use while\nbarring third-party redistribution / commercial use. Better fit\nthan MIT for a tool meant to stay close to the Liftoff team.\n\nFull text inline; README pointer updated.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(license): switch from MIT to PolyForm Internal Use 1.0.0",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T19:55:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e05187415401266344e35a03eef94777ed105a4e",
          "body": "…kit setup`\n\nCoworkers without Go on their machine were stuck — now the install\nsection spells out the brew install, PATH export, then `go install`\n+ `kit setup` as the canonical path. Clone-and-make-install stays\nas the contributor alternative.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): lead with `brew install go` + `go install …@latest` + `…",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T19:45:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "def0737e2c655205151486cfd6c889499d1b970f",
          "body": "Corrected punctuation and formatting in README.",
          "is_bot": false,
          "headline": "Fix formatting in README.md for clarity",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T19:45:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "db59cf81f81bea02fe595f4d5ca013e725e16175",
          "body": "Updated README to clarify command usage and improve wording.",
          "is_bot": false,
          "headline": "Revise README for clarity and command updates",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T19:42:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "05d6787c6b6efef22df420f954affc2d82ee2c55",
          "body": "…lf-test (#5)\n\nFour polish features for v0.1.0:\n\n- **Dynamic tab completion** on every name-arg command. Cobra\n  ValidArgsFunction reads config.Worktrees + git worktree list and\n  returns matching names. Adopt completes only unmanaged candidates.\n- **`kit submit [name]`** wraps `gt submit` in the wo\n[…]\n,\n  PortsBindable(99), ListWorktrees, run-dir write. Catches \"kit\n  installed but env broken\" issues that the static audit misses.\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: dynamic completion, kit submit, kit slots renumber, doctor --se…",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T19:39:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dca668b0d2b93611e8185932c0601759e82687fa",
          "body": "* refactor: state.toml → config.toml + Settings block\n\n- Renames internal/liftoff/state.go → config.go. `State` kept as a\n  type alias for backwards compat.\n- Adds Settings struct (Root, MasterDir, GtabDir, MainBranch, PyVenv,\n  Editor, LiftoffRepo) — written by `kit setup`, hand-editable.\n- Worktre\n[…]\none-liners where the meaning was\nalready obvious.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: config.toml + kit adopt + bulk-adopt in setup (#4)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T19:30:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fe3dad31da4e9a3f15293039e28697a0e0337485",
          "body": "…olveTarget everywhere (#3)\n\n* fix(wash): delete the actual branch, not the kit name\n\nWashPlan kept only the kit-normalized name (e.g. \"voice-agent\") and\npassed it to DeleteBranch. Worktrees on branches like\n\"acs/voice-agent-cleanup\" silently no-op'd or deleted the wrong\nbranch.\n\n- Add Branch field \n[…]\n\n`kit links` likewise gains arg + picker support.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix+refactor: wash branch bug, doctor read-only, design name arg, res…",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T17:03:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b43405b54b760b83a268fca74824f7bf4632aed1",
          "body": "* chore(naming): rename `kit dress` → `kit design` in user-facing strings\n\nThe cobra command is `kit design`, but four error/empty-state strings\nstill said `kit dress`. New users following the README would hit\n\"unknown command 'dress'\". Internal DressPlan struct kept as-is with a\ncomment to flag the\n[…]\ntree): unbold current branch, keep Liftoff purple\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: kit doctor + kit setup (onboarding bootstrap) (#2)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T16:52:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0dd4e25652c938d314f2508e82c1f3ee1a9c733e",
          "body": "* feat(swap): include master in kit picker\n\n`kit swap` picker now shows master (the main repo) as a first-class\nentry so users can `kit swap` → master → editor without remembering\nthe special path.\n\n- shown as 🏠 master (special emoji, always first row)\n- path resolves to layout.Master\n- TouchLastUse\n[…]\nyIdx field on playWtItem (missed in prior commit)\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(swap): include master in kit picker (#1)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T15:52:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "947b44f57970239d0f7d9f8afc8fe311a5713f07",
          "body": "Squash of today's 4 commits:\n- single-arg `kit swap zed` reads as editor when cwd is a worktree\n- ldflags inject `git describe` into `kit -v`\n- drop second positional, use `-e/--editor` flag, always pickers when\n  arg/flag absent (per clig.dev + johnlindquist/worktree-cli)\n- cache appBundleExists results, delete dead worktreeFromCwd\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(swap): rework arg shape, ldflags version, app-bundle detection",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-11T13:57:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f1f7c5658beb21b692de9e46a51d481423170b5d",
          "body": "`code` on PATH is commonly a shim from another tool (e.g. Cursor),\nnot VS Code itself, so detecting \"VS Code installed\" via PATH alone\nis misleading. Same risk for `zed`. Switch detection to: known\neditors require the .app bundle in /Applications; if both bundle and\nbinary exist, prefer the binary (\n[…]\npresent but `zed` binary missing → was hidden.\nFixes: VS Code.app absent but `code` shim present → was shown as\ninstalled VS Code.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(swap): require .app bundle for known editor detection",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T22:32:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f4d60ab7f0f61843dc1974de2cb418b26c2bbf66",
          "body": "`kit swap` (zero args) now opens two pickers:\n1. pick a kit (from worktrees)\n2. pick an editor (from zed/cursor/code that are actually installed)\n\nIf only one editor is installed, the editor picker is skipped.\n1+ args fall back to today's behavior (auto-pick editor or use the\npositional one).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(swap): two-step picker for no-arg flow (worktree → editor)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T22:29:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0ee59ea925df0479494c25c1a5fcb572a6d38a2b",
          "body": "\"pick a kit to put on\" reads as a wardrobe action, matching the\noverall design (`kit dress`, `wash`, `tear`).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ux(play): retitle picker to fit kit metaphor",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T22:26:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7e4c04978922d51b0eb3ab1c71778ecaa3f75ec4",
          "body": "`kit swap` with zero args now opens a Bubble Tea picker listing every\nworktree (sorted by last-used). Pick → opens in default editor.\n\nArgument forms:\n- `kit swap`                    picker → default editor\n- `kit swap <name>`             default editor\n- `kit swap <name> <editor>`    forces the editor\n\nAdds tui.PickWorktree() helper for reuse by future commands that want\nthe same picker UX.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(swap): no-arg opens picker",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T22:26:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3cab0a41eefd8a42c83f293912af322faf600ee3",
          "body": "Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ux(design): clarify name-field hint wording",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T22:24:21Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2728c699f3943c26ffffd330b1211514f57aa431",
          "body": "The \"liftoff- prefix is stripped\" detail is implementation trivia; users\ncare more about what the name is actually *used* for downstream.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "ux(design): swap name-field hint to something more useful",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T22:23:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "80baaebe1a0f70f42e1db252787738bb321e2e85",
          "body": "- Requirements table: required vs optional tools so teammates can\n  audit before install. Optional ones auto-disable when missing.\n- Drop verbose zsh completion subsection; one-liner pointer to\n  `kit completion --help` is enough.\n- Renames §\"What kit dress does\" → §\"What kit design does\" to match\n  the renamed command.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add Requirements section, mention kit completion",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T21:46:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5bd2856cf87b839a2838183a72b96f432aa06079",
          "body": "Captures the matrix of required vs optional tools so teammates can\naudit their machine before installing. Optional tools are documented\nas auto-disabling — kit shouldn't crash when pg_dump or gt isn't\ninstalled.\n\nRenames §\"What kit dress does\" → §\"What kit design does\" to match\nthe renamed command.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add Requirements section + zsh completion setup",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T21:44:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a77288c1483bc7a27b129d21e1461e082c093939",
          "body": "- TrimSpace glamour body before printing; eliminates double blank\n  line between cmd.Short and rendered markdown\n- raise wrap cap to 120 so paragraphs don't break on every other\n  word at the right edge of wide terminals\n- skip the post-Short blank line when Long is present (glamour adds\n  its own leading padding)\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(help): tighter section spacing + wrap cap 100→120",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T21:41:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "03eac90b96e222891552799aa3b74c3585f1bda4",
          "body": "- WithStandardStyle(\"auto\") was falling back to ascii on Ghostty,\n  leaving \"##\" literal in headers; switch to WithAutoStyle() which\n  detects light/dark terminal background properly\n- WordWrap was 0 (no wrap); now uses term.GetSize - 2, capped 40-100\n- add blank line between Long body and Usage section so they don't\n  visually run together\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(help): glamour auto-style + width-aware wrap + section spacing",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T21:35:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "aa27a41b864914d34d63379823f63d839a3cc746",
          "body": "- swap \"dress time\" → \"design time\" everywhere\n- emoji pool count tightened from ~95 → ~90\n- note lineup column order (NAME · SLOT · RUNNING · BRANCH · STATUS)\n  and rationale for SLOT-RUNNING adjacency\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(plan): refresh narrative for design rename + lineup columns",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T21:21:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "954e8088099ea4ce00cb4b74942cf8dfdb2e3492",
          "body": "- columns now NAME · SLOT · RUNNING · BRANCH · STATUS\n  slot + running adjacent since both describe port-allocation lifecycle\n  (slot = ports reserved, running = ports actually serving)\n- LAST USED column removed; meta.LastUsed still drives row sort order\n- delete unused realnow.go + relativeTime helper\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(lineup): reorder columns, drop LAST USED",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T21:15:13Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1a7919d70e82af5aee7933d82efd572a32da676f",
          "body": "- export tui.Color* for cmd/ packages; drop hex literals from\n  cmd/help.go, cmd/root.go, internal/tui/logflow.go\n- log viewer: append to strings.Builder per line, rebuild only on\n  ring trim (was strings.Join over 5000 lines per incoming line)\n- log: drop redundant pre-flight stat; RunLogTUI's Read\n[…]\nquit\n- docs/PLAN.md: living design doc — port slots, runtime env injection,\n  charm component map, roadmap, verification checklist\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: dedup colors, streamline log buffer, expand emoji pool",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T21:13:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "eb8b3c6169f57af9e0ca1dc32f41c15450326291",
          "body": "User-visible:\n- Drop `dress` from design aliases (only `new` remains)\n- Rename `prune` → `tear` (alias `prune` kept). \"Tear up the field.\"\n- `kit swap <name> [editor]` — positional editor override (e.g. `kit swap notebook cursor`)\n- `kit play` (no arg) auto-detects cwd inside a worktree and uses tha\n[…]\n-flight: errors before entering TUI when no run dir\n- orb bounds clip: clampInt prevents out-of-bounds writes if spring overshoots\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Polish + critical fixes from audit",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T21:00:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1fbb7abd048baddb55c387637dd1ed73a31313ad",
          "body": "Side panel during `kit design` now shows a penalty kick at goal:\n- ball flies from penalty spot to a random corner (harmonica spring)\n- goalie dives left or right (separate spring), 45% chance to match\n- judge phase: SAVE if goalie within 2.5 cells of ball, GOAL otherwise\n- score tally in top-right (saves vs goals)\n- ~3s loop with pre-shoot/shoot/result phases\n\nSame `Orb` type name kept for back-compat with designflow.go.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Replace orb panel with animated penalty kick",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T20:47:55Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ebc90a265c22b3d9bbd930c9c367d2e235097676",
          "body": "- Rename `dress` → `design` (aliases: `dress`, `new`)\n- huh forms replace manual toggle screens in design wizard\n- Animated orb panel during design (harmonica spring physics + 3-dot orbit)\n- bubbles/progress overall progress bar + bubbles/stopwatch elapsed timer\n  in design and play run screens\n- bu\n[…]\n`)\n- Cobra root Long rewritten in markdown for glamour rendering\n- New cmd/help.go with custom `prettyHelp` template using glamour\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Adopt huh, glamour, charm/log + bubbles components",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T20:44:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "11c23f0355f776d4ddc22d560c7e214efe094b84",
          "body": "- Replace fixed-width fmt.Sprintf padding with lipgloss/table for proper\n  ANSI/emoji-aware column alignment\n- Drop GTAB column (always auto-managed) and SERVICES dot column\n  (replaced by simpler N/6 RUNNING count, blank when zero)\n- Adaptive color palette via lipgloss.AdaptiveColor for both light\n\n[…]\no worktrees made by the old zshrc script work with\n  `kit warmup` etc\n- Remove gtab toggle from `kit dress` wizard — always create\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Polish lineup table + adaptive colors + legacy gtab compat",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T20:32:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1a8ec93940674860b2d40863f43ab8cb56efe678",
          "body": "Each worktree now gets a deterministic 5-port slot at `kit dress` time\n(state.toml). New `kit play` wizard spawns frontend/app + frontend/admin\n(Vite) + backend/api + backend/admin (uvicorn --reload) + celery worker +\nbeat as detached processes, with port-aware env injection at runtime\n(env files st\n[…]\nkit swap` bumps last_used so picker keeps recent kits on top\n- New env vars: KIT_STATE_DIR, KIT_RUN_DIR, KIT_PY_VENV, KIT_NO_EMOJI\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add port wiring + service runner (play/pause/log/prune)",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T20:24:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9f16fe9545ee57144150f356d37e592ccb32ce84",
          "body": "Bubble Tea TUI wrapping git worktree + env copy + DB clone +\ndep install + graphite tracking + ghostty workspace generation.\n\nSubcommands: dress (new), lineup (ls), wash (rm), warmup (gtab), swap (open).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Initial commit: kit CLI for Liftoff feature worktrees",
          "author_name": "Andrei Stoica",
          "author_login": "andreicstoica",
          "committed_at": "2026-05-08T19:21:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        }
      ],
      "releases_count": 12,
      "commits_last_year": 96,
      "latest_release_at": "2026-06-09T15:53:54Z",
      "latest_release_tag": "v0.2.5",
      "releases_from_tags": false,
      "days_since_last_push": 2,
      "active_weeks_last_year": 9,
      "days_since_latest_release": 47,
      "mean_days_between_releases": 1.4
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "github.com/andreicstoica/kit",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/andreicstoica/kit",
          "is_deprecated": false,
          "latest_version": "v0.3.3",
          "repository_url": "https://github.com/andreicstoica/kit",
          "versions_count": 21,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-24T21:51:14Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 2
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 1,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 1
    },
    "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": 22092,
      "source_files_sampled": 120,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/BurntSushi/toml",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.6.0"
        },
        {
          "name": "github.com/charmbracelet/bubbles",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.0"
        },
        {
          "name": "github.com/charmbracelet/bubbletea",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.3.10"
        },
        {
          "name": "github.com/charmbracelet/fang",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.0"
        },
        {
          "name": "github.com/charmbracelet/glamour",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.0"
        },
        {
          "name": "github.com/charmbracelet/harmonica",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.2.0"
        },
        {
          "name": "github.com/charmbracelet/huh",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.0.0"
        },
        {
          "name": "github.com/charmbracelet/lipgloss",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.1.1-0.20250404203927-76690c660834"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "golang.org/x/term",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v0.43.0"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 1,
        "merged_prs": 13,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "andreicstoica",
          "commits": 96,
          "avatar_url": "https://avatars.githubusercontent.com/u/68513477?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": true,
      "ci_workflows": [],
      "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": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 0,
            "reason": "0 out of 8 merged PRs checked by a CI test -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 9,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "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": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "12 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "8bc26d12c7c9aea6b81ab422ff30a22a0268856b",
        "ran_at": "2026-07-26T22:42:34Z",
        "aggregate_score": 1.3,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-24T21:51:27Z",
      "oldest_open_prs": [
        {
          "number": 14,
          "created_at": "2026-07-13T21:24:32Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-13T18:19:15Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/andreicstoica/kit",
    "host": "github.com",
    "name": "kit",
    "owner": "andreicstoica"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 44,
      "inputs": {
        "security": 13,
        "vitality": 76,
        "community": 21,
        "governance": 54,
        "engineering": 40
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 76,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "commits_last_year": 96,
              "human_commit_share": 1,
              "days_since_last_push": 2,
              "active_weeks_last_year": 9
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 2 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 2
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "9/52 weeks with commits",
                "points": 6.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 9
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "96 commits in the last year",
                "points": 17.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 96
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 12,
              "latest_release_tag": "v0.2.5",
              "releases_from_tags": false,
              "days_since_latest_release": 47,
              "mean_days_between_releases": 1.4
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "12 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 12
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 47 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 47
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~1.4 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 1.4
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 21,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 1,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "1 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "at_risk",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 44,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file present, not a recognized license",
                "points": 16.9,
                "status": "partial",
                "details": [
                  {
                    "code": "license_custom",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 54,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 72,
            "inputs": {
              "merged_prs": 13,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "13/13 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 13,
                      "decided": 13
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 52,
            "inputs": {
              "followers": 13,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "andreicstoica",
              "public_repos": 38,
              "account_age_days": 2198
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "13 followers of andreicstoica",
                "points": 8.2,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 13,
                      "login": "andreicstoica"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "38 public repos, account ~6 yr old",
                "points": 23.6,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 38
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 6
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "github.com/andreicstoica/kit"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 2
            },
            "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 2 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 2
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "21 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 21
                    }
                  }
                ],
                "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": "at_risk",
        "name": "Engineering Quality",
        "value": 40,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "critical",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 24,
            "inputs": {
              "has_ci": false,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "0 out of 8 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "critical",
        "name": "Security",
        "value": 13,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "critical",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 13,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 14,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 4,
              "scorecard_aggregate": 1.3
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "0 out of 8 merged PRs checked by a CI test -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "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 not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "12 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 2
            },
            "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": "moderate",
        "name": "AI Readiness",
        "value": 65,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.969,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "93 of 96 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 93,
                      "sampled": 96
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 71,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.688,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "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": "66 of the last 96 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 66,
                      "sampled": 96
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 22092,
              "source_files_sampled": 120,
              "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/120 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 120,
                      "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": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-26T22:42:41.730231Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/a/andreicstoica/kit.svg",
  "full_name": "andreicstoica/kit",
  "license_state": "custom",
  "license_spdx": null
}

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

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

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