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

Foorack / kumidocs

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

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

53
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

58 关注者80 个公开仓库始于 2013年7月Sony Group Corporation

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布标签
npmkumidocs0.20260720.1568,9971396 天前wikidocsmarkdowngitbunself-hosted

按类别列示的指标

活力

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

45存在风险 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 6 天前
9.7/36提交节奏 — 52 周中有 14 周有提交
18/18提交量 — 最近一年 836 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year836
human_commit_share1
days_since_last_push6
active_weeks_last_year14
评分方式
0/27有发布版本 — 未发布任何发布版本
0/36发布时效 — 没有发布版本
0/27发布节奏 — 没有发布版本
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count0
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

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

36存在风险 · 占总体的 18%
评分方式
4.9/60星标 — 3 个星标
0/25复刻 — 2 个复刻
0/15关注者 — 1 位关注者
所用输入
forks2
stars3
watchers1
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
评分方式
52.7/80月度下载量 — npm 合计每月 8,997 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packageskumidocs
dependents
ecosystemsnpm
total_downloads
monthly_downloads8,997
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

63中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
2.7/13.5贡献者广度 — 2 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 5 contributing companies or organizations
所用输入
bus_factor1
contributors_sampled2
top_contributor_share0.999
评分方式
46.8/46.8议题解决 — 100% 的议题已关闭
38.2/38.3PR 接受 — 已裁定的 PR 中 6/6 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs6
open_issues0
closed_issues1
issue_closed_ratio1
closed_unmerged_prs0
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
12.7/25所有者影响力 — Foorack 有 58 位关注者
25/25既往记录 — 80 个公开仓库,账户约 13 年
所用输入
followers58
owner_typeUser
is_verified
owner_loginFoorack
public_repos80
account_age_days4,759
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — npm 上有 1 个软件包
35/35发布时效 — 最近一次发布于 6 天前
20/20版本历史 — 139 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packageskumidocs
ecosystemsnpm
any_deprecated
min_days_since_publish6

工程质量

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

58中等 · 占总体的 20%

工程实践

60中等
评分方式
24/24CI 工作流 — 1 个工作流
24/24存在测试
0/16Linter 配置
0/9.6Pre-commit 钩子
0/6.4.editorconfig
0/20OpenSSF Scorecard:CI-Tests — 无数据
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config
已排除计分(无数据或不适用):OpenSSF Scorecard:CI-Tests。 其余权重已重新归一化。

文档

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

安全

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

59中等 · 占总体的 16%

安全态势

58中等
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 无数据
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 5 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — 无数据
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate5.8
已排除计分(无数据或不适用):ci_tests, signed_releases。 其余权重已重新归一化。
评分方式
14/35直接依赖不含已知公告 — 1 个受影响:js-yaml 5.2.1 (high 7.5)
11/25间接依赖不含已知公告 — 1 个受影响:react-router 7.18.0 (high)
40/40没有长期未处理的公告 — 没有公告公开超过 90 天
所用输入
sourceosv
advisories2
affected_packages2
assessed_packages443
unassessed_packages0
affected_by_severityhigh 2
direct_affected_packages1
比对的是 npm:kumidocs@0.20260720.156 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 443 个软件包。 未对可达性进行分析。

AI 就绪度

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

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

关键数据

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

数据采集警告

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

更多细节

Star 与 Fork 历史 0 ★ / 2 ⇿
0Star
2Fork

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

111222212026-062026-062026-06
OpenSSF Scorecard 5.8 / 10
5.8综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
不适用CI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
10Contributorsproject has 5 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
7Vulnerabilities3 existing vulnerabilities detected
直接依赖 41
注册表软件包版本约束清单文件
npm@dnd-kit/core6.3.1package.json
npm@dnd-kit/sortable10.0.0package.json
npm@dnd-kit/utilities3.2.2package.json
npm@iconify-json/devicon1.2.62package.json
npm@iconify-json/flag1.2.12package.json
npm@iconify-json/fluent-color1.2.21package.json
npm@iconify-json/glyphs-poly1.2.0package.json
npm@iconify-json/logos1.2.11package.json
npm@noble/hashes2.2.0package.json
npm@radix-ui/react-label2.1.10package.json
npm@radix-ui/react-select2.3.1package.json
npm@radix-ui/react-slider1.4.2package.json
npm@radix-ui/react-slot1.3.0package.json
npm@streamdown/cjk1.0.3package.json
npm@streamdown/code1.1.1package.json
npm@streamdown/math1.0.2package.json
npm@streamdown/mermaid1.0.2package.json
npmclass-variance-authority0.7.1package.json
npmclsx2.1.1package.json
npmcmdk1.1.1package.json
npmcolor5.0.3package.json
npmdiff9.0.0package.json
npmhtml2canvas-pro2.2.0package.json
npmignore7.0.5package.json
npmjs-yaml5.2.1package.json
npmjspdf4.2.1package.json
npmkhroma2.1.0package.json
npmlinkedom^0.18.13package.json
npmlucide-react1.21.0package.json
npmminisearch7.2.0package.json
npmnext-themes0.4.6package.json
npmradix-ui1.6.0package.json
npmreact19.2.7package.json
npmreact-diff-view3.3.3package.json
npmreact-dom19.2.7package.json
npmreact-router-dom7.18.0package.json
npmrehype-harden1.1.8package.json
npmsonner2.0.7package.json
npmstreamdown2.5.0package.json
npmtailwind-merge3.6.0package.json
npmws8.21.0package.json
全部依赖 57

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

注册表软件包版本关系
npm@dnd-kit/core6.3.1直接
npm@dnd-kit/sortable10.0.0直接
npm@dnd-kit/utilities3.2.2直接
npm@iconify-json/devicon1.2.62直接
npm@iconify-json/flag1.2.12直接
npm@iconify-json/fluent-color1.2.21直接
npm@iconify-json/glyphs-poly1.2.0直接
npm@iconify-json/logos1.2.11直接
npm@noble/hashes2.2.0直接
npm@radix-ui/react-label2.1.10直接
npm@radix-ui/react-select2.3.1直接
npm@radix-ui/react-slider1.4.2直接
npm@radix-ui/react-slot1.3.0直接
npm@streamdown/cjk1.0.3直接
npm@streamdown/code1.1.1直接
npm@streamdown/math1.0.2直接
npm@streamdown/mermaid1.0.2直接
npmclass-variance-authority0.7.1直接
npmclsx2.1.1直接
npmcmdk1.1.1直接
npmcolor5.0.3直接
npmdiff9.0.0直接
npmhtml2canvas-pro2.2.0直接
npmignore7.0.5直接
npmjs-yaml5.2.1直接
npmjspdf4.2.1直接
npmkhroma2.1.0直接
npmlinkedom^0.18.13直接
npmlucide-react1.21.0直接
npmminisearch7.2.0直接
npmnext-themes0.4.6直接
npmradix-ui1.6.0直接
npmreact19.2.7直接
npmreact-diff-view3.3.3直接
npmreact-dom19.2.7直接
npmreact-router-dom7.18.0直接
npmrehype-harden1.1.8直接
npmsonner2.0.7直接
npmstreamdown2.5.0直接
npmtailwind-merge3.6.0直接
npmws8.21.0直接
npm@tailwindcss/typography0.5.20间接
npm@types/bun1.3.14间接
npm@types/color4.2.1间接
npm@types/node26.0.1间接
npm@types/react19.2.17间接
npm@types/react-dom19.2.3间接
npm@types/ws8.18.1间接
npm@typescript/native-preview7.0.0-dev.20260626.1间接
npmbun-plugin-tailwind0.1.2间接
npmcountry-flag-icons1.6.19间接
npmoxfmt0.56.0间接
npmoxlint1.71.0间接
npmoxlint-tsgolint0.23.0间接
npmtailwindcss4.3.1间接
npmtw-animate-css1.4.0间接
npmtypescript6.0.3间接
依赖安全公告 2

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

