公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-23 12:25 UTC

zeroliu / otacon

TypeScriptMIT★ 6 星标⑂ 0 复刻始于 2026年6月在 GitHub 上查看 ↗

zeroliu/otacon 的健康指数为 100 分中的 55 分,处于「中等」区间。 其得分最高的类别是Vitality(75/100),最低的是Community & Adoption(36/100)。 最近一次更新在 5 天前。 近期的大部分工作由 1 位贡献者完成。

55
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

Zero Liu个人账户
29 关注者44 个公开仓库始于 2010年3月Lumos

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布
npmotacon0.1.112,2432112 天前

按类别列示的指标

活力

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

75良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 5 天前
4.2/36提交节奏 — 52 周中有 6 周有提交
18/18提交量 — 最近一年 178 次提交
0/10OpenSSF Scorecard:Maintained — project was created within the last 90 days. Please review its contents carefully
所用输入
commits_last_year178
human_commit_share1
days_since_last_push5
active_weeks_last_year6

发布纪律

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

社区与采用

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

36存在风险 · 占总体的 18%
评分方式
11.3/60星标 — 6 个星标
0/25复刻 — 0 个复刻
0/15关注者 — 0 位关注者
所用输入
forks0
stars6
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

50中等
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(MIT)
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
评分方式
44.7/80月度下载量 — npm 合计每月 2,243 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packagesotacon
dependents
ecosystemsnpm
total_downloads
monthly_downloads2,243
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

55中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
3/10OpenSSF Scorecard:Contributors — project has 1 contributing companies or organizations -- score normalized to 3
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
0/46.8议题解决 — 没有议题或无数据
37/38.3PR 接受 — 已裁定的 PR 中 60/62 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs60
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs2
已排除计分(无数据或不适用):议题解决。 其余权重已重新归一化。
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
10.6/25所有者影响力 — zeroliu 有 29 位关注者
24/25既往记录 — 44 个公开仓库,账户约 16 年
所用输入
followers29
owner_typeUser
is_verified
owner_loginzeroliu
public_repos44
account_age_days5,970
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — npm 上有 1 个软件包
35/35发布时效 — 最近一次发布于 12 天前
20/20版本历史 — 21 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesotacon
ecosystemsnpm
any_deprecated
min_days_since_publish12

工程质量

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

55中等 · 占总体的 20%

工程实践

48存在风险
评分方式
24/24CI 工作流 — 1 个工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
0/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 0 out of 21 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文档 / 主页站点
0/10仓库描述
0/10主题标签
10/10Wiki
所用输入
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

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

46存在风险 · 占总体的 16%

安全态势

36存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
0/2.5CI-Tests — 0 out of 21 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.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — 无数据
0.5/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 1
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 — 无数据
6.8/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
3/7.5Vulnerabilities — 6 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate3.6
已排除计分(无数据或不适用):packaging, signed_releases。 其余权重已重新归一化。
评分方式
18.5/35直接依赖不含已知公告 — 1 个受影响:@hono/node-server 1.19.14 (moderate 5.9)
25/25间接依赖不含已知公告 — 1 个受影响:dompurify 3.4.11 (low)
40/40没有长期未处理的公告 — 没有公告公开超过 90 天
所用输入
sourceosv
advisories2
affected_packages2
assessed_packages122
unassessed_packages0
affected_by_severitymoderate 1, low 1
direct_affected_packages1
比对的是 npm:otacon@0.1.11 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 122 个软件包。 未对可达性进行分析。

AI 就绪度

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

68中等 · 占总体的 0%
评分方式
45/45代理指令 — AGENTS.md, CLAUDE.md
0/15机器可读文档(llms.txt)
38.9/40可读的提交历史 — 100 次人类提交中有 73 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.73
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes2,824
评分方式
0/18一条命令的引导启动
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — src/ui/tsconfig.json, tsconfig.json
0/10可复现环境
10/10已体现的代理实践 — 最近 100 次提交中有 65 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
1/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 1
所用输入
has_nix
has_tests
lockfiles
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configssrc/ui/tsconfig.json, tsconfig.json
agent_commit_share0.65
toolchain_manifests
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — TypeScript(静态类型)
54.6/55可控的文件大小 — 采样的 266 个源文件中有 2 个超过 60KB
所用输入
primary_languageTypeScript
largest_source_bytes239,907
source_files_sampled266
oversized_source_files2

关键数据

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

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token

更多细节

OpenSSF Scorecard 3.6 / 10
3.6综合

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

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
0CI-Tests0 out of 21 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
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
不适用Packagingpackaging workflow not detected
1Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 1
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
9Token-Permissionsdetected GitHub workflow tokens with excessive permissions
4Vulnerabilities6 existing vulnerabilities detected
直接依赖 4
注册表软件包版本约束清单文件
npm@hono/node-server^1package.json
npmhappy-dom^20.10.3package.json
npmhono^4package.json
npmmermaid^11.15.0package.json
全部依赖 21

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

注册表软件包版本关系
npm@hono/node-server^1直接
npmhappy-dom^20.10.3直接
npmhono^4直接
npmmermaid^11.15.0直接
npm@playwright/test^1.60.0间接
npm@storybook/addon-a11y^10.5.0间接
npm@storybook/react-vite^10.5.0间接
npm@types/bunlatest间接
npm@types/node^24间接
npm@types/react^19.2.17间接
npm@types/react-dom^19.2.3间接
npm@vitejs/plugin-react^6.0.2间接
npmdompurify^3.4.10间接
npmhighlight.js^11.11.1间接
npmlucide-react^1.21.0间接
npmmarked^18.0.5间接
npmreact^19.2.7间接
npmreact-dom^19.2.7间接
npmstorybook^10.5.0间接
npmtypescript^5间接
npmvite^8.0.16间接
依赖安全公告 2

安装 npm:otacon@0.1.11 会引入 122 个包(直接与传递):其中 2 个存在已知公告,1 个为直接依赖。