软件包版本关系严重程度公告数修复版本
js-yaml5.2.1直接15.2.2
react-router7.18.0间接18.3.0

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 27092,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "CSS": 15941,
        "HTML": 547,
        "TypeScript": 1227859
      },
      "pushed_at": "2026-07-20T11:22:58Z",
      "created_at": "2026-03-06T13:07:56Z",
      "owner_type": "User",
      "updated_at": "2026-07-20T11:23: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": "https://foorack.com/",
      "name": "Foorack / Max Faxälv",
      "type": "User",
      "login": "Foorack",
      "company": "Sony Group Corporation",
      "location": "European Union, SE/DK",
      "followers": 58,
      "avatar_url": "https://avatars.githubusercontent.com/u/5008081?v=4",
      "created_at": "2013-07-14T18:35:59Z",
      "is_verified": null,
      "public_repos": 80,
      "account_age_days": 4759
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [],
      "recent_commits": [
        {
          "oid": "1c3db31da59b81addde1b3cf900396002e649c18",
          "body": "idb-cache.ts, emoji-loader.ts, and register-mermaid-icons.ts use IndexedDB,\nfetch(), and other browser-only APIs. Kept lib/ for framework-independent\nshared code.",
          "is_bot": false,
          "headline": "refactor: move browser-only modules from lib/ to client/",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-20T09:55:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f1870ecc8b53f0523a5ed0c5cf940a2d0b83a39b",
          "body": "slides/utils.ts was mixing three concerns: slide constants (SLIDE_W/H),\nPDF/DOM overlay logic (document.createTreeWalker, jsPDF), and pure\nfunctions (splitSlides, buildCanvasStyle). Now each has its own file.",
          "is_bot": false,
          "headline": "refactor: split slides/utils.ts into constants.ts and pdf-overlay.ts",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-20T08:28:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "06da6d84c25687382bfdbce4a9df9b3e76b93b81",
          "body": "Adds MAGIC_BYTES constant to filetypes.ts with expected byte signatures\nfor PNG, JPEG, GIF, and WEBP. Upload handler now rejects files whose\ncontent doesn't match their declared extension, preventing extension\nrenaming attacks (e.g. .exe -> .png).",
          "is_bot": false,
          "headline": "feat: validate image upload content via magic bytes",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T19:38:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "03f924ae63e07cea542178e6fac3675c8ae31a61",
          "body": "File exported components (ContentArea, buildEditorContent) and type helpers,\nnot pure utilities. New name accurately reflects its contents.",
          "is_bot": false,
          "headline": "refactor: rename file-page/utils.tsx to editor-content.tsx",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T17:34:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "abf5033d262c615289c0e5de705742ce5c626cda",
          "body": "sortedObject wrapped objects in a Proxy to force alphabetical key ordering,\nbut js-yaml's sortKeys: true already sorts keys at every nesting level\nduring dump(). The Proxy was redundant.\n\nAdds bun test infrastructure and a test proving sortKeys: true works\nat all nesting levels.",
          "is_bot": false,
          "headline": "refactor: remove redundant sortedObject Proxy, add YAML sorting tests",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T17:27:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c3ecfac310529bd806cf76788cd4e3635458a4af",
          "body": "Add requireUserOr and requireRateLimitOr helpers to replace 16 copies of\nthe requireUser + rate-limit boilerplate pattern across route handlers.\n\nrequireUserOr: authenticate, return user or 401\nrequireRateLimitOr: authenticate + rate-limit, return user or error response",
          "is_bot": false,
          "headline": "refactor: extract auth guard helpers in router.ts",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T16:25:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "17b02bc4b073836fcef4801c225e86e4b8a13c2c",
          "body": "Function was copy-pasted in both lib/utils.ts and server/api-utils.ts.\nRemoved the server copy and pointed api-file.ts to the canonical lib/utils.ts version.",
          "is_bot": false,
          "headline": "refactor: consolidate duplicated assertJsonObject",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T16:15:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ea7702083aee767a7672223c6345d4188895c631",
          "body": "- Delete unused shadcn card.tsx and textarea.tsx components\n- Remove sendSaveConflict function (zero callers)\n- Remove /api/sidebar route and handler (never consumed by frontend)\n\nRemoves 121 lines.",
          "is_bot": false,
          "headline": "chore: remove dead code",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T15:43:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7fdc8c55a62657b4ce7cedd05565ff6c5322972e",
          "body": null,
          "is_bot": false,
          "headline": "refactor: relocate ticket dialog components to components/dialogs/ticket",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T15:34:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6f34866090402457e0bae43022cda6a76f27b4cd",
          "body": null,
          "is_bot": false,
          "headline": "refactor: centralize allowed background URL prefixes in slide.ts",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T07:01:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59362636ae1013ae29be9e3e935b1d3afa131c0f",
          "body": null,
          "is_bot": false,
          "headline": "fix: handle missing git repository in file GET endpoint",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T06:57:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f715bc73d05ea75467012fbb7682effc43ac2931",
          "body": null,
          "is_bot": false,
          "headline": "fix: log invalid WebSocket messages for debugging",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T06:54:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "34433c7e01eac1d61630e7fd0cbb787dbae58fea",
          "body": null,
          "is_bot": false,
          "headline": "fix: improve email validation in auth endpoint to match RFC 5321",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-19T06:51:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ec198ddb67098df1748fb8fd10b36db5bb212d59",
          "body": null,
          "is_bot": false,
          "headline": "fix: resolve symlinks in isSafePath to prevent path traversal bypass",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-18T21:36:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae96f58338d892688b37e619c2cbe879b3d5ad42",
          "body": "…ipts",
          "is_bot": false,
          "headline": "feat: add full-page mermaid diagram view and relax CSP for inline scr…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-18T21:12:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83704929dfa0ec1ed74277f955500c99c49f9e43",
          "body": null,
          "is_bot": false,
          "headline": "feat: add mermaid file type with icon and rendering support",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-18T20:46:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7ffb340edd384aebd478b1696cf9c3af70e5e861",
          "body": "Adds ok: true/false discriminant to the return type so callers\nuse proper type narrowing via result.ok instead of fragile\n'error' in result duck-checking.",
          "is_bot": false,
          "headline": "refactor: use discriminated union for duplicatePage return type",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T12:28:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4ea4ff6324ec76b5cdf26b91eac00228dfc80841",
          "body": "Replaces the verbose allProps intermediary with direct parameter\ndestructuring in both components.",
          "is_bot": false,
          "headline": "style: destructure children directly in ThemeProvider and Providers",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T10:46:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9b644f0d432f6519b2656c9b491f0a6c4f97730a",
          "body": "Previously returned 'just now' for any future timestamp. Now formats\nfuture dates more usefully (e.g. 'in 3 days') with sub-minute future\ndates still resolving to 'just now' for natural clock skew handling.",
          "is_bot": false,
          "headline": "fix: return 'in X units' for future dates in relativeTime",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T10:36:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c70db494814bab1a265629183279e41281cda818",
          "body": "Adds optional JWT verification using a base64-encoded JWKS passed via\nthe --jwks-base64 CLI flag or KUMIDOCS_JWKS_BASE64 env var. No outbound\nrequests are made -- keys are loaded at startup.\n\n- crypto.createPublicKey with JWK format validates RSA key material\n- Supports RS256, RS384, RS512 algorithms\n- Rejects alg:none, missing kid, unknown kid, and bad signatures\n- Fail-open when no JWKS configured (backward compatible)\n- Exposes jwtKids array in /api/me for client visibility",
          "is_bot": false,
          "headline": "feat: add JWT signature verification via --jwks-base64",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T10:33:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "609f951606a23998fb8c037c20d8d7dc2d29492a",
          "body": "useMountEffect cleanup now calls wsClient.disconnect(), closing the\nWebSocket connection and clearing timers when the component unmounts\n(e.g. on auth state change).",
          "is_bot": false,
          "headline": "fix: disconnect WebSocket on WsConnector unmount",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:50:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7bc875153aea8afdca7779ea2871742107d64028",
          "body": "The ternary rendered <MoreHorizontal /> in both branches regardless\nof dotsHovered/dotsOpen state. Simplified to a direct assignment.\nAlso dropped the unused state reads (now [, setDotsHovered]) since\nonly the setters are still wired to event handlers.",
          "is_bot": false,
          "headline": "fix: remove dead conditional in sidebar dotsIcon",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:49:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57c977fbc1b0667ffbdff1bedfb173e1d470d02a",
          "body": "Adds an isMountedRef that is set to false on unmount. The auto-save\nsetTimeout callback checks this ref before calling doSave, preventing\nstate updates on an unmounted component if the timer was set after\nthe cleanup already ran.",
          "is_bot": false,
          "headline": "fix: prevent auto-save timer from firing after unmount",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:44:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "98141562e87f537885c8dfe885b0b85fc990ea7a",
          "body": "…nt storms\n\nThe key included sidebarDefaultDepth, causing every sidebar node to\nunmount and remount when the config changed, losing all open/close\ntoggle state. node.path alone is unique and stable.",
          "is_bot": false,
          "headline": "fix: remove sidebarDefaultDepth from PageNodeRow key to prevent remou…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:41:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "56a3d3588de856721ec49ba9e0875bfc55bfbe75",
          "body": "The serial save queue caught but silently discarded errors from\nprior saves. Now logs them to console so they're visible during\ndebugging, while still allowing the queue to proceed.",
          "is_bot": false,
          "headline": "fix: log previous save errors in save queue instead of swallowing",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:38:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5bb1a8a1f842ff7b141ce1ab6191037830c40e80",
          "body": "…everywhere\n\nReplaces all three remaining gray-matter usages (filestore.ts, search.ts,\nbacklinks.ts) with the project's own parseFrontmatter from lib/frontmatter.ts.\nRemoves the gray-matter package from dependencies.",
          "is_bot": false,
          "headline": "refactor: remove gray-matter dependency, use custom parseFrontmatter …",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T08:24:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "645c4e91973f046622debd440543c6180cffcd33",
          "body": "Extracts the common title/path mapping logic into buildWikilinkLookup()\nin lib/wikilinks.ts. Both callers (buildLookupFromTree on the client,\nbuildLookup on the server) now collect page entries from their\nrespective data sources and delegate to the shared function.",
          "is_bot": false,
          "headline": "refactor: deduplicate wikilink lookup logic into shared function",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T07:02:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "60955641c8382a387bf5460a9f09f368649d6c34",
          "body": "Moves assertJsonObject from server/api-utils.ts into lib/utils.ts so both\nclient and server code can use it. Replaces 11 raw as Record<string, unknown>\ncasts across server/api.ts and lib/board.ts with runtime-validated assertions\nthat reject null, arrays, and primitives before treating the value as an object.\n\nAlso replaces as string casts in approval parsing with typeof guards plus\nempty-string fallback to prevent undefined from propagating into string fields.",
          "is_bot": false,
          "headline": "refactor: replace raw as Record casts with assertJsonObject validator",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T06:40:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "551c4306346c4fe51740d7dc8befe315da57af43",
          "body": "Three caches that could grow without bound now have size limits with\noldest-entry eviction:\n\n- ws.ts reopenCallbacks: capped at 100, drops oldest when full\n- emoji-icon.tsx dataUriCache: capped at 500, drops oldest when full\n- api-images.ts avatarCache: capped at 200, drops oldest when full",
          "is_bot": false,
          "headline": "fix: cap unbounded caches with LRU-style eviction",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-16T06:35:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "faadbcdf313725606bec40e2dfb46a06eee37a9c",
          "body": "Creates ErrorBoundary class component (src/components/ui/error-boundary.tsx)\nthat catches render-time errors in its subtree and shows a fallback UI\nwith a 'Try again' button instead of crashing the whole app.\n\nPlaced around <AppRoutes /> in app.tsx so all route-level pages (markdown\nviewer, board, image library, themes, etc.) are covered while providers\n(theme, user, tooltip) remain outside and survive a page crash.",
          "is_bot": false,
          "headline": "feat: add top-level error boundary to prevent white-screen crashes",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T11:14:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "36fc1a0d815ff54b7af3b45fa70937af85b63b7e",
          "body": "…n sha256Hex\n\ngit-ignore.ts: replace spawnSync/existsSync/readFileSync with async\nalternatives (execFileAsync, fs/promises access/readFile) so startup\nI/O doesn't block the event loop.\n\nruntime.ts: sha256Hex no longer creates intermediate Buffer.from()\ncopies. ArrayBuffer input uses a Uint8Array view directly, string\ninput passes encoding to hash.update(), Buffer input passes through.",
          "is_bot": false,
          "headline": "refactor: convert git-ignore to async I/O and eliminate Buffer copy i…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T10:53:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1475992c77ff45af7c702e2888105e159b4c1186",
          "body": "Previously the timestamp push was separated from the length check by an\nempty-bucket eviction branch, creating a window where two callers could\nobserve the same bucket state. Now the allow path is a single if-block\nthat checks, pushes, and returns with no intervening operations.",
          "is_bot": false,
          "headline": "refactor: make rate limiter check+record atomic in a single pass",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T09:41:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4abfcf816a0736c18c536710619d483bd298d2bb",
          "body": "The old sanitizeSvg used 8 chained .replaceAll() calls to blacklist\ndangerous elements and attributes. This is fundamentally flawed because\nXML is not a regular language -- regex cannot reliably handle CDATA\nsections, HTML entities, namespace tricks, or nested elements.\n\nNow uses linkedom's parseHTM\n[…]\n- Removes javascript:/data: URIs from href, src, action attributes\n- Restricts <use> hrefs to fragment-only references (#id)\n- Returns empty string on parse failure instead of serving un-sanitized SVG",
          "is_bot": false,
          "headline": "security: replace regex-based SVG sanitizer with DOM parser (linkedom)",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T09:32:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6d4eec89e954ab727b565916f9a9340e4b6900ca",
          "body": "…e derivation\n\n- app-shell.tsx: move activeEmails set computation from useEffect into\n  useMemo, leaving the effect only for the external-store sync side effect\n- sidebar-page-node.tsx: replace useEffect for auto-open on navigation\n  with render-time ref-based pattern, removing the useEffect dependency\n\nPer project convention: never useEffect(() => setX(f(y)), [y]);\ncompute inline during render instead.",
          "is_bot": false,
          "headline": "refactor: replace useEffect-derived state with useMemo and render-tim…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T09:11:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bddccd35e0359cf59be1cbfe27dd1650f7997c35",
          "body": null,
          "is_bot": false,
          "headline": "feat: set document title for board list page",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T08:19:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d48ee733583384f45f5206e87073acf4f7901b35",
          "body": null,
          "is_bot": false,
          "headline": "feat: extract shared BoardHeader component for board page headers",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-15T08:07:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ab2effef965ec62b5250f9de7d3eb147f01152a0",
          "body": null,
          "is_bot": false,
          "headline": "feat: display board icons in ticket create dialog board selector",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T11:25:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9af543f52727fcd7d0d1dfa56be2a92895f451b8",
          "body": "…dex entries",
          "is_bot": false,
          "headline": "fix: wrap discard calls in try-catch to prevent crashes on missing in…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T11:11:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0318e392ec8e8dbeae9e47f11a77e5a04976deb6",
          "body": null,
          "is_bot": false,
          "headline": "fix: ensure consistent key ordering in ticket YAML serialization",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T09:03:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "152155a085fe1cf3ea514db39a2598286fbc48a0",
          "body": null,
          "is_bot": false,
          "headline": "fix: enable sortKeys in ticketToYaml for consistent key ordering",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T06:56:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "04865acb615de45b5cd35224ff33cb03ec47a001",
          "body": null,
          "is_bot": false,
          "headline": "feat: add mode-specific favicons for board and docs views",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-14T04:25:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3a797a419601567599be38850b809c9c29f6fb93",
          "body": null,
          "is_bot": false,
          "headline": "refactor: use EmojiIcon for home, activity, approval, and version icons",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T14:54:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0d292bb10de7048bdf1c5fd92efa3bf6e10c1893",
          "body": "- Remove redundant value !== undefined check (Headers.get() returns string | null)\n- Move oxlint-disable comment to correct line for request.method ?? \"GET\"\n  defensive fallback (IncomingMessage.method is typed as string)",
          "is_bot": false,
          "headline": "chore: eliminate last two lint warnings in http-server.ts",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T11:33:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90f95bba80f6efe369cfd8f3e93c89a75d98e6f8",
          "body": "This rule catches real ReferenceError bugs with const/let/class access\nbefore initialization. The blanket suppress in http-server.ts was for\nhoisted function declarations (which are safe). No project-wide\nviolations exist -- only 2 inline suppressions in tree-components.tsx.",
          "is_bot": false,
          "headline": "fix: restore eslint/no-use-before-define as active rule",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T10:20:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "75e7d82142f5ed03a2c96bd0b90fc30b65996e50",
          "body": "…ted rules\n\n- Move eslint/id-length and no-use-before-define to .oxlintrc.json (project-wide)\n- Replace 17-rule file-level suppress with focused 8-rule comment for\n  Node/Bun portability patterns only\n- Add inline oxlint-disable-next-line for type assertions that cannot\n  be eliminated (Node EventEm\n[…]\ns DOM patterns, any casts from ws)\n- Remove unnecessary type assertion on route handler lookup\n- Two remaining false-positive warnings on Headers iterator and Record\n  index access (oxlint limitation)",
          "is_bot": false,
          "headline": "refactor: replace blanket oxlint-disable in http-server.ts with targe…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T10:15:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9581a71c9c0315e7bdb338b6e4eee6cd9b98bc8f",
          "body": null,
          "is_bot": false,
          "headline": "refactor: format cn() calls for readability across 11 files",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T09:46:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7ee2de41cfe14dd538f7c98b66d0d0b2548cfae1",
          "body": "…files\n\nEnsures Tailwind class conflicts are resolved by twMerge (inside cn()).\nFiles updated:\n- pages/: board-detail, board/card, file-page/header, image-library/page,\n           ticket/ticket-sidebar, ticket/timeline\n- components/dialogs/: page-action-dialogs\n- components/editor/markdown/: editor, inline-editor, csv-grid\n- components/layout/: app-shell, board-sidebar, sidebar-page-node,\n                      board-filter-bar, page-header-button",
          "is_bot": false,
          "headline": "refactor: replace raw template literal className with cn() across 16 …",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T09:44:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e2b193bbe1446deea512680be1caa2ee178cc712",
          "body": null,
          "is_bot": false,
          "headline": "chore: fix lint warnings in ticket-dialog",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T08:14:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "279789b668796b609a2328a0a0d1687b246ce914",
          "body": "- TicketDialog joins WS presence room for the ticket file on open\n- Acquires edit lock (editing_start) on Edit button click\n- Releases lock (editing_stop) on save, cancel, or dialog close\n- Blocks Edit button if another user holds the lock (shows warning toast)\n- Blocks comment submission and approval actions when locked\n- Shows amber banner when another user is editing the ticket\n- Server-side apiFilePut already enforces the lock via getEditorForPage",
          "is_bot": false,
          "headline": "fix: add write-lock to ticket editing via WebSocket presence",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T08:11:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ecfdaa24ada55e68e0d39caf5ffca99a5697891d",
          "body": null,
          "is_bot": false,
          "headline": "fix: remove dead validation guard in EmailSetupDialog",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:34:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "07c355d2c4bda78639bd2379e5bcb4461bc5e374",
          "body": null,
          "is_bot": false,
          "headline": "fix: replace try/catch flow control with MiniSearch discard()",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:33:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2a9196d41a2a222e2ac4d20d5acef9fa77bea49b",
          "body": null,
          "is_bot": false,
          "headline": "fix: replace numeric session counter with randomUUID",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:33:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0257a3ecebb04ecf02daa850c910441c1bb46b86",
          "body": null,
          "is_bot": false,
          "headline": "fix: prevent double submit on Enter in NewPageDialog",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:32:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8ac37763aa5b5a02edf8f3a6d6a5d10198e89533",
          "body": null,
          "is_bot": false,
          "headline": "fix: replace non-null assertion on wsDataStore with defensive throw",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:31:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b9dc7ff1312d58df7abab4378c1a822e4da43d4c",
          "body": null,
          "is_bot": false,
          "headline": "fix: replace unsafe as string assertions with ?? fallback in search",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:31:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a310958ce7acd374c6f552e5332522914c8538d0",
          "body": null,
          "is_bot": false,
          "headline": "fix: cap inflight request dedup map to prevent unbounded growth",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:30:45Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "46a76075cc40167ef052036b510685fdcec4ac46",
          "body": null,
          "is_bot": false,
          "headline": "fix: destructure all values from single useUser() call",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:30:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0153c18d21da92d8ea85a0a5587b5b56b42e294",
          "body": null,
          "is_bot": false,
          "headline": "refactor: use named import for isSafePath, drop redundant default export",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:29:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c501979328afac54ee48a742497882e79463a40d",
          "body": null,
          "is_bot": false,
          "headline": "Replace fragile regex with js-yaml for ticket YAML timestamp injection",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T07:27:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f8e58ed4fa4fc7b6707e1d1c410060e6fb11a53a",
          "body": null,
          "is_bot": false,
          "headline": "Fix path traversal vulnerability in SPA file serving",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:57:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b303b689f0506d0bd00a1f346c7fa29dfd7f7ea0",
          "body": null,
          "is_bot": false,
          "headline": "Fix eager eviction of empty rate-limit buckets",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:55:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a01469b1124798fda4b5bfe77cddab3a8473d77f",
          "body": null,
          "is_bot": false,
          "headline": "Pin ws and @types/ws to exact versions",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:50:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59637371ab6af2df93b49e4b4eb1f89bed11a4e1",
          "body": null,
          "is_bot": false,
          "headline": "Display theme names as-is in slide properties select",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:15:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "48328fe9d760521b4d2dd3ed44cf7c5cee73d826",
          "body": null,
          "is_bot": false,
          "headline": "Refactor state ordering and fix empty string handling in top-bar link",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:12:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2286eeff231938e485f38a29fcdae4fedc65a7e6",
          "body": "…mmit link",
          "is_bot": false,
          "headline": "Add repoUrl support to user context and use it in top-bar for HEAD co…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-13T05:09:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "84594ee9dec3b3514b6c14d38f45308640da4fd3",
          "body": null,
          "is_bot": false,
          "headline": "Remove custom paragraph component from slide markdown viewer",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T16:29:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8c89fb0cde547fe808d28dc1a7933e8c47a9a8b0",
          "body": null,
          "is_bot": false,
          "headline": "Sync editor cursor position to slide preview in scroll mode",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T16:19:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99907ffba042ec1253b26d26e7afa29348bcdee5",
          "body": "…s as completed in TASKS.md",
          "is_bot": false,
          "headline": "Mark User List, Sidebar Ticket Filtering, and Cross-Board Search task…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T14:01:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7e1876ed576cae0e6688f8366ac4cea8b8dadab",
          "body": "Sidebar ticket filtering (Task 4)",
          "is_bot": false,
          "headline": "Merge pull request #7 from Foorack/feat/filter-bar",
          "author_name": "Foorack / Max Faxälv",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T13:59:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a0805f4d2b46dc41939269c8bf93f2cd3363542",
          "body": "…put component; simplify sidebar callbacks",
          "is_bot": false,
          "headline": "Refactor board filter bar with user toggle, multi-line labels, and In…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T13:54:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c0d4d424a1aab6cc393b4b6cfe2f18b1fae000f8",
          "body": null,
          "is_bot": false,
          "headline": "Add separator between Copy link and Manage in board menu",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T13:13:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e0b98bf4958d55babd571a18bd548c6370eed176",
          "body": null,
          "is_bot": false,
          "headline": "Fix list spacing in AGENTS.md and format DropdownMenuContent inline",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:27:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad09ee30e5c0c483f7b607d02f3f9359e07e0d21",
          "body": "- Extracted hamburger menu trigger (MoreHorizontal button + dropdown\n  wrapper) into shared HeaderMenu component in layout/.\n- File page header now uses HeaderMenu wrapping PageMenuItems (same\n  items as before: Export, Duplicate, Move, Delete, etc.).\n- Board page header now has its own hamburger menu with:\n  - Open in new tab\n  - Copy link\n  - Manage (navigates to /bm/:slug for board management)\n- Updated AGENTS.md with Shared UI Patterns convention to prevent\n  future single-mode assumptions.",
          "is_bot": false,
          "headline": "Add shared HeaderMenu component, use in board header with Manage item",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:27:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "80669455404f35c3963feb00c4197a5ab602c96d",
          "body": "…age\"\n\nThis reverts commit c37e16e130d3c0c351a7c00a6cff88d1978a0e1d.",
          "is_bot": false,
          "headline": "Revert \"Remove Export PDF and Move/Delete from doc page menu, add Man…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:24:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c37e16e130d3c0c351a7c00a6cff88d1978a0e1d",
          "body": "- Removed onExportPdf from PageMenuItems (was passing exportPagePdf).\n- Removed onMove/onDelete from PageMenuItems (were Move/Delete items).\n- Added 'Manage' DropdownMenuItem after PageMenuItems that navigates\n  to /bm (board manager).",
          "is_bot": false,
          "headline": "Remove Export PDF and Move/Delete from doc page menu, add Manage",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:21:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b431b6dac1f98391c3f1ce444381dfe639e76987",
          "body": null,
          "is_bot": false,
          "headline": "Add me-3 to viewer avatar groups for spacing with header buttons",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T12:10:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ce49277eedc4259b429c36f243197b25cafaa8c9",
          "body": null,
          "is_bot": false,
          "headline": "Add grayscaleWhenInactive to Info/TOC PageHeaderButtons",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:51:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "40778b50e3b0de0d44923f0d80acbb730d7dd026",
          "body": null,
          "is_bot": false,
          "headline": "Add px-0 to commit history button entries",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:48:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7cb4bd6ba4d3621cd1bb419f42140fbaf75e5bf",
          "body": null,
          "is_bot": false,
          "headline": "Revert padding change, remove py-1.5 from commit tiles",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:47:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "94c76a1f767bb0eade600e2a26b850ab3232f7a0",
          "body": "…bold group labels",
          "is_bot": false,
          "headline": "Remove horizontal padding from commit history in PageInfo sidebar, un…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:45:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "916f1ba85ed173bc11fb1a133e118300ac85b215",
          "body": "- Renamed ArchiveButton -> PageHeaderButton (generic toggle for\n  page headers, accepts any fileType/label).\n- Moved from src/components/ui/ (general components) to\n  src/components/layout/ (app-specific layout component).\n- Replaced inline ToggleButton in file-page/header.tsx with\n  PageHeaderButton, removed dead ToggleButton function.",
          "is_bot": false,
          "headline": "Move PageHeaderButton from ui/ to layout/, remove old file",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:43:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "352971546b8909f0964eccf10ab35a47d031fb0b",
          "body": "…size=sm)",
          "is_bot": false,
          "headline": "Fix ArchiveButton height: add h-7 to match Info button (was h-8 from …",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:39:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5a0563108fa68f888133bc595e96b97bb27c0ddd",
          "body": null,
          "is_bot": false,
          "headline": "PageInfo/TOC sidebar icons 18 -> 17",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:34:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2283b4f30a0433cf063b3b2e9c87434901b6f514",
          "body": "- toc-sidebar: close X button -> Button variant=ghost size=icon-sm\n- page-info-panel: close X, commit group toggle, commit items -> Button\n- ticket-dialog: copy ID, clear assignee, assign-to-me -> Button\n- version-control-tab: commit click rows -> Button variant=ghost\n- top-bar: app logo from <button onClick={navigate}> to <a href='/'>\n  (supports middle-click, removes unused useNavigate import)",
          "is_bot": false,
          "headline": "Convert all bare button elements to use standard Button component",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:32:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "518601b0dc88b2b861b0d313e8241a4b8a7e6c6c",
          "body": "…o 18\n\n- ArchiveButton now uses <Button> component with variant='secondary'\n  (active) or 'ghost' (inactive) instead of bare <button>.\n- Board page Info button icon bumped from 16 to 18 (matches Archive).\n- File page TOC/Info toggle icons bumped from 16 to 18 (matches\n  board header).",
          "is_bot": false,
          "headline": "Standardize ArchiveButton to use Button component, unify icon sizes t…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:22:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d0f1cc8f93670e8af5be4e25e289911b4cd18294",
          "body": null,
          "is_bot": false,
          "headline": "Fix line height",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:21:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "16f35d1689a4de0203082a11534f51b6f70bff1f",
          "body": null,
          "is_bot": false,
          "headline": "Bump PageInfo/TOC sidebar icon size to 18",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:21:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "636ef395afd821956b7130d72587a76a1a94a402",
          "body": null,
          "is_bot": false,
          "headline": "Remove padding on X close button in PageInfo sidebar header",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:20:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d20f68b58d05924ddc28f0cbb520d2392f54d6f6",
          "body": "…s to tracking-wider\n\n- PageInfo sidebar: py-2 -> py-2.5 (matches column header height)\n- Main sidebar: removed pt-1 from text span (was making header 44px vs 38px)\n- All uppercase headings now use tracking-wider consistently:\n  page-info-panel labels, slide-themes headings, ticket-sidebar headings",
          "is_bot": false,
          "headline": "Fix header height inconsistency and standardize all uppercase heading…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:14:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ba744c1c9f7b48fcc977d9e129802f24690cb412",
          "body": null,
          "is_bot": false,
          "headline": "Match sidebar header tracking to board column headers (tracking-wider)",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:11:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c23c273747339584315e413cdd3181667b2ea0af",
          "body": null,
          "is_bot": false,
          "headline": "Fix TOC icon name: AppListDetail -> AppsListDetail",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:10:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b250622a114da15830b67067afdc5d9e6c57d3a6",
          "body": null,
          "is_bot": false,
          "headline": "Swap File/List icons in PageInfoPanel and TocSidebar for EmojiIcon",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:09:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d4baed783976757ef17b6a5951ed9245939c53ea",
          "body": null,
          "is_bot": false,
          "headline": "Swap lucide Info/List icons for EmojiIcon pageinfo/toc",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T11:05:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "01acf5e9eed84137d7debbf409cc9fc71bd75866",
          "body": "…n types",
          "is_bot": false,
          "headline": "Add pageinfo (DocumentText24Color) and toc (AppListDetail24Color) ico…",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T09:01:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6066f14a6eab12e7386a66d96e3e0938b8d10f0d",
          "body": null,
          "is_bot": false,
          "headline": "Remove mr-2 from ArchiveButton",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:58:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "18b79f4f0c67b7bea67837b3c8a701db5e0e423f",
          "body": null,
          "is_bot": false,
          "headline": "Bump board header py-1 to py-2",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:56:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cd027a30f3378aea4cb887ceeaf1d422ed8cf333",
          "body": null,
          "is_bot": false,
          "headline": "Use colon instead of comma in sort labels",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:42:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cca039ec8cb946fcbca6012c5d0643b6cf0b0071",
          "body": null,
          "is_bot": false,
          "headline": "Bump gap from space-y-0.5 to space-y-1",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:38:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "282134885f84da0e166ca7956a9ea1d9a56a0657",
          "body": null,
          "is_bot": false,
          "headline": "Add pb-2 back to filter bar for space above divider",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:36:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "90f303cd294b1f56e4f2735185afe7a6f3fbdbf3",
          "body": null,
          "is_bot": false,
          "headline": "Unify spacing: all gaps come from parent space-y-0.5 only",
          "author_name": "Foorack",
          "author_login": "Foorack",
          "committed_at": "2026-07-12T08:33:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 0,
      "commits_last_year": 836,
      "latest_release_at": null,
      "latest_release_tag": null,
      "releases_from_tags": false,
      "days_since_last_push": 6,
      "active_weeks_last_year": 14,
      "days_since_latest_release": null,
      "mean_days_between_releases": null
    },
    "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": "kumidocs",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "wiki",
            "docs",
            "markdown",
            "git",
            "bun",
            "self-hosted"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/kumidocs",
          "is_deprecated": false,
          "latest_version": "0.20260720.156",
          "repository_url": "https://github.com/Foorack/kumidocs",
          "versions_count": 139,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 8997,
          "first_published_at": "2026-03-13T09:54:29.418000Z",
          "latest_published_at": "2026-07-20T11:23:22.843000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 6
        }
      ]
    },
    "popularity": {
      "forks": 2,
      "stars": 3,
      "watchers": 1,
      "fork_history": {
        "days": [
          {
            "date": "2026-06-28",
            "count": 1
          },
          {
            "date": "2026-06-30",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 2,
        "total_forks": 2
      },
      "star_history": null,
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 419910,
      "source_files_sampled": 150,
      "oversized_source_files": 1,
      "agent_instruction_files": [
        "AGENTS.md"
      ],
      "agent_instruction_max_bytes": 10645
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [
          {
            "name": "js-yaml",
            "direct": true,
            "version": "5.2.1",
            "severity": "high",
            "ecosystem": "npm",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-pm4m-ph32-ghv5"
            ],
            "fixed_version": "5.2.2",
            "advisory_count": 1,
            "oldest_advisory_days": 1
          },
          {
            "name": "react-router",
            "direct": false,
            "version": "7.18.0",
            "severity": "high",
            "ecosystem": "npm",
            "cvss_score": null,
            "advisory_ids": [
              "GHSA-qwww-vcr4-c8h2"
            ],
            "fixed_version": "8.3.0",
            "advisory_count": 1,
            "oldest_advisory_days": 1
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "high": 2
        },
        "advisory_count": 2,
        "affected_count": 2,
        "assessed_count": 443,
        "malicious_count": 0,
        "assessed_package": "npm:kumidocs@0.20260720.156",
        "unassessed_count": 0,
        "direct_affected_count": 1
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@dnd-kit/core",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "6.3.1"
        },
        {
          "name": "@dnd-kit/sortable",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "10.0.0"
        },
        {
          "name": "@dnd-kit/utilities",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "3.2.2"
        },
        {
          "name": "@iconify-json/devicon",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.62"
        },
        {
          "name": "@iconify-json/flag",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.12"
        },
        {
          "name": "@iconify-json/fluent-color",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.21"
        },
        {
          "name": "@iconify-json/glyphs-poly",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.0"
        },
        {
          "name": "@iconify-json/logos",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.2.11"
        },
        {
          "name": "@noble/hashes",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.2.0"
        },
        {
          "name": "@radix-ui/react-label",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.1.10"
        },
        {
          "name": "@radix-ui/react-select",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.3.1"
        },
        {
          "name": "@radix-ui/react-slider",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.4.2"
        },
        {
          "name": "@radix-ui/react-slot",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.3.0"
        },
        {
          "name": "@streamdown/cjk",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.0.3"
        },
        {
          "name": "@streamdown/code",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.1.1"
        },
        {
          "name": "@streamdown/math",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.0.2"
        },
        {
          "name": "@streamdown/mermaid",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.0.2"
        },
        {
          "name": "class-variance-authority",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "0.7.1"
        },
        {
          "name": "clsx",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.1.1"
        },
        {
          "name": "cmdk",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.1.1"
        },
        {
          "name": "color",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "5.0.3"
        },
        {
          "name": "diff",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "9.0.0"
        },
        {
          "name": "html2canvas-pro",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.2.0"
        },
        {
          "name": "ignore",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "7.0.5"
        },
        {
          "name": "js-yaml",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "5.2.1"
        },
        {
          "name": "jspdf",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "4.2.1"
        },
        {
          "name": "khroma",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.1.0"
        },
        {
          "name": "linkedom",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.18.13"
        },
        {
          "name": "lucide-react",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.21.0"
        },
        {
          "name": "minisearch",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "7.2.0"
        },
        {
          "name": "next-themes",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "0.4.6"
        },
        {
          "name": "radix-ui",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.6.0"
        },
        {
          "name": "react",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "19.2.7"
        },
        {
          "name": "react-diff-view",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "3.3.3"
        },
        {
          "name": "react-dom",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "19.2.7"
        },
        {
          "name": "react-router-dom",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "7.18.0"
        },
        {
          "name": "rehype-harden",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "1.1.8"
        },
        {
          "name": "sonner",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.0.7"
        },
        {
          "name": "streamdown",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "2.5.0"
        },
        {
          "name": "tailwind-merge",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "3.6.0"
        },
        {
          "name": "ws",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "8.21.0"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "@dnd-kit/core",
            "direct": true,
            "version": "6.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "@dnd-kit/sortable",
            "direct": true,
            "version": "10.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "@dnd-kit/utilities",
            "direct": true,
            "version": "3.2.2",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/devicon",
            "direct": true,
            "version": "1.2.62",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/flag",
            "direct": true,
            "version": "1.2.12",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/fluent-color",
            "direct": true,
            "version": "1.2.21",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/glyphs-poly",
            "direct": true,
            "version": "1.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "@iconify-json/logos",
            "direct": true,
            "version": "1.2.11",
            "ecosystem": "npm"
          },
          {
            "name": "@noble/hashes",
            "direct": true,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "@radix-ui/react-label",
            "direct": true,
            "version": "2.1.10",
            "ecosystem": "npm"
          },
          {
            "name": "@radix-ui/react-select",
            "direct": true,
            "version": "2.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "@radix-ui/react-slider",
            "direct": true,
            "version": "1.4.2",
            "ecosystem": "npm"
          },
          {
            "name": "@radix-ui/react-slot",
            "direct": true,
            "version": "1.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "@streamdown/cjk",
            "direct": true,
            "version": "1.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "@streamdown/code",
            "direct": true,
            "version": "1.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "@streamdown/math",
            "direct": true,
            "version": "1.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@streamdown/mermaid",
            "direct": true,
            "version": "1.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "class-variance-authority",
            "direct": true,
            "version": "0.7.1",
            "ecosystem": "npm"
          },
          {
            "name": "clsx",
            "direct": true,
            "version": "2.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "cmdk",
            "direct": true,
            "version": "1.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "color",
            "direct": true,
            "version": "5.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "diff",
            "direct": true,
            "version": "9.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "html2canvas-pro",
            "direct": true,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "ignore",
            "direct": true,
            "version": "7.0.5",
            "ecosystem": "npm"
          },
          {
            "name": "js-yaml",
            "direct": true,
            "version": "5.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "jspdf",
            "direct": true,
            "version": "4.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "khroma",
            "direct": true,
            "version": "2.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "linkedom",
            "direct": true,
            "version": "^0.18.13",
            "ecosystem": "npm"
          },
          {
            "name": "lucide-react",
            "direct": true,
            "version": "1.21.0",
            "ecosystem": "npm"
          },
          {
            "name": "minisearch",
            "direct": true,
            "version": "7.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "next-themes",
            "direct": true,
            "version": "0.4.6",
            "ecosystem": "npm"
          },
          {
            "name": "radix-ui",
            "direct": true,
            "version": "1.6.0",
            "ecosystem": "npm"
          },
          {
            "name": "react",
            "direct": true,
            "version": "19.2.7",
            "ecosystem": "npm"
          },
          {
            "name": "react-diff-view",
            "direct": true,
            "version": "3.3.3",
            "ecosystem": "npm"
          },
          {
            "name": "react-dom",
            "direct": true,
            "version": "19.2.7",
            "ecosystem": "npm"
          },
          {
            "name": "react-router-dom",
            "direct": true,
            "version": "7.18.0",
            "ecosystem": "npm"
          },
          {
            "name": "rehype-harden",
            "direct": true,
            "version": "1.1.8",
            "ecosystem": "npm"
          },
          {
            "name": "sonner",
            "direct": true,
            "version": "2.0.7",
            "ecosystem": "npm"
          },
          {
            "name": "streamdown",
            "direct": true,
            "version": "2.5.0",
            "ecosystem": "npm"
          },
          {
            "name": "tailwind-merge",
            "direct": true,
            "version": "3.6.0",
            "ecosystem": "npm"
          },
          {
            "name": "ws",
            "direct": true,
            "version": "8.21.0",
            "ecosystem": "npm"
          },
          {
            "name": "@tailwindcss/typography",
            "direct": false,
            "version": "0.5.20",
            "ecosystem": "npm"
          },
          {
            "name": "@types/bun",
            "direct": false,
            "version": "1.3.14",
            "ecosystem": "npm"
          },
          {
            "name": "@types/color",
            "direct": false,
            "version": "4.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "@types/node",
            "direct": false,
            "version": "26.0.1",
            "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": "@types/ws",
            "direct": false,
            "version": "8.18.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/native-preview",
            "direct": false,
            "version": "7.0.0-dev.20260626.1",
            "ecosystem": "npm"
          },
          {
            "name": "bun-plugin-tailwind",
            "direct": false,
            "version": "0.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "country-flag-icons",
            "direct": false,
            "version": "1.6.19",
            "ecosystem": "npm"
          },
          {
            "name": "oxfmt",
            "direct": false,
            "version": "0.56.0",
            "ecosystem": "npm"
          },
          {
            "name": "oxlint",
            "direct": false,
            "version": "1.71.0",
            "ecosystem": "npm"
          },
          {
            "name": "oxlint-tsgolint",
            "direct": false,
            "version": "0.23.0",
            "ecosystem": "npm"
          },
          {
            "name": "tailwindcss",
            "direct": false,
            "version": "4.3.1",
            "ecosystem": "npm"
          },
          {
            "name": "tw-animate-css",
            "direct": false,
            "version": "1.4.0",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "6.0.3",
            "ecosystem": "npm"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 57,
        "direct_count": 41,
        "indirect_count": 16
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 6,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 1,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "Foorack",
          "commits": 833,
          "avatar_url": "https://avatars.githubusercontent.com/u/5008081?v=4"
        },
        {
          "type": "User",
          "login": "systeemgod",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/36364329?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.999
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "publish.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": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 5 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "1c3db31da59b81addde1b3cf900396002e649c18",
        "ran_at": "2026-07-26T16:35:21Z",
        "aggregate_score": 5.8,
        "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-20T11:23:26Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-12T13:59:38Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/Foorack/kumidocs",
    "host": "github.com",
    "name": "kumidocs",
    "owner": "Foorack"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 53,
      "inputs": {
        "security": 59,
        "vitality": 45,
        "community": 36,
        "governance": 63,
        "engineering": 58
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "at_risk",
        "name": "Vitality",
        "value": 45,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 74,
            "inputs": {
              "commits_last_year": 836,
              "human_commit_share": 1,
              "days_since_last_push": 6,
              "active_weeks_last_year": 14
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 6 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "14/52 weeks with commits",
                "points": 9.7,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 14
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "836 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 836
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "critical",
            "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": 1,
            "inputs": {
              "releases_count": 0
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "no releases published",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases_published",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "no releases",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases",
                    "params": {}
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "no releases",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_releases",
                    "params": {}
                  }
                ],
                "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": 5,
            "inputs": {
              "forks": 2,
              "stars": 3,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "3 stars",
                "points": 4.9,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "2 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "1 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "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": 66,
            "inputs": {
              "packages": [
                "kumidocs"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 8997
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "8,997 downloads/month across npm",
                "points": 52.7,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 8997,
                      "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": 63,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 22,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.999
            },
            "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": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "2 contributors",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "merged_prs": 6,
              "open_issues": 0,
              "closed_issues": 1,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "6/6 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 6,
                      "decided": 6
                    }
                  }
                ],
                "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": 60,
            "inputs": {
              "followers": 58,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "Foorack",
              "public_repos": 80,
              "account_age_days": 4759
            },
            "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": "58 followers of Foorack",
                "points": 12.7,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 58,
                      "login": "Foorack"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "80 public repos, account ~13 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 80
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 13
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "kumidocs"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 6
            },
            "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 6 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "139 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 139
                    }
                  }
                ],
                "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": 58,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 59,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 58,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 5.8
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "3 existing vulnerabilities detected",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "moderate",
            "name": "Dependency advisories",
            "note": "Matched the npm:kumidocs@0.20260720.156 runtime dependency closure — what installing the published package pulls in — 443 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:kumidocs@0.20260720.156",
                  "assessed": 443
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 65,
            "inputs": {
              "source": "osv",
              "advisories": 2,
              "affected_packages": 2,
              "assessed_packages": 443,
              "unassessed_packages": 0,
              "affected_by_severity": "high 2",
              "direct_affected_packages": 1
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "1 affected: js-yaml 5.2.1 (high 7.5)",
                "points": 14,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "js-yaml 5.2.1 (high 7.5)"
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "1 affected: react-router 7.18.0 (high)",
                "points": 11,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "react-router 7.18.0 (high)"
                    }
                  }
                ],
                "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": 443,
              "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": 4
            },
            "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": 66,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "good",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.65,
              "agent_instruction_files": [
                "AGENTS.md"
              ],
              "agent_instruction_max_bytes": 10645
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.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": "65 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 34.7,
                "status": "partial",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 65,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 43,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": true,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "tsconfig.json"
              ],
              "agent_commit_share": 0,
              "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": "tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "no agent-authored commits among the last 100",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_authored_commits",
                    "params": {
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 419910,
              "source_files_sampled": 150,
              "oversized_source_files": 1
            },
            "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": "1/150 source files over 60KB",
                "points": 54.6,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 150,
                      "oversized": 1
                    }
                  }
                ],
                "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-26T16:35:31.137602Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/f/Foorack/kumidocs.svg",
  "full_name": "Foorack/kumidocs",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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