软件包版本关系严重程度公告数修复版本
@hono/node-server1.19.14直接12.0.5
dompurify3.4.11间接13.4.12

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 5671,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "CSS": 165703,
        "HTML": 852,
        "Shell": 156147,
        "JavaScript": 6054,
        "TypeScript": 2513449
      },
      "pushed_at": "2026-07-18T03:37:49Z",
      "created_at": "2026-06-12T16:40:06Z",
      "owner_type": "User",
      "updated_at": "2026-07-18T03:36:10Z",
      "description": null,
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Zero Liu",
      "type": "User",
      "login": "zeroliu",
      "company": "Lumos",
      "location": "San Francisco",
      "followers": 29,
      "avatar_url": "https://avatars.githubusercontent.com/u/226076?v=4",
      "created_at": "2010-03-19T12:21:49Z",
      "is_verified": null,
      "public_repos": 44,
      "account_age_days": 5970
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.1.11",
          "kind": "patch",
          "published_at": "2026-07-10T21:59:01Z"
        },
        {
          "tag": "v0.1.10",
          "kind": "patch",
          "published_at": "2026-07-10T21:58:49Z"
        },
        {
          "tag": "v0.1.9",
          "kind": "patch",
          "published_at": "2026-07-07T18:46:44Z"
        },
        {
          "tag": "v0.1.8",
          "kind": "patch",
          "published_at": "2026-07-04T16:27:53Z"
        },
        {
          "tag": "v0.1.7",
          "kind": "patch",
          "published_at": "2026-06-28T15:59:02Z"
        },
        {
          "tag": "v0.1.6",
          "kind": "patch",
          "published_at": "2026-06-27T11:42:44Z"
        },
        {
          "tag": "v0.1.5",
          "kind": "patch",
          "published_at": "2026-06-25T16:14:52Z"
        },
        {
          "tag": "v0.1.4",
          "kind": "patch",
          "published_at": "2026-06-25T12:32:10Z"
        },
        {
          "tag": "v0.1.3",
          "kind": "patch",
          "published_at": "2026-06-20T12:12:18Z"
        },
        {
          "tag": "v0.1.2",
          "kind": "patch",
          "published_at": "2026-06-18T15:04:05Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-06-15T17:32:02Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "4df0b3491211286341f4e7556abff19af5915e2d",
          "body": null,
          "is_bot": false,
          "headline": "Support external PRs in Review V2 (#65)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-18T03:36:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "66bf95194af190937c1fd7950b5af7872161f310",
          "body": null,
          "is_bot": false,
          "headline": "Fix Plan V2 skill setup safeguards (#64)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-18T03:22:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7fcf095aa632aaddcf9d45d1dcbc2e1448699acb",
          "body": "…acon-review-v2 (#63)\n\nThree agent-side prototype cards implementing the Plan V2 live co-design SOP,\nplus a repo-custom-prompt mechanism so the cards adapt to per-project\nconventions without hardcoding them. No daemon or UI changes; the cards run\nentirely in the agent with session artifacts under ~/.otacon/v2-sessions/.\n\n\nClaude-Session: https://claude.ai/code/session_01XYiQS9dKerESXsHcWu3bCT\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add Plan V2 prototype skills: otacon-plan-v2, otacon-implement-v2, ot…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-18T02:44:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3a3751a0f647774c00a9cc46c02c40a54bb04619",
          "body": "…(#62)\n\nPR review had re-derived the composer placement with hardcoded numbers\nthat drifted from plan review's tuned math, floated the selection bar\ncontextually (colliding with native selection popovers), and never\npublished --kb-inset for its phone composer sheet.\n\nExtract the tuned math as one ex\n[…]\nooks; both screens place\nthrough them. The contextual SelectionBar mode and its CSS are removed.\nPR review keeps immediate comment delivery, the knowledge options slot,\nand the selectionOverride flow.",
          "is_bot": false,
          "headline": "Unify selection bar and composer placement across plan and PR review …",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-17T01:54:11Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c63d5d3f86945b566dc3ecdcded609ab0213597d",
          "body": null,
          "is_bot": false,
          "headline": "Add explicit daemon restart command",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-16T15:49:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "43b64b2559c5cc0c4f23c78048a087d07a0d760c",
          "body": null,
          "is_bot": false,
          "headline": "Allow anchor text everywhere",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-16T14:39:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eb8bccb38779f59b6830232d1f3ffbe938dc2fdb",
          "body": "…n (#61)\n\nThe kind switch synced mode to the open session's kind in an effect that\nre-ran on every render, so clicking the other tab while a session was open\nwas reverted immediately. Follow the open session's kind only when the open\nsession actually changes; keep the empty-side fallback in the effect.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix sidebar Plans/Reviews switch snapping back while a session is ope…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-16T14:38:26Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f8dd07444f0c3ed7033652de18a25d1f758515e6",
          "body": null,
          "is_bot": false,
          "headline": "Run release tests in isolated worker (#60)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-16T14:31:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5858ff144bd77a3e9f938e8c9f9ad6563f8d13bf",
          "body": "* Prototype PR review experience in Storybook\n\n* Add local PR review knowledge store\n\n* Add typed PR review sessions\n\n* Add persistent PR review reports\n\n* Add durable adaptive review quizzes\n\n* Add interactive PR review threads\n\n* Add durable PR review completion\n\n* Ship the Otacon review skill\n\n* \n[…]\n\n\n* validate persisted quiz answer events\n\n* fix(review): close startup and checkout races\n\n* fix: bind review leases to code actions\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add personalized PR review skill (#59)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-15T22:40:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "641c8564ad1bd2c1428d67b30691ff43285ca6a7",
          "body": null,
          "is_bot": false,
          "headline": "0.1.11",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-10T21:58:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "08880bc9ee99e40a028516f6c852d14faf4aebf9",
          "body": null,
          "is_bot": false,
          "headline": "0.1.10",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-10T21:58:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "badf4bacd15ccaf61ca057b30dadf4b83615016e",
          "body": null,
          "is_bot": false,
          "headline": "Fix skill directory symlink installs (#58)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-10T21:57:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7189729f133272222e7529fa125fbfdd3c66fb2",
          "body": null,
          "is_bot": false,
          "headline": "0.1.9",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-07T18:45:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4113fed59c11d72ff6a33d51f45ad75ea5785bd8",
          "body": "* Add pr.draft config knob (default true)\n\nIntroduce a `pr` config section with a single `draft` boolean, defaulting\nto true, wired through the schema-driven config system exactly like\n`socratic`: interface, DEFAULT_CONFIG, CONFIG_SCHEMA, overlayConfig merge,\nand a SECTION_GROUPS entry so it renders\n[…]\nomated review running on them instead of\nsilently skipping every otacon PR.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Draft PRs by default (pr.draft config) (#57)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-07T05:35:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7cc21ca4a8f10d0451dd21a2cf415d08e7e92004",
          "body": null,
          "is_bot": false,
          "headline": "0.1.8",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-04T16:27:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0efcb3f9deeae75ddc34f188d707292457d61d9a",
          "body": "Retune the skill wrapper's Implement-loop Finish step to author the PR\nbody from a reviewer-first template ported from the approved plan --\nSummary (Why/What + the plan's lead visual), Decisions (cites stripped),\nper-commit Changes (goal + behavior to verify), optional Notes -- instead\nof the old \"p\n[…]\ne PR's current state rather than appending revision stubs.\n\nRegenerate the dogfood SKILL.md, retune DESIGN/DECISIONS, add a wrapper guard test.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Reviewer-first PR body for the Implement loop (#56)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-07-04T16:26:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a9c914a7e9ddffc9400209eda8879f82307eff04",
          "body": null,
          "is_bot": false,
          "headline": "0.1.7",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-28T15:58:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "95b613a2f83eb3ea9c97b5fc07173badd67da713",
          "body": "* Phase 1: prState model + gh fetchPrState probe\n\nAdd a prState field (open/merged/closed) to the session model and a pure,\ntotal fetchPrState that shells out to the gh CLI to probe a PR's GitHub fate.\nNever throws: any failure (gh missing, non-zero exit, malformed JSON) resolves\nundefined. Injected\n[…]\ning closed PRs would reintroduce unbounded Done-bucket polling against D6.)\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "PR review section + live PR status + impl detail header (#50)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-28T15:49:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d087f93a3bd3f69b2ea72343c770ad42815c2510",
          "body": "The desktop section ⋯ popover was hardwired to width: 272px with nowrap rows,\nbut the widest row needs ~290px, so the hint clipped past the right edge.\nContent-size the box (max-content, clamped 240px..min(360px, 100vw-24px)) so\nits fixed-copy rows can never clip, and drop .sec-hint from 14px to the 12px\nmenu-label tier so it stops out-reading the action it annotates.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase card popover: content-size .sec-pop, drop hint to 12px (#54)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-28T15:30:49Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3d5d66e07a8557ec9641c5f55763bd6d9ad96bf4",
          "body": "Callouts (`[!risk]` `[!note]` `[!decision]` `[!assumption]`) render as small inline badges via a marked inline token (like scope pills), matched anywhere in prose, instead of flat blockquote panels. Fixes the bare `[!assumption] body` line rendering as literal text. Callout badges are free inline (not budget- or visual-capped); only the decision matrix remains a capped visual. Skill card + DESIGN/DECISIONS updated, and the verify:branch samples now showcase the badges.",
          "is_bot": false,
          "headline": "Render callouts as inline badges, not flat panels (#51)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-28T13:58:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4755c95929b09a31e6dbdc443e28c798aadbd2f0",
          "body": "* Capture the user's verbatim request via `otacon start --prompt`\n\nAdd an optional `prompt` to the session record, set once at start from a\nnew `--prompt` flag, trimmed and stored as-is (no cap). It rides into the\nUI through the existing summarize() spread, so no read-path plumbing is\nneeded. Whites\n[…]\n-line preview and\nthe expand-to-full-text behavior with newlines preserved.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Prompt card: show the user's original request atop the review (#49)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-28T13:51:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "859a06fb768d8cc0cf05b6249b2ac5513cfb1441",
          "body": "…TD-by-default (#48)\n\n* gen:skill emits the committed dogfood SKILL.md too\n\nscripts/gen-skill-asset.ts now writes both generated wrappers: the published\ndist/skills/otacon/SKILL.md (skillMd) and the committed\n.claude/skills/otacon-dev/SKILL.md (dogfoodSkillMd). A skill-text change now\nregenerates th\n[…]\ne per read-path section' fence rule cannot slip\n  back into either wrapper.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Diagram guidance: match the visual to the content's shape, not graph-…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-28T13:45:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "101b6c546a2227e0ea644717837ad85ef2eaaef9",
          "body": "Reorder phase fields to Goal, Verification, Files (last); render the Files field labelless and full-width. New plans author Files as a | File | What changed | GFM table (rendered at 14px, path in a mono code chip); a legacy list still renders as-is, no render-time parsing. Lint requires a Files tabl\n[…]\n\" with every body row's cell filled (E_FILES_NO_SUMMARY); a Files table is exempt from the per-phase visual cap. Docs, SKILL protocol, and the verify:branch/e2e fixtures updated to exercise the table.",
          "is_bot": false,
          "headline": "Phase card: Files-table information architecture (#52)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-28T13:33:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d1d19fb43fb7bd6e465a2f91dd2abe49594806d6",
          "body": "Add a \"one question, well-shaped\" rule to the shared protocol card so\nagents ask focused, short questions and break the rare long one into\nshort paragraphs, authored in a $TMPDIR temp file and passed via\n--question \"$(cat ...)\" then removed. Long unbroken grill questions are\nagent-authored, not a re\n[…]\ne the committed dogfood SKILL.md, add a wrapper test asserting\nboth wrappers carry the rule, and record the decision in\nDECISIONS.md/DESIGN.md.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Grill questions: format long ones via temp file, guide not lint (#47)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-27T15:50:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4db6fe4767f799f266601f201c06a1848bc1a317",
          "body": "The open grill question rendered at --fs-title (18px), a tier above its\nown option chips, answer field, and answered state (all at or below\n--fs-ui 14px). A grill question is reading content the user reads and\nanswers, not a heading, so it drops to --fs-body (16px). The settled\nstate keeps --fs-ui (\n[…]\n-title to the --fs-body list in the styles.css token comments and\nthe DESIGN.md type-scale paragraph, and records the tradeoff in\nDECISIONS.md.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Grill questions read at body (16px), not the title heading tier (#46)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-27T14:04:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f23e27ef906546feafaec6286e24652f3591dac0",
          "body": null,
          "is_bot": false,
          "headline": "0.1.6",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-27T11:41:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2cfcd8cf2609603e10e86c086d9503154ec946ad",
          "body": "…ender (#45)",
          "is_bot": false,
          "headline": "Socratic mode: an opt-in planning posture that resists cognitive surr…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-26T08:44:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "74a2906019dd9ae76cf87fddb055fa7a689294b1",
          "body": null,
          "is_bot": false,
          "headline": "0.1.5",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-25T16:14:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0a040a34f0b1c1c6a850b35622a12628a1538734",
          "body": "* Type scale phase 1: rename 3 size tokens into a 5-role scale\n\nValue-preserving rename of the CSS type-scale tokens: --fs-prose/body/label\n(16/14/12) become --fs-meta 12, --fs-ui 14, --fs-body 16, with new --fs-title\n18 and --fs-display 22 defined but not yet wired (later phases map classes to\nthem\n[…]\nrole scale is preserved and 12 sits on the floor.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Typography: a 5-role semantic type scale (#43)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-25T15:48:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "17cecb22f7faf3c097c4727f9b504e32824a95f5",
          "body": "…(#44)\n\nOn the staging branch, `bun run release` computed the prerelease base from\nthe local package.json, which the prior cut had already bumped, so every\nre-cut inflated the core (0.1.4-staging, then 0.1.5-staging, then\n0.1.6-staging) even though main never moved.\n\nThe staging path now auto-fetche\n[…]\nh resolves the base and passes it to staging-version.ts as\nan explicit `current` arg, so that script stays pure and unit-testable.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Source staging release base from origin/main, not local package.json …",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-25T14:58:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6f3c1817229b84eac453f7807b5a35aa03ad7550",
          "body": null,
          "is_bot": false,
          "headline": "0.1.4",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-25T12:31:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cd9527794fb684066456a44c81659e5c688a6299",
          "body": "…package (#42)\n\n* Phase 1: ship skillMd() as a packaged file + path resolver\n\nBuild-time codegen (scripts/gen-skill-asset.ts) writes skillMd() to\ndist/skills/otacon/SKILL.md, shipped via files:[\"dist\"], so a later\nsymlink-to-package install has a stable, auto-updating target. Adds\npackagedSkillPath(\n[…]\ns/npx), project, and\nlegacy pre-symlink installs.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Keep installed skills fresh: symlink wrappers into the auto-updating …",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-25T01:37:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "aade252a389f712508687767f7c942e6ff678d62",
          "body": "…ot (#41)\n\n* Side nav: meaningful per-session status icons (lucide)\n\nReplace the unicode status glyph with lucide-react icons that read at a\nglance. Attention states get recognizable icons plus a slightly brighter\nrow background: answer-needed (open questions) shows MessageCircleQuestion,\nreview-nee\n[…]\nw, always-tappable delete unchanged.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* fix style\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Side nav: per-session status icons + delete overlays the agent-dot sl…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T17:11:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d745eb09253e1c1b897a2f4f4fdeb600001ac6e7",
          "body": "* Add pure interview-open module + hook (phase 1)\n\nThe Interview panel's open/collapsed decision, pulled into a pure, unit-tested\nmodule (src/ui/review/interview-open.ts) mirroring session-sheet-state.ts and\ncompact.ts so it tests under renderToStaticMarkup (which skips effects). The\nuseInterviewOpe\n[…]\ng. Documents the behavior in DESIGN.md section 8.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Auto-open Interview panel when a new question arrives mid-build (#38)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T16:09:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d5531bbadadafc4f09ff7ae96440da173b7bae6d",
          "body": "…dest-first (#40)\n\n* Portal modal dialogs to body so they always stack on top\n\nConfirm dialogs, the section menu, and the mobile session sheet rendered\ninline, trapping any dialog opened from the sticky sidebar in its stacking\ncontext (the main column's grill cards painted over a delete confirm's z5\n[…]\nom the\nremoved pill to the fresh-revision banner.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Portal dialogs to top z-index, one always-on header bar, interview ol…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T16:02:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cf5960b0ad69951f31efcf35d1d7e994c78c99d1",
          "body": "…rs (#39)\n\n* Audit-log every notification decision to daemon.log\n\nmaybeNotify logs a notify dispatch line (session, kind, title, message) when a\nbanner fires and a notify skip line (reason config-disabled|watched) when\nsuppressed; createDesktopNotifier logs a notify backend line with the chosen\nback\n[…]\ner comment. Records the decision in DECISIONS.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Audit-log notifications + stop the test suite firing real macOS banne…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T15:27:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c0d837ff069f759c4a160dee2838c401d9e7111f",
          "body": "* Daemon-wide live-tab gauge on /api/health (open-tab reuse, phase 1)\n\nCount the daemon's live SSE connections (the index stream plus every\nper-session stream) in a single in-memory gauge, bumped in sse()'s start\nand dropped in its cleanup so open/close stay paired across cancel, abort,\nand reader-l\n[…]\n) hooks from phase 1 (ui.ts back to origin/main).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "otacon open reuses an already-open review tab (no duplicate tabs) (#37)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T14:56:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bc6754dc27c792df18e3be0d345e11868428de64",
          "body": "The staging-release Test-gate failure (channelOf(VERSION) flips to staging\nwhen the build stamps a -staging. VERSION) and the installedVersion seam that\nfixes it are a non-obvious tradeoff; document it beside the channel-aware\nauto-update entry.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "DECISIONS: record why update-channel tests inject the installed version",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T14:39:14Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "26062a29ea4745f2444d7078a731976bbbbaeca3",
          "body": "Staging npm releases failed at the CI Test gate: `npm version\n0.1.4-staging.<stamp>` regenerates src/shared/version.ts so VERSION is a\n`-staging.` build, and channelOf(VERSION) flips latest→staging. Two\nupdate-channel tests hardcoded the `latest` channel, so they went red under a\nstaging VERSION and\n[…]\n version and add positive staging-channel coverage to both\nmodules, so the suite is green regardless of the ambient build channel.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Decouple update-channel tests from the build-time VERSION",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T14:39:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "75b9104dd4afd2d215abe7116a608d6923051f07",
          "body": "…ts there\n\nAfter the storage relocation the agent no longer drafts plan.md in the repo, so\notacon start now prints the `plan` path (~/.otacon/sessions/<id>/plan.md). The\ndogfood skill text drafts there and submit keeps defaulting to it; status and\nresume already print the path. Regenerated .claude/skills/otacon-dev/SKILL.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Surface the home plan draft path: start prints it; dogfood skill draf…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T14:30:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dd5c6a3760d223c25754c409b1f37e7e2d99d645",
          "body": "…the home folder\n\nPer-session working state (session.json, events.json, threads, transcript,\nactivity, stream, r<N>.* snapshots, plan.md) moves from <repo>/.otacon/<id>/\ninto the home store ~/.otacon/sessions/<id>/, the dir the approved plan already\narchives into. <repo>/.otacon/ now holds only conf\n[…]\nessionDir(id). No\nmigration of pre-existing in-repo session dirs: pre-release and gitignored, so\nthe change is going-forward only.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Relocate session working state to ~/.otacon/sessions; delete removes …",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T14:30:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0289f62e90e9b29f0664d8f4ee2829070b9f2696",
          "body": "Mount the threads rail on every state so the desktop right column is never blank,\nand give it a centered empty-state placeholder whose copy adapts to whether a plan\nexists. Add an \"ask the agent\" action that opens a whole-plan (null-anchor) ask\ncomposer, and relax the composer gate so it can open be\n[…]\na question during the grill phase. Such questions post to the\nlive session and reach the parked agent as ordinary question events.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Always-on threads rail with empty state; ask the agent during grill",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T13:39:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2cbbd5d5b80e719eff14728375231daec6bb396c",
          "body": "Route any reviewer-resolved root conversation (question or comment) through the\ncollapsing ResolvedCard, generalized to be kind-aware, so a resolved question\nfolds to a checkmark summary that expands to the question, the agent answer, and\nReopen, instead of staying open with an inline mark. Remove t\n[…]\nrsationCard. The plan-highlight (lit) path already\nexcludes resolved roots, so a resolved question clears its highlight unchanged.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Collapse reviewer-resolved questions like resolved comments",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T13:39:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5250bc0fe6b0aadaca34467673f7d764708cfbe0",
          "body": "Remove the browser-daemon \"link\" indicator (the LinkState dot) from the session\nheader and its now-unused connected prop, keeping the agent presence dot. Restore\nthe meta-row right-alignment via card-time's base margin. On mobile (<960px) hide\nthe back link and move the hamburger menu into its top-left slot, so the hamburger\nis the sole session-nav control there; the desktop sidebar remains the list.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Header cleanup: remove the link dot; dedupe mobile session nav",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T13:39:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e383b1892c90dde3aa809fcd21befc151583771c",
          "body": "…ard)\n\nIntroduce --fs-prose/--fs-body/--fs-label (16/14/12px) tokens and sweep every\nsub-12px font literal in styles.css to the role-appropriate token: mono telemetry\nlabels to the 12px floor, readable/interactive text to 14px, the prose reading\ncolumn to 16px. Lift icon-only controls to a legible g\n[…]\n and hit box. Add\nstyles.test.ts, a guard that fails on any sub-12px font literal. Record the scale\nin DESIGN.md and DECISIONS.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "UI type-scale floor: 12px minimum, 14px norm, 16px prose (tokens + gu…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T13:39:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b643ef45d4cf95537ff17ea7e314a44087e5a953",
          "body": "…#30)\n\n* Phase 1: diagrams exempt from the per-section fence cap\n\nmermaid fences now count only toward diagramCount (the L7 lead-diagram\ncheck), never toward fenceCount / E_FENCE_CAP, so a lead diagram and an\nin-section structural diagram can coexist. Code and before/after fences\nkeep the one-fence-\n[…]\nts, and documents it in DESIGN.md +\nDECISIONS.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Tree-shaped plan content as mermaid diagrams + uncap diagram fences (…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T13:12:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "86d8e8fe8b8397d850be771a97e9a4a1af75e881",
          "body": "…g branch (#31)\n\n* Phase 1: pure staging-version helper + tests\n\nAdd scripts/staging-version.ts: a pure stagingVersion({current,kind,stamp})\nthat strips any prerelease off the current version, bumps the X.Y.Z core by\nkind (patch/minor/major, npm semantics, manual parse — no semver dep), and\nreturns \n[…]\n to the branch-detected model in the same commit.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Branch-detected `bun run release`: staging builds cut from the stagin…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T13:02:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c8b4fcbf7011ee50e0a1a0eac86d4c4bd7504ad9",
          "body": null,
          "is_bot": false,
          "headline": "Harden otacon skill implementation approval gate (#29)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-24T02:37:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0a75d62f015a04548351fb6e08c9d1ed9bb076b2",
          "body": "…(#28)\n\n* Now-playing console collapsed by default (no auto-expand)\n\nThe console now starts collapsed and never auto-expands. The status-based\nauto-open (draft/implementing) and its crossing effect are removed, so a\nmanual choice always sticks. The always-on one-line now-playing bar still\nsignals ac\n[…]\nity-collapse-and-sidebar-plans plan (otc_k9n45e).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Console collapsed by default + interview is the single grill surface …",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-23T09:44:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d61f7cc668d9c9214fdcd88b8c6ed8e39dd9934e",
          "body": "…dates (#27)\n\n* Phase 1: staging npm channel (release:staging + suffix-routed publish)\n\nAdd a `staging` npm dist-tag channel. `bun run release:staging [minor|major]`\ncuts a vX.Y.Z-staging.N prerelease tag from the staging branch; the existing\nrelease.yml routes by version suffix, publishing `-stagin\n[…]\n DESIGN and DECISIONS updated in the same commit.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Staging npm channel: otacon@staging preview builds + channel-aware up…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-23T09:42:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bee59985e7315cd1b92e4c831609ca9f1bbf1517",
          "body": "* Phase 1: reusable SessionList + extracted status helper\n\nAdd a condensed SessionList component (active rows + a collapsed\n\"approved (n)\" disclosure; accent, title, repo/branch, status glyph,\nagent dot, unread, hover-delete) for the upcoming app-shell sidebar.\nNot wired into the app yet.\n\nExtract t\n[…]\n.\n\nPart of the session-sidebar plan (otc_gji4tl).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Session list as a left sidebar (app shell) + mobile overflow menu (#26)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-22T15:38:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e7feafc2aea31a40dea2015a196900ea119cf584",
          "body": "…ations (#25)\n\n* Stop surfacing \"orphaned\" in the threads rail (Phase 1)\n\nDetached threads (anchor's quote can no longer be located) no longer go to a\nseparate ⚠ \"orphaned\" tray. They stay inline in the rail, rendered muted with a\nsubtle icon + hover tooltip; the user-facing word \"orphaned\" is gone.\n[…]\ntandard rhythm) so it reads as a separate action.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Never auto-orphan comments: reviewer-driven Resolve + comment convers…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-22T15:14:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "197fab3083f2d09428cffd49099ebb275310318d",
          "body": "Running /otacon <request> from inside an Implement build worktree now reopens the\nsame finished session and amends that worktree in place (same branch, same PR),\ninstead of spawning a second worktree.\n\n- daemon: RegistrySession.impl recorded at Implement-approve; POST /reopen flips a\n  terminal sess\n[…]\non resume`; `otacon status` surfaces resumeCandidate.\n- protocol card: resume-from-worktree bootstrap (relatedness + terminal confirm) and\n  amend-in-place Implement loop; dogfood wrapper regenerated.",
          "is_bot": false,
          "headline": "Resume + amend an implemented plan from its build worktree (#24)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-22T15:11:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "61b3d983c71b187985b52bece11d8a95829c4458",
          "body": "* feat(daemon): live-activity stream pipeline (phase 1)\n\nAdd the normalized StreamEvent model, an append-only stream.jsonl store\nwith monotonic per-session seq and cap/rotation, and a redact+truncate+label\nnormalizer. Route otacon progress notes into the same stream as highlight\nevents and publish a\n[…]\ned on expand. Adds a regression test per adapter.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Live progress: always-on now-playing console + cross-agent capture (#22)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-22T14:42:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4cfd698f18113c9a1c7a6af746fb927f0571337f",
          "body": "…vent) (#23)\n\n* Stamp re-answer events with revised + prior (Phase 1)\n\nWhen POST /api/sessions/:id/answers overwrites an already-answered grill\nquestion, the queued answer event now carries `revised: true` and `prior`\n(the previous answer's content). A first answer omits both, so its event\nshape is \n[…]\not on both surfaces. Sync DESIGN.md and the test.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Undo an answered question (reopenable grill answers + revised/prior e…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-21T15:20:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a48d05a207ee4926bc3e954a02ae292080ed603c",
          "body": "* Capture mermaid fence bodies in the daemon parser\n\nPhase 1 of mermaid renderability validation. Extend the canonical plan\nparser to collect each mermaid fence's source, start line, and enclosing\nsection into ParsedPlan.diagrams, sharing the exact detection seam that\nalready increments diagramCount\n[…]\nse-not-render, blocking, and fail-open tradeoffs.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Verify mermaid diagrams render at submit time (L8) (#21)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-21T12:59:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8c26504a58bf94c8e66fd0d54c9814532bcbdd4c",
          "body": "* Add session-nav module: [ / ] prev/next shortcut core\n\nPure adjacentSession wrap-around neighbor pick, the isTypingTarget guard\n(single source for the no-typing-interference rule), and the useSessionNav\nkeydown hook. Unit-tested; no UI wiring yet.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <nor\n[…]\nSIGN.md and record the\ndecisions in DECISIONS.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add [ / ] keyboard shortcuts for previous/next session (#20)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-21T12:38:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2a380e2d802aa9f1e6c94e5e60dd33e91a8658f6",
          "body": "* Remove internal spec references from wrappers\n\n* Remove internal spec breadcrumbs from code comments\n\n* Polish acceptance comment wording",
          "is_bot": false,
          "headline": "Remove internal spec references from code (#19)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-20T15:44:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6ae98fb2a3af7002af7c7dedd2e3118066e16e85",
          "body": "* docs: restructure README install and get-started\n\nMove the skill-install step into Installation alongside the CLI install,\nadd a project-level install line (otacon install --project --all), and\nopen Get started with a concrete /otacon example for Claude Code.\n\nCo-Authored-By: Claude Opus 4.8 (1M c\n[…]\nnthropic.com>\n\n* docs: show an example review URL\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: restructure README install and get-started (#18)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-20T12:27:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f8f517fbadf4d06dfa0961c4187735d0768c67a1",
          "body": null,
          "is_bot": false,
          "headline": "remove legacy docs",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-20T12:15:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "811066cf8d731f278eac177654b01112655cd507",
          "body": null,
          "is_bot": false,
          "headline": "0.1.3",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-20T12:11:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5e9a4095a654b626058a30e4fdd6b533a3b744bb",
          "body": "The sticky review header compacts on scroll, shrinking ~44px. Default\nbrowser scroll anchoring then drags window.scrollY by that amount to keep\ncontent visually steady, but scrollY is what drives the compact/expand\ndecision and the ~44px nudge exceeds the 36px hysteresis band (enter 48 /\nexit 12), s\n[…]\napse (was pumping 52->9->48->7\nwith repeated state flips). DESIGN.md and DECISIONS.md updated per the repo\ndocumentation contract.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix review header flicker: disable scroll anchoring on .page-review",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-20T12:11:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1cb2bd7bd3dae0d028e7910cc787448c11322cca",
          "body": "* Add approved plan: auto-update outdated version on start\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* Phase 1: pure update-check core + update.auto config key\n\nAdd src/cli/update.ts with isNewer/updateCheckDue/fetchLatest (all fail-open),\nthe update.auto config key thre\n[…]\nevision 3. Docs: DESIGN.md §6/§16 +\nDECISIONS.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Auto-update otacon to the latest version on start (#17)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-20T12:09:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "174d4dea29bfc9da81e491a91f6a99be3e919b50",
          "body": null,
          "is_bot": false,
          "headline": "0.1.2",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-18T15:03:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "179a1f521cd96cfbd5fa47f20b5b4b9c915d5d7f",
          "body": "…rage\n\nConfigurable plan storage: home archive, Save vs Implement, two-tier config",
          "is_bot": false,
          "headline": "Merge pull request #15 from zeroliu/otacon/impl-configurable-plan-sto…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-18T14:54:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "274e2401ef3e6cdf9c92cb889639238da181d240",
          "body": "…ault:\" placeholder\n\nThree Settings-screen fixes:\n\n- Saved value no longer reverts on a scope-tab switch. useConfig cached the\n  fetched scopes and only refetched on a repo/nonce change, and the save path\n  advanced its local baseline without touching that cache. A scope-tab switch\n  remounts ScopeF\n[…]\nI again. DESIGN.md and DECISIONS.md updated (the\nauto-save entry's claim that a scope switch refetches was wrong and caused this).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Settings UI: fix stale value on tab switch, show plans dir, drop \"def…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-18T14:53:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "251023449b06369e56ca6e93737250200035017c",
          "body": "otacon writes no .gitignore, so nothing under .otacon/ is gitignored on its\nbehalf. Update the source and test comments that still described\nconfig.local.json as the \"gitignored personal override\" and .otacon/plans as\nthe \"gitignored\" project copy: config.local.json is the personal,\nper-developer ov\n[…]\nle.\n\nComments now describe the current behavior plainly, with no claim about git\nignoring and no \"otacon does not commit\" framing.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Stop calling config.local.json / .otacon/plans gitignored in comments",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-17T11:34:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "69344e9aeb7c27d08ea334d89a6182a47b19b2c5",
          "body": "…t do\n\nDrop the \"otacon never git-commits\" / \"do NOT commit the plan\" / \"otacon\nmanages no .gitignore\" framing from the SKILL prompt, code comments, DESIGN,\nand README. These defined behavior by what otacon refuses to do and leaned on\nprovenance (DECISIONS.md back-references, supersession notes) tha\n[…]\nroject-vs-home path distinction; the agent always acts on\nthe path the event delivers.\n\nRegenerate the committed dogfood SKILL.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Prompts and comments: describe current behavior, not what otacon won'…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-17T11:22:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8a7b326e4c9c938bc4c470a316946c05871210d2",
          "body": "Move the default `worktree.dir` out of the repo to `~/.otacon/worktrees`\n(alongside the home sessions store), and stop managing the repo's\n`.gitignore` entirely: `otacon start` no longer appends the selective\n`.otacon/* + !.otacon/config.json` ignore (the `ensureGitignore` step is\ngone). Whether `.o\n[…]\n2/§16 + DECISIONS.md (new superseding entry) reflect the new\n  storage/gitignore model; regenerate the committed dogfood SKILL.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Worktrees in ~/.otacon; otacon manages no .gitignore",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-17T11:05:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e2d4117236d30339b9fa64795b7226b6649a715f",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive configurable-plan-storage plan (shipped)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-17T08:37:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "edabcde549b8fecb0e247bbb3be843457f6937e1",
          "body": "…commit\n\nRelabels the confirm sheet actions to Save Plan / Implement (and the warn/draft\nescapes to Save/Implement/Finalize anyway, Send & approve, Discard & approve).\nCopy now names the home archive (~/.otacon/sessions/) + project copy\n(.otacon/plans), never a git commit. api.ts/ApprovedNote carry the home path.\nAligns the e2e + smoke assertions and README/DECISIONS to the new model.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 4: approve dialog — Save vs Implement, honest destinations, no …",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-17T08:37:30Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c7430d3c6541171f9e85867bdee6695d039f087c",
          "body": "Adds the plans.dir config leaf. On approve the daemon writes every plan to a\ncanonical home store ~/.otacon/sessions/<id>/<date>-<slug>.md; Save also writes a\nproject copy under plans.dir, Implement keeps home only and the agent builds from\nit. otacon no longer git-commits or archives plans. The app\n[…]\nved event becomes\n{path, home, implement?}; the skill protocol card + dogfood SKILL.md drop the\ncommit + docs/plans/archive steps.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 3: home plan store + Save/Implement approve (otacon never commits)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T17:11:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fd2960120e5385a050bf948407646b47bb6cd441",
          "body": "Settings screen gains a third scope (User / Project / Project · local) with a\nuser < project < project.local inheritance display. inheritedValue/overriddenBy\nwalk highest-precedence-first chains; api.ts + saveConfig carry project.local.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 2: Settings UI project.local scope + 3-scope inheritance",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T16:26:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0974ab3bc963445d253bcfb600d190d01bc6b10d",
          "body": "…config.local.json)\n\nSplits repo config into committed .otacon/config.json (team-shared) + gitignored\n.otacon/config.local.json (personal). loadConfig precedence becomes\nuser < project < project.local; /api/config GET/POST gain a project.local scope;\notacon start writes a selective .otacon/* + !.otacon/config.json ignore so\nconfig.json stays trackable. Revises the #11 gitignored-repo-config decision.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 1: two-tier project config (committed config.json + gitignored …",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T16:08:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "55ddafa7ba306dd6df3e6ee4356c6b8742eda009",
          "body": "…ent, two-tier config\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Plan: configurable-plan-storage — home/sessions store, Save vs Implem…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T15:52:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "807dee2118e319b0ad066260e6aa4121e9d2398e",
          "body": "… docs/PHONE-ACCESS\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Plan: readme-rewrite — value-prop README + user-facing docs/INSTALL +…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T15:46:57Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "47f2c0c4c6603025469b3031ed93711d767eeed5",
          "body": "…ound (#12)\n\n* Comment & approve: defer finalize so a final nit costs no re-review round\n\nApproving with open comments now offers a third path beside force-commit:\nSend to agent (approve {sendOpenComments:true}). It flips the session to a\nnew non-terminal status `finalizing`, arms a `pendingApproval\n[…]\nect and Send & commit paths read 409/error alike.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Comment & approve: defer finalize so a final nit costs no re-review r…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T15:07:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "691bf644c0c2381d7b9c40c089699c55c6aa2e23",
          "body": "Settings web UI + otacon config CLI, two untracked config scopes (User/Project)\nover a single CONFIG_SCHEMA, new worktree.dir option, and browser-launching\nopen/config with OTACON_NO_BROWSER opt-out. Settings shows cross-scope\ninheritance hints and auto-saves (no Save button). bun test 575/0, typecheck\nclean, build green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Settings web UI + hierarchical config + worktree.dir (#11)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T14:47:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7d4a4a1e38b29d009bc036359636c7e273bf6026",
          "body": null,
          "is_bot": false,
          "headline": "Update PHONE-ACCESS.md",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T11:43:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90195db6b294347bd344c1ac29c7cd99c8d81cf3",
          "body": null,
          "is_bot": false,
          "headline": "Update README.md",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T11:41:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "34184b1826b7e53a50d17d3cc8bd4897382852a2",
          "body": "…/phone guides (#14)\n\n* Plan: install-project-scope — otacon install --project + codex skill migration\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* Plan: readme-rewrite — value-prop README + user-facing docs/INSTALL + docs/PHONE-ACCESS\n\nCo-Authored-By: Claude Opus 4.8 (1M\n[…]\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* update readme\n\n* update readme\n\n* update readme\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: rewrite README as a value-prop front door + user-facing install…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T11:36:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bc01a48f19076c6e50cb1527a7e1bd25beba9d72",
          "body": "* Plan: install-project-scope — otacon install --project + codex skill migration\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* Phase 1: scope-aware install locations + Codex skill migration\n\nIntroduce InstallScope ({user} | {project,root}) and make claudeSkillPath /\ncodexS\n[…]\nArchive plan: install-project-scope (implemented)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "otacon install --project + Codex skill-folder migration (#13)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T08:47:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "217ae105000456bc1af2dd00d112f3f1f816919e",
          "body": "The Stop hook is a belt-and-suspenders backstop on top of the skill's\nnever-end-your-turn rule, not required setup. Stop flagging its absence\nas a problem:\n\n- doctor: include the stop-hook check only when registered (status ok);\n  omit it entirely when absent instead of emitting a warn.\n- install wi\n[…]\npt,\nand the script still blocks turn-end while a session is open. Updates\nDESIGN.md §16 and records the rationale in DECISIONS.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Make Stop hook optional in doctor/install UX",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-16T07:12:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f898608f5541b2e664831f7bd4cb2ed602cfe7fd",
          "body": null,
          "is_bot": false,
          "headline": "update readme",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T17:35:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2767b1a5ebb53ad2b64ac40e43c3cf5e4d795bf8",
          "body": null,
          "is_bot": false,
          "headline": "0.1.1",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T17:31:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90fbf30c09acf225cd2c66630f72487d1b4e6da2",
          "body": "…e.dir\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Plan: config-web-ui — Settings web UI + hierarchical config + worktre…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T17:27:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ba96396770746d4e6f96573f7ad88fbad2137a55",
          "body": "* Plan: deployment-and-install — npm publish, release flow, install docs\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* Phase 1: npm-publishable package + single-source version\n\npackage.json is now the single version source: scripts/gen-version.ts\nregenerates src/shared/ver\n[…]\n.\nDECISIONS: record the OIDC-over-token decision.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Deployment: npm publish, release flow, install docs (#10)",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T17:26:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f7841bfb5b97b3b101acda2a4a727fe592f7aa62",
          "body": null,
          "is_bot": false,
          "headline": "add logo",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T17:11:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0e01d53868480dc929df52097415bc0b892f066d",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Plan: deployment-and-install — npm publish, release flow, install docs",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T17:11:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "437b619646b748972d7f30d7b3a2439705bedea5",
          "body": "Removed project name header from README.",
          "is_bot": false,
          "headline": "Remove header from README.md",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T16:54:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1a9a109ac5b174ce0863b5635a280f85e96db18c",
          "body": null,
          "is_bot": false,
          "headline": "Update README with image and project description",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T16:52:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "790fce2d072c078bea9d4b1bf02c3408b9935117",
          "body": "… iOS auto-zoom (#9)\n\nThree coexisting-with-the-OS fixes for the phone review loop:\n\n- Retire the floating \"codec cursor\" toolbar for a Comment/Ask bar docked at a\n  fixed bottom edge, out of the zone where the un-suppressable native selection\n  and dictionary popovers land. Desktop keeps the c/q sh\n[…]\noms on\n  focus, while the viewport meta stays permissive so pinch-zoom still works.\n\nDESIGN.md/DECISIONS.md updated for all three.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Mobile review polish: docked selection bar, keyboard-aware sheets, no…",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T15:03:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "46cb69f45489917bdf02a47cda7bac6517d8abb5",
          "body": null,
          "is_bot": false,
          "headline": "move plans",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T14:50:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "258f614ac12306086f6c890bc1bac4eb4efc06fe",
          "body": "- Implement loop \"Finish\" now git mv's the committed plan into\n  docs/plans/archive/ as a commit on the impl branch on success, so it rides\n  in the PR and lands on the default branch only on merge. Aborted (--failed)\n  and plain Approve leave the plan active in docs/plans/.\n- Targeted protocol-card\n[…]\nECISIONS.md entry document the agent-owned plan\n  archival, distinct from `otacon clean` (which still never rewrites docs/plans/).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive plan after implementation; tighten protocol card",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T14:41:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "84454c2a7e6e98b06a9323be7b142ad45b01eadd",
          "body": "Add white-space: pre-wrap to .grill-question, .settled-answer, and .iv-q\nso multi-line grill questions, settled answers, and interview questions\nrender with their authored newlines instead of collapsing to one line —\nmatching the existing thread-body / iv-answer-body pattern.\n\nImplements docs/plans/2026-06-15-qa-card-line-breaks.md (Phase 1).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Preserve line breaks in grill/interview Q&A cards",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T14:20:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8c2db87326c2b06c25dd1554f47de04e3b2e7ab7",
          "body": "Approved otacon plan. Adds white-space: pre-wrap to grill-question,\nsettled-answer, and iv-q so multi-line grill/interview text renders\nwith line breaks, matching the thread/iv-answer-body pattern.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Plan: qa-card-line-breaks — preserve newlines in Q&A cards",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T14:14:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1ee8018b1526de45f6160533cd6c6ddcdccb9784",
          "body": null,
          "is_bot": false,
          "headline": "move plans",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T13:55:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e0e87fe4b94431226de094c789ca05d2c761bda1",
          "body": "…(#8)\n\n* Approve & Implement: implementing status machine, implement-done, UI\n\nImplements the planned Approve & Implement flow. The status machine grows an\n`approved → implementing → implemented | implement_failed` branch with a shared\nTERMINAL_STATUSES source of truth that the daemon's mutation gua\n[…]\nmmit anyway\", so its explanatory comment matches.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Approve & Implement: implementing status machine, implement-done, UI …",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T13:55:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0f00c2012d7bfb3f8bf925b1eb895d2291055c66",
          "body": null,
          "is_bot": false,
          "headline": "move archievd plans",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-15T13:50:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aa9a29d3eddedfa777b961635c3acfa8dc49d4b4",
          "body": "…scenarios (#7)\n\n* Review-altitude schema: optional Contract/Impact, lead diagrams, gwt scenarios\n\nGrow the plan schema toward the review-altitude goal — lead with intent and\nrisk, not steps. Three additions, all linted:\n\n- Optional `## Contract` / `## Impact` H2 sections, slotted at fixed positions\n[…]\n are covered by the manual branch-verify surface.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Review-altitude schema: optional Contract/Impact, lead diagrams, gwt …",
          "author_name": "Zero Liu",
          "author_login": "zeroliu",
          "committed_at": "2026-06-14T16:32:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 11,
      "commits_last_year": 178,
      "latest_release_at": "2026-07-10T21:59:01Z",
      "latest_release_tag": "v0.1.11",
      "releases_from_tags": false,
      "days_since_last_push": 5,
      "active_weeks_last_year": 6,
      "days_since_latest_release": 12,
      "mean_days_between_releases": 2.5
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": false,
      "has_contributing": false,
      "health_percentage": 28,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "otacon",
          "exists": true,
          "license": "MIT",
          "keywords": [],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/otacon",
          "is_deprecated": false,
          "latest_version": "0.1.11",
          "repository_url": "https://github.com/zeroliu/otacon",
          "versions_count": 21,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 2243,
          "first_published_at": "2026-06-15T17:29:20.917000Z",
          "latest_published_at": "2026-07-10T21:58:59.917000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 12
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 6,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 3
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "src/ui/tsconfig.json",
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 239907,
      "source_files_sampled": 266,
      "oversized_source_files": 2,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 2824
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [
          {
            "name": "@hono/node-server",
            "direct": true,
            "version": "1.19.14",
            "severity": "moderate",
            "ecosystem": "npm",
            "cvss_score": 5.9,
            "advisory_ids": [
              "GHSA-frvp-7c67-39w9"
            ],
            "fixed_version": "2.0.5",
            "advisory_count": 1,
            "oldest_advisory_days": 1
          },
          {
            "name": "dompurify",
            "direct": false,
            "version": "3.4.11",
            "severity": "low",
            "ecosystem": "npm",
            "cvss_score": 0,
            "advisory_ids": [
              "GHSA-c2j3-45gr-mqc4"
            ],
            "fixed_version": "3.4.12",
            "advisory_count": 1,
            "oldest_advisory_days": 1
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "low": 1,
          "moderate": 1
        },
        "advisory_count": 2,
        "affected_count": 2,
        "assessed_count": 122,
        "malicious_count": 0,
        "assessed_package": "npm:otacon@0.1.11",
        "unassessed_count": 0,
        "direct_affected_count": 1
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@hono/node-server",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^1"
        },
        {
          "name": "happy-dom",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^20.10.3"
        },
        {
          "name": "hono",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^4"
        },
        {
          "name": "mermaid",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^11.15.0"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "@hono/node-server",
            "direct": true,
            "version": "^1",
            "ecosystem": "npm"
          },
          {
            "name": "happy-dom",
            "direct": true,
            "version": "^20.10.3",
            "ecosystem": "npm"
          },
          {
            "name": "hono",
            "direct": true,
            "version": "^4",
            "ecosystem": "npm"
          },
          {
            "name": "mermaid",
            "direct": true,
            "version": "^11.15.0",
            "ecosystem": "npm"
          },
          {
            "name": "@playwright/test",
            "direct": false,
            "version": "^1.60.0",
            "ecosystem": "npm"
          },
          {
            "name": "@storybook/addon-a11y",
            "direct": false,
            "version": "^10.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "@storybook/react-vite",
            "direct": false,
            "version": "^10.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "@types/bun",
            "direct": false,
            "version": "latest",
            "ecosystem": "npm"
          },
          {
            "name": "@types/node",
            "direct": false,
            "version": "^24",
            "ecosystem": "npm"
          },
          {
            "name": "@types/react",
            "direct": false,
            "version": "^19.2.17",
            "ecosystem": "npm"
          },
          {
            "name": "@types/react-dom",
            "direct": false,
            "version": "^19.2.3",
            "ecosystem": "npm"
          },
          {
            "name": "@vitejs/plugin-react",
            "direct": false,
            "version": "^6.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "dompurify",
            "direct": false,
            "version": "^3.4.10",
            "ecosystem": "npm"
          },
          {
            "name": "highlight.js",
            "direct": false,
            "version": "^11.11.1",
            "ecosystem": "npm"
          },
          {
            "name": "lucide-react",
            "direct": false,
            "version": "^1.21.0",
            "ecosystem": "npm"
          },
          {
            "name": "marked",
            "direct": false,
            "version": "^18.0.5",
            "ecosystem": "npm"
          },
          {
            "name": "react",
            "direct": false,
            "version": "^19.2.7",
            "ecosystem": "npm"
          },
          {
            "name": "react-dom",
            "direct": false,
            "version": "^19.2.7",
            "ecosystem": "npm"
          },
          {
            "name": "storybook",
            "direct": false,
            "version": "^10.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "^5",
            "ecosystem": "npm"
          },
          {
            "name": "vite",
            "direct": false,
            "version": "^8.0.16",
            "ecosystem": "npm"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 21,
        "direct_count": 4,
        "indirect_count": 17
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 3,
        "merged_prs": 60,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 2
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "zeroliu",
          "commits": 178,
          "avatar_url": "https://avatars.githubusercontent.com/u/226076?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "release.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 3,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 0,
            "reason": "0 out of 21 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": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 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": 1,
            "reason": "dependency not pinned by hash detected -- score normalized to 1",
            "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": 9,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 4,
            "reason": "6 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "4df0b3491211286341f4e7556abff19af5915e2d",
        "ran_at": "2026-07-23T12:25:26Z",
        "aggregate_score": 3.6,
        "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-18T03:36:08Z",
      "oldest_open_prs": [
        {
          "number": 34,
          "created_at": "2026-06-24T13:52:30Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 53,
          "created_at": "2026-06-28T12:45:19Z",
          "last_comment_at": "2026-06-28T12:45:32Z",
          "last_comment_author": "coderabbitai"
        },
        {
          "number": 55,
          "created_at": "2026-06-28T14:22:28Z",
          "last_comment_at": "2026-06-28T14:22:41Z",
          "last_comment_author": "coderabbitai"
        }
      ],
      "last_merged_pr_at": "2026-07-18T03:36:06Z",
      "ci_last_conclusion": null,
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/zeroliu/otacon",
    "host": "github.com",
    "name": "otacon",
    "owner": "zeroliu"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 55,
      "inputs": {
        "security": 46,
        "vitality": 75,
        "community": 36,
        "governance": 55,
        "engineering": 55
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 75,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 58,
            "inputs": {
              "commits_last_year": 178,
              "human_commit_share": 1,
              "days_since_last_push": 5,
              "active_weeks_last_year": 6
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "6/52 weeks with commits",
                "points": 4.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "178 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 178
                    }
                  }
                ],
                "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": 11,
              "latest_release_tag": "v0.1.11",
              "releases_from_tags": false,
              "days_since_latest_release": 12,
              "mean_days_between_releases": 2.5
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "11 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 11
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 12 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 12
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~2.5 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 2.5
                    }
                  }
                ],
                "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": "at_risk",
        "name": "Community & Adoption",
        "value": 36,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 11,
            "inputs": {
              "forks": 0,
              "stars": 6,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "6 stars",
                "points": 11.3,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 6
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 56,
            "inputs": {
              "packages": [
                "otacon"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 2243
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "2,243 downloads/month across npm",
                "points": 44.7,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 2243,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 55,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 13,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "moderate",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 69,
            "inputs": {
              "merged_prs": 60,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 2
            },
            "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": "60/62 decided PRs merged",
                "points": 37,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 60,
                      "decided": 62
                    }
                  }
                ],
                "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": 56,
            "inputs": {
              "followers": 29,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "zeroliu",
              "public_repos": 44,
              "account_age_days": 5970
            },
            "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": "29 followers of zeroliu",
                "points": 10.6,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 29,
                      "login": "zeroliu"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "44 public repos, account ~16 yr old",
                "points": 24,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 44
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 16
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "otacon"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 12
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 12 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 12
                    }
                  }
                ],
                "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": "moderate",
        "name": "Engineering Quality",
        "value": 55,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "at_risk",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 48,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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 21 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": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": false
            },
            "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": 0,
                "status": "missed",
                "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": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 46,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 36,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 3.6
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "0 out of 21 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 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "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 1",
                "points": 0.5,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file 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": "detected GitHub workflow tokens with excessive permissions",
                "points": 6.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "6 existing vulnerabilities detected",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "good",
            "name": "Dependency advisories",
            "note": "Matched the npm:otacon@0.1.11 runtime dependency closure — what installing the published package pulls in — 122 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:otacon@0.1.11",
                  "assessed": 122
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 84,
            "inputs": {
              "source": "osv",
              "advisories": 2,
              "affected_packages": 2,
              "assessed_packages": 122,
              "unassessed_packages": 0,
              "affected_by_severity": "moderate 1, low 1",
              "direct_affected_packages": 1
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "1 affected: @hono/node-server 1.19.14 (moderate 5.9)",
                "points": 18.5,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "@hono/node-server 1.19.14 (moderate 5.9)"
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "1 affected: dompurify 3.4.11 (low)",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "dompurify 3.4.11 (low)"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory has been public longer than 90 days",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "advisories_none_stale",
                    "params": {
                      "days": 90
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 122,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 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": 68,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "good",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.73,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 2824
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "73 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 38.9,
                "status": "partial",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 73,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 44,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "src/ui/tsconfig.json",
                "tsconfig.json"
              ],
              "agent_commit_share": 0.65,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "src/ui/tsconfig.json, tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "src/ui/tsconfig.json, tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "65 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 65,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 1",
                "points": 1,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 239907,
              "source_files_sampled": 266,
              "oversized_source_files": 2
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "2/266 source files over 60KB",
                "points": 54.6,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 266,
                      "oversized": 2
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-23T12:25:40.167018Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/z/zeroliu/otacon.svg",
  "full_name": "zeroliu/otacon",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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