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

khayll / sobree

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

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

58
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

Balázs Korossy个人账户
9 关注者12 个公开仓库始于 2015年8月

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

软件包生态系统

按类别列示的指标

活力

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

82良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 0 天前
5.5/36提交节奏 — 52 周中有 8 周有提交
18/18提交量 — 最近一年 298 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year298
human_commit_share0.72
days_since_last_push0
active_weeks_last_year8

发布纪律

100优秀
评分方式
27/27有发布版本 — 已发布 100 个发布版本
36/36发布时效 — 最近一次发布版本于 5 天前
27/27发布节奏 — 约每 0.2 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count100
latest_release_tag@sobree/zoom-controls@0.1.71
releases_from_tags
days_since_latest_release5
mean_days_between_releases0.2
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

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

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

社区健康

50中等
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(MIT)
0/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template
评分方式
62.7/80月度下载量 — npm 合计每月 50,588 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packages@sobree/mcp, @sobree/core, @sobree/review, @sobree/keyboard, @sobree/block-tools, @sobree/collab-server, @sobree/zoom-controls, @sobree/collab-providers
dependents
ecosystemsnpm
total_downloads
monthly_downloads50,588
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

52中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
0/10OpenSSF Scorecard:Contributors — project has 0 contributing companies or organizations -- score normalized to 0
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
0/46.8议题解决 — 没有议题或无数据
37.4/38.3PR 接受 — 已裁定的 PR 中 263/269 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/24 approved changesets -- score normalized to 0
所用输入
merged_prs263
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs6
已排除计分(无数据或不适用):议题解决。 其余权重已重新归一化。
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
7.2/25所有者影响力 — khayll 有 9 位关注者
20.1/25既往记录 — 12 个公开仓库,账户约 10 年
所用输入
followers9
owner_typeUser
is_verified
owner_loginkhayll
public_repos12
account_age_days3,983
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — npm 上有 8 个软件包
35/35发布时效 — 最近一次发布于 5 天前
20/20版本历史 — 69 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packages@sobree/mcp, @sobree/core, @sobree/review, @sobree/keyboard, @sobree/block-tools, @sobree/collab-server, @sobree/zoom-controls, @sobree/collab-providers
ecosystemsnpm
any_deprecated
min_days_since_publish5

工程质量

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

64中等 · 占总体的 20%

工程实践

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

文档

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

安全

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

51中等 · 占总体的 16%

安全态势

42存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2/2.5CI-Tests — 24 out of 30 merged PRs checked by a CI test -- score normalized to 8
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/24 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — 无数据
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — 无数据
6.8/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 42 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate4.2
已排除计分(无数据或不适用):packaging, signed_releases。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
13.2/25间接依赖不含已知公告 — 1 个受影响:@hono/node-server 1.19.14 (moderate 5.9)
40/40没有长期未处理的公告 — 没有公告公开超过 90 天
所用输入
sourceosv
advisories1
affected_packages1
assessed_packages100
unassessed_packages0
affected_by_severitymoderate 1
direct_affected_packages0
比对的是 npm:@sobree/mcp@0.1.71 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 100 个软件包。 未对可达性进行分析。

AI 就绪度

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

74良好 · 占总体的 0%
评分方式
45/45代理指令 — AGENTS.md
15/15机器可读文档(llms.txt) — 存在 llms.txt
40/40可读的提交历史 — 72 次人类提交中有 71 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.986
agent_instruction_filesAGENTS.md
agent_instruction_max_bytes22,997
评分方式
0/18一条命令的引导启动
22/22自动化测试
11/11Lint / 格式化配置 — biome.json
11/11静态类型检查 — apps/docs/tsconfig.json, apps/playground/tsconfig.json, packages/block-tools/tsconfig.json, packages/collab-providers/tsconfig.json, packages/collab-server/tsconfig.json, packages/core/tsconfig.json, packages/keyboard/tsconfig.json, packages/mcp/tsconfig.json, packages/review/tsconfig.json, packages/zoom-controls/tsconfig.json, tools/fixtures-gen/tsconfig.json
10/10可复现环境 — lockfile
10/10已体现的代理实践 — 最近 100 次提交中有 36 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
所用输入
has_nix
has_tests
lockfilespnpm-lock.yaml
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configsapps/docs/tsconfig.json, apps/playground/tsconfig.json, packages/block-tools/tsconfig.json, packages/collab-providers/tsconfig.json, packages/collab-server/tsconfig.json, packages/core/tsconfig.json, packages/keyboard/tsconfig.json, packages/mcp/tsconfig.json, packages/review/tsconfig.json, packages/zoom-controls/tsconfig.json, tools/fixtures-gen/tsconfig.json
agent_commit_share0.36
toolchain_manifests
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — TypeScript(静态类型)
55/55可控的文件大小 — 采样的 485 个源文件中有 0 个超过 60KB
所用输入
primary_languageTypeScript
largest_source_bytes54,709
source_files_sampled485
oversized_source_files0
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
20/20MCP 服务器
0/40可运行示例
所用输入
example_dirs
has_mcp_signal
api_schema_files

关键数据

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

数据采集警告

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

更多细节

OpenSSF Scorecard 4.2 / 10
4.2综合

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

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
8CI-Tests24 out of 30 merged PRs checked by a CI test -- score normalized to 8
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/24 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
不适用Packagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
9Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities42 existing vulnerabilities detected
直接依赖 18
注册表软件包版本约束清单文件
npm@sobree/block-toolsworkspace:*apps/playground/package.json
npm@sobree/collab-providersworkspace:*apps/playground/package.json
npm@sobree/coreworkspace:*apps/playground/package.json
npm@sobree/keyboardworkspace:*apps/playground/package.json
npm@sobree/reviewworkspace:*apps/playground/package.json
npm@sobree/zoom-controlsworkspace:*apps/playground/package.json
npmy-indexeddb^9.0.12apps/playground/package.json
npmyjs^13.6.30apps/playground/package.json
npmlib0^0.2.99packages/collab-server/package.json
npmws^8.18.0packages/collab-server/package.json
npmy-protocols^1.0.7packages/collab-server/package.json
npmfflate^0.8.2packages/core/package.json
npmyjs^13.6.30packages/core/package.json
npm@modelcontextprotocol/sdk^1.29.0packages/mcp/package.json
npm@sobree/coreworkspace:*packages/mcp/package.json
npm@napi-rs/canvas^0.1.100tools/fixtures-gen/package.json
npmdocx^9.0.3tools/fixtures-gen/package.json
npmpdfjs-dist^4.10.38tools/fixtures-gen/package.json
全部依赖 未采集

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

依赖安全公告 1

安装 npm:@sobree/mcp@0.1.71 会引入 100 个包(直接与传递):其中 1 个存在已知公告,0 个为直接依赖。

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

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 4196,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "CSS": 73610,
        "MDX": 8419,
        "HTML": 2712,
        "JavaScript": 34748,
        "TypeScript": 2960101
      },
      "pushed_at": "2026-07-23T03:45:05Z",
      "created_at": "2026-04-18T17:22:28Z",
      "owner_type": "User",
      "updated_at": "2026-07-23T02:53:42Z",
      "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": "http://www.balazskorossykhayll.com",
      "name": "Balázs Korossy",
      "type": "User",
      "login": "khayll",
      "company": null,
      "location": "Budapest, Hungary",
      "followers": 9,
      "avatar_url": "https://avatars.githubusercontent.com/u/13990683?v=4",
      "created_at": "2015-08-27T01:45:29Z",
      "is_verified": null,
      "public_repos": 12,
      "account_age_days": 3983
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "@sobree/zoom-controls@0.1.71",
          "kind": "other",
          "published_at": "2026-07-18T07:15:10Z"
        },
        {
          "tag": "@sobree/core@0.1.71",
          "kind": "other",
          "published_at": "2026-07-18T07:15:08Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.71",
          "kind": "other",
          "published_at": "2026-07-18T07:15:04Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.71",
          "kind": "other",
          "published_at": "2026-07-18T07:15:01Z"
        },
        {
          "tag": "@sobree/mcp@0.1.71",
          "kind": "other",
          "published_at": "2026-07-18T07:14:58Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.71",
          "kind": "other",
          "published_at": "2026-07-18T07:14:55Z"
        },
        {
          "tag": "@sobree/review@0.1.71",
          "kind": "other",
          "published_at": "2026-07-18T07:14:52Z"
        },
        {
          "tag": "@sobree/review@0.1.70",
          "kind": "other",
          "published_at": "2026-07-16T18:40:33Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.70",
          "kind": "other",
          "published_at": "2026-07-16T18:40:30Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.70",
          "kind": "other",
          "published_at": "2026-07-16T18:40:27Z"
        },
        {
          "tag": "@sobree/core@0.1.70",
          "kind": "other",
          "published_at": "2026-07-16T18:40:24Z"
        },
        {
          "tag": "@sobree/mcp@0.1.70",
          "kind": "other",
          "published_at": "2026-07-16T18:40:21Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.70",
          "kind": "other",
          "published_at": "2026-07-16T18:40:18Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.70",
          "kind": "other",
          "published_at": "2026-07-16T18:40:15Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.69",
          "kind": "other",
          "published_at": "2026-07-16T15:18:15Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.69",
          "kind": "other",
          "published_at": "2026-07-16T15:18:12Z"
        },
        {
          "tag": "@sobree/core@0.1.69",
          "kind": "other",
          "published_at": "2026-07-16T15:18:09Z"
        },
        {
          "tag": "@sobree/review@0.1.69",
          "kind": "other",
          "published_at": "2026-07-16T15:18:06Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.69",
          "kind": "other",
          "published_at": "2026-07-16T15:18:03Z"
        },
        {
          "tag": "@sobree/mcp@0.1.69",
          "kind": "other",
          "published_at": "2026-07-16T15:18:00Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.69",
          "kind": "other",
          "published_at": "2026-07-16T15:17:57Z"
        },
        {
          "tag": "@sobree/review@0.1.68",
          "kind": "other",
          "published_at": "2026-07-12T18:11:41Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.68",
          "kind": "other",
          "published_at": "2026-07-12T18:11:38Z"
        },
        {
          "tag": "@sobree/mcp@0.1.68",
          "kind": "other",
          "published_at": "2026-07-12T18:11:35Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.68",
          "kind": "other",
          "published_at": "2026-07-12T18:11:32Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.68",
          "kind": "other",
          "published_at": "2026-07-12T18:11:29Z"
        },
        {
          "tag": "@sobree/core@0.1.68",
          "kind": "other",
          "published_at": "2026-07-12T18:11:26Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.68",
          "kind": "other",
          "published_at": "2026-07-12T18:11:23Z"
        },
        {
          "tag": "@sobree/mcp@0.1.67",
          "kind": "other",
          "published_at": "2026-07-08T14:26:31Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.67",
          "kind": "other",
          "published_at": "2026-07-08T14:26:25Z"
        },
        {
          "tag": "@sobree/review@0.1.67",
          "kind": "other",
          "published_at": "2026-07-08T14:26:19Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.67",
          "kind": "other",
          "published_at": "2026-07-08T14:26:13Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.67",
          "kind": "other",
          "published_at": "2026-07-08T14:26:28Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.67",
          "kind": "other",
          "published_at": "2026-07-08T14:26:22Z"
        },
        {
          "tag": "@sobree/core@0.1.67",
          "kind": "other",
          "published_at": "2026-07-08T14:26:16Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.66",
          "kind": "other",
          "published_at": "2026-07-08T13:20:36Z"
        },
        {
          "tag": "@sobree/review@0.1.66",
          "kind": "other",
          "published_at": "2026-07-08T13:20:33Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.66",
          "kind": "other",
          "published_at": "2026-07-08T13:20:30Z"
        },
        {
          "tag": "@sobree/core@0.1.66",
          "kind": "other",
          "published_at": "2026-07-08T13:20:27Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.66",
          "kind": "other",
          "published_at": "2026-07-08T13:20:24Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.66",
          "kind": "other",
          "published_at": "2026-07-08T13:20:21Z"
        },
        {
          "tag": "@sobree/mcp@0.1.66",
          "kind": "other",
          "published_at": "2026-07-08T13:20:18Z"
        },
        {
          "tag": "@sobree/review@0.1.65",
          "kind": "other",
          "published_at": "2026-07-08T05:49:46Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.65",
          "kind": "other",
          "published_at": "2026-07-08T05:49:43Z"
        },
        {
          "tag": "@sobree/mcp@0.1.65",
          "kind": "other",
          "published_at": "2026-07-08T05:49:40Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.65",
          "kind": "other",
          "published_at": "2026-07-08T05:49:37Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.65",
          "kind": "other",
          "published_at": "2026-07-08T05:49:34Z"
        },
        {
          "tag": "@sobree/core@0.1.65",
          "kind": "other",
          "published_at": "2026-07-08T05:49:31Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.65",
          "kind": "other",
          "published_at": "2026-07-08T05:49:28Z"
        },
        {
          "tag": "@sobree/review@0.1.64",
          "kind": "other",
          "published_at": "2026-07-07T14:04:05Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.64",
          "kind": "other",
          "published_at": "2026-07-07T14:04:01Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.64",
          "kind": "other",
          "published_at": "2026-07-07T14:03:58Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.64",
          "kind": "other",
          "published_at": "2026-07-07T14:03:55Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.64",
          "kind": "other",
          "published_at": "2026-07-07T14:03:52Z"
        },
        {
          "tag": "@sobree/core@0.1.64",
          "kind": "other",
          "published_at": "2026-07-07T14:03:50Z"
        },
        {
          "tag": "@sobree/mcp@0.1.64",
          "kind": "other",
          "published_at": "2026-07-07T14:03:47Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.63",
          "kind": "other",
          "published_at": "2026-07-06T14:54:27Z"
        },
        {
          "tag": "@sobree/review@0.1.63",
          "kind": "other",
          "published_at": "2026-07-06T14:54:24Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.63",
          "kind": "other",
          "published_at": "2026-07-06T14:54:21Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.63",
          "kind": "other",
          "published_at": "2026-07-06T14:54:18Z"
        },
        {
          "tag": "@sobree/core@0.1.63",
          "kind": "other",
          "published_at": "2026-07-06T14:54:15Z"
        },
        {
          "tag": "@sobree/mcp@0.1.63",
          "kind": "other",
          "published_at": "2026-07-06T14:54:12Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.63",
          "kind": "other",
          "published_at": "2026-07-06T14:54:09Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.62",
          "kind": "other",
          "published_at": "2026-07-06T14:33:25Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.62",
          "kind": "other",
          "published_at": "2026-07-06T14:33:22Z"
        },
        {
          "tag": "@sobree/review@0.1.62",
          "kind": "other",
          "published_at": "2026-07-06T14:33:19Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.62",
          "kind": "other",
          "published_at": "2026-07-06T14:33:16Z"
        },
        {
          "tag": "@sobree/mcp@0.1.62",
          "kind": "other",
          "published_at": "2026-07-06T14:33:13Z"
        },
        {
          "tag": "@sobree/core@0.1.62",
          "kind": "other",
          "published_at": "2026-07-06T14:33:10Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.62",
          "kind": "other",
          "published_at": "2026-07-06T14:33:07Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.61",
          "kind": "other",
          "published_at": "2026-07-06T14:13:04Z"
        },
        {
          "tag": "@sobree/review@0.1.61",
          "kind": "other",
          "published_at": "2026-07-06T14:13:01Z"
        },
        {
          "tag": "@sobree/mcp@0.1.61",
          "kind": "other",
          "published_at": "2026-07-06T14:12:58Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.61",
          "kind": "other",
          "published_at": "2026-07-06T14:12:55Z"
        },
        {
          "tag": "@sobree/core@0.1.61",
          "kind": "other",
          "published_at": "2026-07-06T14:12:52Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.61",
          "kind": "other",
          "published_at": "2026-07-06T14:12:49Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.61",
          "kind": "other",
          "published_at": "2026-07-06T14:12:46Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.60",
          "kind": "other",
          "published_at": "2026-07-06T08:16:14Z"
        },
        {
          "tag": "@sobree/mcp@0.1.60",
          "kind": "other",
          "published_at": "2026-07-06T08:16:11Z"
        },
        {
          "tag": "@sobree/review@0.1.60",
          "kind": "other",
          "published_at": "2026-07-06T08:16:08Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.60",
          "kind": "other",
          "published_at": "2026-07-06T08:16:05Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.60",
          "kind": "other",
          "published_at": "2026-07-06T08:16:02Z"
        },
        {
          "tag": "@sobree/core@0.1.60",
          "kind": "other",
          "published_at": "2026-07-06T08:15:59Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.60",
          "kind": "other",
          "published_at": "2026-07-06T08:15:56Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.59",
          "kind": "other",
          "published_at": "2026-07-06T08:09:18Z"
        },
        {
          "tag": "@sobree/review@0.1.59",
          "kind": "other",
          "published_at": "2026-07-06T08:09:15Z"
        },
        {
          "tag": "@sobree/core@0.1.59",
          "kind": "other",
          "published_at": "2026-07-06T08:09:12Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.59",
          "kind": "other",
          "published_at": "2026-07-06T08:09:09Z"
        },
        {
          "tag": "@sobree/mcp@0.1.59",
          "kind": "other",
          "published_at": "2026-07-06T08:09:06Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.59",
          "kind": "other",
          "published_at": "2026-07-06T08:09:03Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.59",
          "kind": "other",
          "published_at": "2026-07-06T08:09:00Z"
        },
        {
          "tag": "@sobree/mcp@0.1.57",
          "kind": "other",
          "published_at": "2026-07-05T21:15:42Z"
        },
        {
          "tag": "@sobree/zoom-controls@0.1.57",
          "kind": "other",
          "published_at": "2026-07-05T21:15:39Z"
        },
        {
          "tag": "@sobree/review@0.1.57",
          "kind": "other",
          "published_at": "2026-07-05T21:15:36Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.57",
          "kind": "other",
          "published_at": "2026-07-05T21:15:33Z"
        },
        {
          "tag": "@sobree/keyboard@0.1.57",
          "kind": "other",
          "published_at": "2026-07-05T21:15:30Z"
        },
        {
          "tag": "@sobree/collab-providers@0.1.57",
          "kind": "other",
          "published_at": "2026-07-05T21:15:27Z"
        },
        {
          "tag": "@sobree/core@0.1.57",
          "kind": "other",
          "published_at": "2026-07-05T21:15:24Z"
        },
        {
          "tag": "@sobree/core@0.1.56",
          "kind": "other",
          "published_at": "2026-07-05T15:53:45Z"
        },
        {
          "tag": "@sobree/block-tools@0.1.56",
          "kind": "other",
          "published_at": "2026-07-05T15:53:42Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "b944ee5398e7f80a9cdc3128717a8eb4d20467d0",
          "body": "…t sides, inline frames (#270)\n\nTier 1b completion — every drawing form the editor models now serializes:\ndrawing groups (wpg:wgp, nested grpSp, child coordinate systems), custom\ngeometry (a:custGeom re-built from the stored SVG path, byte-identical d),\nheader/footer floating frames (re-anchored per\n[…]\nhape-only inline groups, even-page parts.\n\n6 new round-trip suites; LibreOffice converts a groups+custGeom+inline+\nfloat package to PDF; full gate green (1510 tests, corpus:check,\ncorpus:pages, docs).",
          "is_bot": false,
          "headline": "Complete drawing export: groups, custGeom, header/footer frames, floa…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-23T02:53:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d1620d5138a60df2e46bb1c11f381754080673da",
          "body": "Tier 1b slice 1 (re-filed from #269): anchored pictures, textboxes and\npreset-geometry shapes serialize back to <wp:anchor> — all three OOXML\npositioning forms with the importer's precedence (wp14 percent > align >\nEMU offset), wp14 percent sizes, wrap modes (tight/through carry a\nsynthesized full-e\n[…]\ndocument.\nThe anchors ⇄ document import cycle is broken via an injected block\nrenderer (table.ts's own pattern). 10 round-trip tests; LibreOffice\nconverts the exported package to PDF; full gate green.",
          "is_bot": false,
          "headline": "Export anchored floating drawings to wp:anchor DrawingML (#271)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-23T02:49:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "926b883b67bc603b077358af2d3a30fa21c6982d",
          "body": "Tier 1a of devdocs/plan-ooxml-full-support.md: footnotes and comment threads\nimported and rendered but were DROPPED on save. export/notes.ts emits\nfootnotes.xml (stock separator notes first — the importer skips those),\ncomments.xml (author/initials/date + body) and commentsExtended.xml\n(done/reply t\n[…]\n never emits runDefaults /\ntabStops for any paragraph — plan item 2e.\n\n13 focused round-trip tests; LibreOffice converts the output to PDF\n(external referee). Full gate green (1494 tests at the time).",
          "is_bot": false,
          "headline": "Export footnotes and comments (#268)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-23T02:43:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "601274e31dfa2be7397682327eff52c6841fd8df",
          "body": "Exact recurrence of the 0.1.70 failure mode: the Version Packages squash\napplied every bump but orphaned the lockstep changeset, so publish ran\nversion-mode and npm stayed on 0.1.70. Orphan's bump is already realized in\nevery package.json; deleting it lets this push run changeset publish.",
          "is_bot": false,
          "headline": "Remove orphaned lockstep changeset to unblock 0.1.71 publish (#264)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-18T07:11:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "00e3d66beb48f0772a995ccc058e4c7d477a356a",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#263)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-18T07:06:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "53bb942ebce833ae0d827278c57f62a3bfa06096",
          "body": "#260 covers core+keyboard, #261 covers core. Lockstep bump for the remaining\nfive @sobree/* packages so the set releases together on 0.1.71.",
          "is_bot": false,
          "headline": "Add coordinated version bump for 0.1.71 (#262)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-18T07:05:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fd4f935580e0ffc430dca75e1720b5a8175d01f5",
          "body": "…#261)\n\nReported: select part of a paragraph (spanning into the next block), copy,\npaste — the WHOLE paragraphs appeared. The structured-clipboard copy treated\nany multi-block range as whole-block coverage, so the payload carried the full\nendpoint blocks with the offsets ignored. The same function f\n[…]\nrowser-verified on the Field Almanac: sliced\ncopy payload; paste-over-active-selection is a clean replace (36→36); paste\nat the paragraph end yields paragraph / heading (own block) / fragment\n(36→38).",
          "is_bot": false,
          "headline": "Copy/cut carry exactly the selection, not the whole endpoint blocks (…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-18T07:01:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "99c11b553dd897a27cf8dacbbab5b07ea6251178",
          "body": "Tab in a table cell selects the NEXT cell's content (Shift+Tab the previous),\nwrapping across rows — Word/Docs muscle memory. Lives in @sobree/keyboard as\ntwo bindings dispatching new core commands (`table.cellNext` / `table.cellPrev`);\nthe command bus stays the single owner of what the keys do.\n\nTh\n[…]\n the block.\n\nFull gate green (1479 tests). Browser-verified: Tab walks cells with content\nselected, Shift+Tab returns, last-cell Tab is a consumed no-op, Tab outside\ntables stays native. Docs updated.",
          "is_bot": false,
          "headline": "Tab / Shift+Tab move between table cells (#260)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-18T07:01:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fb4f24e9c243066d01dcb9cfb4999d253ed42281",
          "body": "The 0.1.70 Version Packages merge applied every package's bump but left\n.changeset/lockstep-0.1.70.md behind, so the post-merge publish ran in version\nmode instead of publishing (npm stayed on 0.1.69). Deleting the orphan — already\nrealized in every package.json — leaves zero changesets, so this push runs\nchangeset publish and ships 0.1.70.",
          "is_bot": false,
          "headline": "Remove orphaned lockstep changeset to unblock 0.1.70 publish (#259)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-16T18:36:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57b620162822b4cb192d31be23f7e2f32abb09f6",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#257)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-16T18:27:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b4c8f37e58a5ae7c5fa8b79bf412d98f294f7248",
          "body": "#254 and #255 landed with @sobree/core-only changesets. Add the lockstep bump\nfor the other six @sobree/* packages so the whole set releases on one version\n(0.1.70), as 0.1.69 did.",
          "is_bot": false,
          "headline": "Add coordinated version bump for 0.1.70 (#256)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-16T18:23:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5abf030c7bea93353ea4d76e0b76f2001763d4e7",
          "body": "…t (#255)\n\nReported: refreshing the almanac changed page 1's vertical alignment — a centred\ntitle page came back top-aligned.\n\nNot a Y.Doc parity issue: `vAlign` round-trips through the Y.Doc intact, and\n`getSectionSetup(0).verticalAlign` reads \"center\" even while the page renders\ntop-aligned. The d\n[…]\nails on the old order with `expected '' to be\n'center'`. No render output changes — only WHEN sections are pushed. Full gate\ngreen; browser-verified (209px above the first block after refresh, was 0).",
          "is_bot": false,
          "headline": "Apply section vAlign on a Y.Doc-hydrated mount, not just after an edi…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-16T18:19:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9ca43ae3f7fea857b6659ff4aa4e6f695e0842dc",
          "body": "Two reported bugs, one cause: the ops address `doc.body`, and a caret in a table\ncell resolves to its TABLE.\n\n  - Tracked typing in a cell was consumed and then DROPPED (`insertRun` /\n    `deleteRange` need a body paragraph and fail for a cell caret, but the\n    handler returned \"consumed\" regardles\n[…]\nirst line — unchanged, and noted.\n\nFull gate green (1468 tests, corpus:check, corpus:pages, docs). The 24 updated\nrender snapshots gain `data-cell` and nothing else. Browser-verified for both\nreports.",
          "is_bot": false,
          "headline": "Make table cells real positions for the ops (#254)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-16T18:19:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1c7c4cbd271f3e209f2bdc102e0ee2645581af0e",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#250)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-16T15:14:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f31ff2fcfe91b355750c878c6d32ef2f1c483cb0",
          "body": "#248/#249/#251/#252 landed since 0.1.68 with only #249's changeset present, so\nthe release would have published the model-first editing work with no changelog\nentry.\n\nOne @sobree/core entry describes the NET user-visible change rather than the\ninternal sequence. #252 fixed regressions from #251, but\n[…]\n version and\nannouncing fixes for them would confuse users who never had them. The existing\nlockstep-incremental-render changeset already covers the coordinated bump for\nthe rest of the @sobree/* set.",
          "is_bot": false,
          "headline": "Add changeset for model-first editing (0.1.69) (#253)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-16T15:09:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "740b25d27668de07d324f7ddd4b07a11afd5c94c",
          "body": "Three regressions from #251: an edit that used to go through the browser now\ngoes through the ops API, and each of these is something the native path did\nimplicitly that the API path failed to reproduce.\n\n1. PASTE DROPPED COLOUR / SMALL-CAPS ON A SEMANTIC TAG. `serializeInlineChildren`\n   read a sem\n[…]\nfore #251. Tracked-mode typing in a cell hits\n   the same gap; that predates this branch and is unchanged here.\n\nRegression tests for each. Full gate green; browser-verified on the Field\nAlmanac seed.",
          "is_bot": false,
          "headline": "Fix three model-first editing regressions (#252)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-16T15:02:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "4605b3a69f75b7b85bcb8a93ae7aac4abc0fefb1",
          "body": "… (#251)\n\n* Incremental pagination: skip re-flow when no page break moved (PR 3a)\n\n`PaperStack.repaginate` re-collected, re-measured, and re-distributed every\nblock on every change event — even the common keystroke that moves no page\nbreak. This adds a fast path: after each re-flow, snapshot the top\n[…]\n gap\n(non-text runs aren't stamped) into the existing image-run limitation.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Model-first editing: route every common edit path through the ops API…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-16T06:17:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4e2828113fa476c515f487e9010d81421de6eabe",
          "body": "An edit ran `renderSobreeDocument` → `host.replaceChildren()`, rebuilding\nEVERY block's DOM node. Now the change pipeline decides which blocks may keep\ntheir existing node — structure unchanged AND content byte-identical — and\nharvests those nodes from the live hosts before the wipe; `renderBlocks` \n[…]\n nodes. Full suite + corpus:check + corpus:pages\nunchanged.\n\nPR 2 of the model-first editing milestone (`devdocs/plan-model-first-editing.md`).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Incremental render: reuse unchanged block nodes on edit (#249)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-13T18:50:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b7665371fc3679e2a5537044e706c7114db8bbbd",
          "body": "…248)\n\nA deterministic bench for the incremental-render work: it counts how many\nblock DOM elements a single-block edit RE-CREATES vs reuses, by comparing\nelement identity across the re-render (wall-clock would be flaky; identity\nis exact).\n\nToday an API edit runs `renderSobreeDocument` → `host.repl\n[…]\nother\nblock's node (reused === N − 1) and this test's assertion flips — it's the\nmilestone's guard.\n\nPlan: devdocs/plan-model-first-editing.md.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add render-node-reuse baseline test (model-first editing, Stage 1) (#…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-13T15:18:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "647b505131768125f1b2aa4ff6bb3e3270d0aa8b",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#247)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-12T18:08:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9f488bac0501e12046d89de5096b736c2958b19d",
          "body": "…entEditable (#246)\n\nA paragraph-boundary Backspace (caret at a paragraph start) or Delete\n(caret at a paragraph end) is a paragraph MERGE. Untracked, it fell\nthrough to the browser's native contentEditable merge, which is lossy:\nChromium strips inline run formatting (small-caps, colour, font-size) \n[…]\n Backspace\nat the next line's start — the merged line kept only bold, losing\nsmall-caps / amber / 11pt. Now the whole merged line stays styled.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Merge paragraphs through the API on Backspace/Delete, not native cont…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-12T18:03:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0e06efb085d1e051c3ed023485315f65d7a5635f",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#245)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-08T14:22:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a6f61fbd349593d1f323589408e8a4845902c35",
          "body": "… (#244)\n\nA `<w:shd w:val=\"pct40\" w:color=\"auto\" w:fill=\"auto\"/>` — the common grey\ndivider-column idiom — paints ~40% grey (40% of the foreground over the\nbackground), but Sobree rendered it white: `readShading` discarded any shd\nwith `fill=\"auto\"`, and the cell / paragraph / run renderers only rea\n[…]\nrned shading is handled identically.\n\nFixes the grey divider column on table-heavy documents (and nist-cui-ssp's\ngrey cells, previously white).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Composite pattern shading (pctN) so grey <w:shd> cells aren't dropped…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T14:16:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a08a473eecd02e4d8f22c264444dd50a0981e666",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#243)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-08T13:17:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2d0e43a25a3b119fe51ac4c861fdc0cfe58b6958",
          "body": "Patch release covering PRs #235–#241: pure mutation-engine extraction\n(inline/range + revision/comment) with HeadlessSobree parity, the typed\nsobree.paperLayout bridge, and the patch-type / page-setup / selection-\ndescriptor ownership moves. Additive + internal — no breaking changes.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: changesets for the architecture-ownership patch (0.1.66) (#242)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T13:11:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dc7d3996dd82618f2eb697fb640dcef354b83ea6",
          "body": "…e (#241)\n\nPhase 5's deferred PR-8: the *consumption* side of tracked changes and\ncomment resolve/reopen were still `EditorContext`-bound under editor/ops,\nso headless/MCP couldn't review revisions an agent (or human) had made.\n\n- New `doc/mutations/comments.ts` — pure `resolveCommentMutation` /\n  `\n[…]\ne; comment resolve/reopen +\nunknown-id failure), each in-memory + Y.Doc reload. Existing\nfeature.revision / review / comment suites stay green.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Extract the revision/comment mutation engine; mirror on HeadlessSobre…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T13:07:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2bba929a1455e69d3ac74727c67f864df2c2aca7",
          "body": "`paperStack/pageSetup.ts` is a fully self-contained page-geometry model\n(page sizes, orientation, margins, vAlign, zone-text + pure dimension/\ntemplate helpers — no DOM), but it lived under `paperStack/`. The pure\n`doc/pageSetupBridge` and `docx/{shared/pageSize,import/headers}` zones\nimported it up\n[…]\n gone, tighten the Phase 2 architecture check:\npure zones (doc/ydoc/pagination/docx) may no longer import `paperStack`\neither. Negative-tested.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Move the pure page-setup model into the document layer (#240)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T13:06:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2cbd32b5cf30c1adf8a3be7e1586de71576d1f23",
          "body": "Inline authoring decisions (run properties, run insertion, range deletion,\nin both direct-edit and track-changes modes) lived under `editor/ops/runs`,\nbound to `EditorContext` — so `HeadlessSobree`/MCP couldn't reuse them and\nagents had to rebuild whole blocks. This is the Phase 5 core of the\nowners\n[…]\nt's not exposed\" list.\n\nFollow-up (plan PR 8): extract the revision accept/reject + comment\nmutation engines and mirror them on HeadlessSobree.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Extract the pure inline/range mutation engine (#239)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T13:05:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "abf11f0ffc226f51ac8b61cf7c6f38135aae2dff",
          "body": "`paperStack` reached into `editor/internal/positionMap` for the selection\ndescriptor it captures/restores around a repagination DOM rebuild — a DOM\nlayout adapter depending on the editor's PRIVATE surface (the plan's\nPhase 4; AGENTS.md: pure/adapter zones shouldn't import editor internals).\n\nSelecti\n[…]\ninternal/**` (negative-tested). `editor/view/docRenderer` stays a\nlegitimate paperStack dependency; only the private `internal` path is\nbanned.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Move repagination selection descriptor out of editor internals (#238)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T13:04:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e897361f676b37bcbc60f223be5329183a0c8c35",
          "body": "Plugins hardcoded the paper-stack layout DOM (`.paper`, `.paper-row`,\n`.paper-comments`, `.paper-header`, `.paper-footer`) — a private core\nprotocol leaking across the package boundary (AGENTS.md: \"Plugins\nhardcoding rendered DOM protocol selectors\" is a fail). A rename in the\npaginator would silent\n[…]\nts the old\nselectors did (asserted by the block-tools/review unit tests), so\nbehaviour is preserved by construction. CI covers the visual gate.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Typed paper-layout bridge; migrate plugins off .paper selectors (#237)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T13:03:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f699d2b875b52dda4e3cea0dc843c59b5ade49ba",
          "body": "AGENTS.md lists boundary violations that \"architecture checks should fail\non\", but the gate only warned on long files. The archunit fitness tests\ncover value-level dependencies but miss TYPE-ONLY imports — which is how\nthe `doc/mutations` → `editor/types` violation (fixed in the previous PR)\nwent un\n[…]\nolation and that the clean tree passes. Test files are exempt\nfrom the pure-zone rule (oracle snapshot tests legitimately import the\nrenderer).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Enforce ownership boundaries in check:architecture (#236)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T12:50:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b707519d782f5733c6f5921329712d52c7b47940",
          "body": "`ParagraphPropertiesPatch`, `SectionPropertiesPatch`, and `NamedStylePatch`\nwere defined in `editor/types.ts` but consumed by the pure `doc/mutations`\nengine, which had to reach up into `editor/types` for its own vocabulary —\nthe wrong ownership direction (AGENTS.md: pure zones must not import edito\n[…]\n behaviour change; the archunit fitness rule missed\nthis because it doesn't track type-only imports (Phase 2 will add a regex\ncheck that does).\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Move document patch types down into the document layer (#235)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T12:33:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b4e5b38d0d5347f36031fb02267a277d62280a39",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#234)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-08T05:46:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5c65a72e644d1dd56adf501e1a23ed997f03eae0",
          "body": "… (#233)\n\n* Right-align hyperlink-wrapped TOC entries at the leader tab stop\n\nA TOC field's result is one hyperlink wrapping the whole\n\"[number] \\t title \\t page number\". planRightTailTab only scanned\ntop-level text runs for the tail tab and bailed when it found the tab\ninside a hyperlink, so these \n[…]\n.8 <noreply@anthropic.com>\n\n* Expand changeset for the leader-tail redesign\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Word-faithful dot-leader TOC lines (right-aligned page-number column)…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-08T05:41:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e543b4653f0c0974868aee6b92e5af5d6a0e6571",
          "body": "Add canonical ownership guidance for shared behaviour in AGENTS.md.",
          "is_bot": false,
          "headline": "Document shared behaviour ownership",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-07T14:10:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dd431db11079af953f80005393bc842aed27c808",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#231)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-07T14:00:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6bfa5d598a2090e80d59d8913bfd6e02ea410cde",
          "body": "….29) (#230)\n\nThe paragraph-mark run properties (<w:pPr><w:rPr>) were being overlaid\nonto content runs, so a paragraph whose ¶ mark carried a different size\nthan its style cascade rendered its text at the MARK size. A one-line\nlegend with a 12pt mark over 10pt cascade content painted ~20% too wide\na\n[…]\nwith no logo\noverlap. Also bundles Lato (OFL) alongside Carlito so form-template\nmetrics match Word instead of a wide Helvetica/Arial fallback.\n\nCo-authored-by: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Paragraph-mark rPr styles only the ¶ glyph, not content runs (§17.3.1…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-07T13:54:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8c4d2d466f22348835cf2546827b5e7ee2caf98c",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#228)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-06T14:50:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "66f4e7f6cc49ddbc8501401323b1f7cc5372c3c7",
          "body": "…#227)\n\nControlled LO fixtures (font-size invariance, multi-line anchors, table adjacency) prove relativeFrom=paragraph resolves at the paragraph top; the baseline rule was a single-document fit. The recipe logo's genuine 0.155in displacement is tracked separately with the evidence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Revert paragraph-anchor baseline rule: fixtures prove paragraph-top (…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-06T14:47:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f6d78b85112a959c9ad8866f269260f422471acf",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#226)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-06T14:29:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8c7a2f9200185dd3730cb0d6795a27d44f24ac61",
          "body": "posV relativeFrom=paragraph resolves to the anchor line's BASELINE (LO/Word-verified: logo 7.435in == legend baseline 7.44in), measured via a zero-font-size inline probe — no font tables. The recipe logo sits below its legend line like Word instead of overlapping it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Paragraph-anchored frames hang from the anchor line's baseline (#225)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-06T14:25:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ff9e835a3aeed539eaf5ebaf9b5cc0e84dde7445",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#224)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-06T14:09:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "94ee70b2bb36d0f34af845995fb3043c6eb4fc64",
          "body": "Word/LO size lines from OS/2 usWin metrics; Lato's diverge sharply from hhea (1.439 vs 1.2). 10pt Lato rows now measure LO's 14.4pt, recovering ~0.4in of table height so the recipe card's anchored logo lands at Word's position. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Lato natural leading from usWin metrics (1.439), not hhea (#223)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-06T14:06:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e4999f290b42c5531b2e1b286afc522c76274ce4",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#222)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-06T08:12:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c160ef2f4944372731b7790c4a2633939e6f0ef9",
          "body": "…oup (#217)\n\nGrid-locked tables (tblW pct + tblLayout=fixed dxa) emit a colgroup of grid shares with table-layout:fixed, replacing per-cell width stamping (CSS fixed layout ignores non-first-row cell widths). Root cause of the earlier 27p/91p explosion: mergeConsecutiveFragments accumulated a colgro\n[…]\nlgroup, and per-page clones deep-clone theirs. Recipe columns even like Word; pentest overlap 0.827->0.875; fedramp 31p matches LO. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "tblLayout=fixed dxa tables follow the grid via a paginator-safe colgr…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-06T08:07:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "76b52682411684f628eed72087adec8e0fc6a4cf",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#221)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-06T08:05:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de69b1232400a88d02356065a9c416774debaeb0",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#219)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-06T07:30:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25d35add96ecac19c6471cd2fff7a2f97690f859",
          "body": "…#220)\n\nEvery block-flow container (body, header, footer, footnotes, inline-frame bodies, anchored textboxes) carries a shared sobree-flow class and all content-styling CSS scopes to it — zones and textboxes render with the body's full stylesheet instead of missing a dozen rules. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "One flow contract: sobree-flow class scopes all content-styling CSS (…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-06T07:28:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "54179cf98836c6b6e334200a3c3fd541e5b3e908",
          "body": "The .sobree-tab-spread flex rules were scoped to .paper-content only; zones fell back to inline flow (footer date wrapped, sentence ran into the logo). Rescoped to :is(.paper-content, .paper-header, .paper-footer) — zone tab lines lay out like the body's. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Tab-spread layout applies in header/footer zones (#218)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-06T06:48:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a61df17eb5935a9b2c42bbea611817837fa8084",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#216)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-05T21:12:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8bf75ac2ca2468cf662c36b7cbd30bc0dafc8af6",
          "body": "…scoping (#215)\n\nw:sym glyphs import with a Unicode map; whitespace passes through verbatim (the 4+-space collapse was an obsolete fallback-font compensation); tab stops accumulate per §17.3.1.38 and multi-tab lines walk one stop per tab (footer spread lines); the anchored-frame paragraph lookup skips container-local block indices. Grid-locked dxa column layout deferred with documented repro (pentest 27p / nih 91p). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Recipe-card fidelity: sym glyphs, verbatim spaces, tab walks, anchor …",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-05T21:02:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c8a1f5a3249b8f134c69f8b10fdcc90ffd075c1c",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#212)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-05T15:50:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e399a1bb7ce77718e0e243ea53ac794ba5fb6f4e",
          "body": "…d (#214)\n\nShape-only inline frames size to their wp:extent instead of stretching to the host column (photo placeholder keeps its 0.6x0.7in portrait aspect); tblW pct tables pin table-layout:fixed with per-cell tblGrid shares so columns follow Word's grid; dxa tables keep auto layout until the tcW preference layer lands. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Decoration inline frames keep their extent; pct tables follow the gri…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-05T15:41:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a3758cc376603ee2f32c6ec6f650487e28d78c36",
          "body": "tblW type=pct imports as widthPct; the renderer emits CSS percent width with explicit symmetric negative margins for centred over-wide tables — a 103.3% banner reaches past the margins to meet the page-frame decoration like Word. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Tables honour tblW percent widths (banner reaches the page frame) (#213)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-05T15:03:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "857fa36b0b8f5bfbb8d1e3b88a5edf9aa01df109",
          "body": "…(#211)\n\nInfeasible keepNext chains degrade pairwise like Word: the one block whose keepNext pair broke moves to the next page (no cascade, never emptying the page) instead of packing to raw overflow mid-pair. Healthcare p2 boundary within one list item of Word's; zero corpus regressions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Pull back the trailing keep-pair block in the all-forbidden fallback …",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-05T08:56:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "02e8e2bca40d5ae26e9c400c7b1d8febfc024fb3",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#205)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-04T22:35:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e74f5b05172964d3f34af3fc3f5f88c1c2fd6a32",
          "body": "…210)\n\npaintTextbox applies the container shape's prstGeom (ellipse/roundedRect) like paintShape — a decorative frame authored as an empty text box keeps its rounded corners on every page. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Anchored text boxes honour their preset geometry (rounded corners) (#…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-04T21:24:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "28cca43b96b3df0945e29ae434686e52c0072278",
          "body": "Anchored frames size from wp14:sizeRelH/V percentages of the page/margin box instead of the stale wp:extent snapshot — the CV page-frame ring renders at Word's thickness (insets 0.46/0.61in, was 0.725/0.86). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Honour wp14 percent sizing on anchored frames (#209)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-04T11:30:29Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2e995c0db12298140cb092fa4622782776acc5a5",
          "body": "naturalLeadingFor returns each font's real hhea ratio (Calibri/Carlito 1.2217, Cambria/Caladea 1.1885) instead of the flat serif 1.15 — Calibri documents rendered ~6% denser than Word, packing 7 extra lines onto a CV page. Verified against LO PDF metrics; zero corpus page-count regressions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Use per-font hhea metrics for lineRule=auto natural leading (#208)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-04T09:28:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fd7549687ed4408bb2ee29d94ac6b2207eb3c866",
          "body": "…207)\n\nTheme blipFill textures decode once at import; duotone fills blend their endpoints (keyed dark->light by lightness) at the image's mean linear luminance — the page-frame ring renders 231 vs LO's measured 224 instead of the midpoint's heavy 217. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Blend duotone theme fills at the texture's measured mean luminance (#…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-04T08:34:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fff882f3afded0d72d0e7e9530434bf2ac66dd86",
          "body": "DrawingML colours track <a:alpha> and emit rgba() for sub-1 opacity — an 83%-white rect over a grey texture ring renders as the layered page design's lighter inner frame instead of flattening to opaque white. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Honour the <a:alpha> colour transform (semi-transparent fills) (#206)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-04T07:08:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "db1af478712d4ffc6a5ad455111e31b2ff4a1700",
          "body": "readCellBorders keeps w:val=nil/none sides as {style:none} so a cell's explicit no-border declaration wins its edge instead of falling through to the table grid — banner tables render clean like Word. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Explicit nil cell borders suppress the table grid (#204)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T20:16:03Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9a7acd1e008696052a0a1229a97a1ac8235cda5c",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#199)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-03T18:50:16Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a0b78f83b70c7d4b3bee91e6c393e7c9350d0cec",
          "body": "Table rows honour <w:trHeight> (atLeast/exact per §17.4.81) — banner tables get their designed tall rows. Shape fillRefs resolve through the theme's real fill-style lists (solids via phClr substitution, gradients as CSS gradients, duotone textures as their colour midpoint) — a CV template's rounded \n[…]\n flattening to white. The tall-row splitter only splits content-tall rows so minimum-tall newsletter scaffold rows stay monolithic. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Import trHeight row minimums; resolve theme fill-style lists (#203)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T18:46:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f27ae72408ad23e8a3e878059d97da6d2db4d92b",
          "body": "… (#202)\n\nHeader/footer zone selection is exact-type with per-type inheritance (titlePg blanks a missing first footer; first-only headers stay off later pages; defaults inherit per type across sections). Anchored frames import and resolve all three OOXML positioning forms (EMU posOffset, wp:align, w\n[…]\ne CV zones now match Word: blank page-1 footer, live 'Page N' bar at the bottom margin, outline-only frames instead of white boxes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Zone anchor fidelity: positions, titlePg selection, noFill, live PAGE…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T18:08:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f3b4b831a27098d19c95abaeaac9bf899bbd3d94",
          "body": "A bare inline wps shape (photo-placeholder rectangle: theme solid fill + a:ln outline) imports with fill and border resolved, but the renderer applied only the fill. Apply shape.border the same way the anchored-shape and textbox painters do. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Paint inline shape borders in the inline-frame renderer (#201)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T18:07:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "42e05feecb0ed6d6e077140d9e2ccf76535ab409",
          "body": "…ext (#200)\n\nA <w:br/> is run content interleaved with <w:t>, not a run type. readRun early-returned on the first break and discarded everything after it — a CV lost 'First-class ' from its education section, a hospital letterhead lost its department line, an IEEE template lost mid-sentence text. Ne\n[…]\naring the run's rPr; all three paragraph walkers flatMap it. childrens-hospital letterhead reaches perfect 1.0 corpus text overlap. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Read runs as segment sequences; <w:br/> no longer swallows trailing t…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T14:32:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "46d0bcdf309931e9b81800bffabc03b61cd7748f",
          "body": "Keep-with-next chains longer than a page degrade to natural page breaks (pickAndEmit excludes +Infinity candidates; force-break at overflow when none finite); backOffIfViolates never retreats into a forbidden keep break; a forced-break penalty at the top of a fresh page is consumed as already-satisf\n[…]\n CV 9p -> 3p; gatech thesis blank page gone, overlap 0.353 -> 0.688. All 45 corpus pages baselines re-blessed at the healthy state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Infeasible keep chains break naturally; forced breaks coalesce (#198)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T14:15:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9f37e1f6654a6738756d4bf5c28ced4fcdb08e5d",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#197)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-03T13:26:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d15b17c63e6a33ef63942a248a365773f2458682",
          "body": "The row-density root cause: a TABLE style's own <w:pPr>/<w:rPr> apply\nto every paragraph inside the table, layered between DocDefaults and\nthe paragraph's style. Word's built-in TableGrid declares\n<w:spacing w:after=\"0\" w:line=\"240\"/> exactly this way — LibreOffice's\nmeasured in-table pitch is singl\n[…]\nm the IndexedDB projection renders 9 pages\nwith identical 1.15 cell line-heights. Cascade + renderer tests pin\nthe layer ordering.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Apply table styles' pPr/rPr to cell paragraphs (ECMA-376 §17.7.2) (#196)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T13:21:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "053b7c29450298b189d8986e0cac937026ae0216",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#195)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-03T09:36:44Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "07e477d23b1d259642fce6fedb386b55133f072a",
          "body": "Two coupled paginator fixes from the trailing-blank-page\ninvestigation:\n\n1. pageHeightAt: a page index BEYOND the measured pageHeights array now\n   extends the LAST measured page's budget instead of falling back to\n   the nominal global. The per-page heights carry the papers' real zone\n   reservatio\n[…]\n-blessed with this note.\nEngine tests updated to the new pageHeightAt contract; trailing-\ncollapse test inverted. Full gate green.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Honest tail-page budgets; keep genuine trailing blank pages (#194)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T09:32:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8cf373dcf97df620b8e74142ef20881d5456b9c9",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#191)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-03T07:29:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "388cc6a1648f00e9cb57fb6749b7d70b70df75ef",
          "body": "The frame wrapper takes the host paragraph's resolved properties (for\nits spacing box), but `tab-size` is CSS-inherited: the host's\n`<w:tabs>`-derived value shadowed the editor-scope default grid\n(`applyDefaultTabStop`) for every paragraph INSIDE the box. Word\nresolves a textbox's inner paragraphs a\n[…]\nhe playground (socials paragraph = 1 visual line). Full\ngate green: 1292 core tests, corpus:check + corpus:pages within\ntolerance.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Clear the host paragraph's tab-size from inline frame wrappers (#193)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T07:25:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1fe74c0505b4b9c6274529324dccc66bc313b096",
          "body": "…192)\n\nTwo fidelity gaps on ljmu-university-letterhead-a4's footer vs Word:\n\n1. Alignment. `.paper-footer { text-align: center }` — a presentation\n   default for the legacy string-template footers — leaked into rich\n   zone paragraphs, centring the address block Word renders left. The\n   zones alrea\n[…]\nt\n(inline_frame persists as whole-block JSON). Full gate green: 1292\ncore tests, corpus:check + corpus:pages all within tolerance.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Footer zones: paragraph-owned alignment + spAutoFit content sizing (#…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T07:15:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "463efef592b4e86649c4817ca8ade498eafbb311",
          "body": "…(#190)\n\nljmu-university-letterhead-a4 rendered a blank page vs Word's\nlogo + address footer. Two root causes:\n\n1. The footer is ONE lone inline text box (`<wp:inline>` + `wps:txbx`\n   holding the department-address paragraphs). parseInlineFrames'\n   `< 2 per paragraph` guard deferred lone bare text\n[…]\ness block, matching Word. Gate green: 1289 core tests, corpus:check\nand corpus:pages all within tolerance, typecheck, biome, docs.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Import inline text boxes everywhere and honour a:srcRect image crops …",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-03T06:09:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0ce122990b91ddf036ec3fb53760b9459b6fa1f8",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#187)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-02T23:09:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d7ec7408ff37bdb812501e63237ad86e7505c31c",
          "body": "…183) (#189)\n\nThe session PRs shipped without changesets; the code is in 0.1.50\neither way — these restore the user-facing changelog prose.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add changelog entries for the pagination/TOC/fields work (#180 #182 #…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T23:05:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7076643b8c3602255c4d36b3cea566087f0cd7c3",
          "body": "…t (#183)\n\n* Read complex fields child-by-child — fldChar/instrText are run content\n\nECMA-376 §17.16.18 makes fldChar / instrText run CONTENT — siblings of\n<w:t> inside one <w:r> — so a producer may pack an entire field\n(begin + instrText + separate + end) into a single run, as the\nfooter/08-footer-\n[…]\nepend on; `paragraphs.ts` re-exports it for\nexisting consumers.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Read complex fields child-by-child — fldChar/instrText are run conten…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T22:57:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "67c40de2c1578f22d0624342c0ae341f32ad926b",
          "body": "pnpm corpus:check compares AST-level import snapshots against the\nLibreOffice reference and never exercises the live paginator — page-\ncount and break-position regressions were invisible to it.\n\nThe new gate renders every corpus fixture in headless Chromium through\nthe playground (window.__corpusPag\n[…]\nible\nfonts). Baselines for the committed generated corpus are included; the\ngitignored real-world corpus gets local-only baselines the same way.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add live-paginator corpus gate (pnpm corpus:pages) (#181)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T22:49:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "49f44eb339d432d0683fa778033f0df50a1abb89",
          "body": "The corpus:pages gate (first run on the merged pagination stack) caught\nnih-icsc-annual-report at 11 pages vs LibreOffice's 9. Bisected to the\nsub-twip twipsToMm change interacting with the cell after-spacing\ntightener: the old code string-matched the rendered \"4mm\" (which the\ninteger-rounded 200-tw\n[…]\noff-by-one tail page (LO p6 holds 3\nlines Sobree packs onto p5). Import-level corpus:check: all within\ntolerance. Full gate green.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Cell trailing space-after: semantic rule, not value matching (#188)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T22:36:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d2f5da73593a1428f50d2552a61830f8398ab67e",
          "body": "…` (#184)\n\n* Single spacing renders at the font's natural leading, not CSS normal\n\nlineRule=\"auto\" line=240 was the one auto multiplier still delegated\nto the browser's line-height: normal, which resolves from per-engine\nrounded font metrics: Times New Roman 12pt measured 18px, 18.398px and\n18.5px a\n[…]\nhatever the combined code renders — regenerated with vitest -u.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Single spacing renders at the font's natural leading, not CSS `normal…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T19:18:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "776c5aa2d00e2265d64bcc8f81cd8e60dc623717",
          "body": "#182's flex spread consumed the tab / space-run separator from the DOM,\ncorrupting the paragraph's TEXT while fixing its geometry: copy/paste\nyielded \"labelvalue\", the DOM→AST serializer lost the tab, and the\ncorpus text-matcher unmatched every spread line (pentest-engineer fell\n72/75 → 63/75 on mai\n[…]\nxt (google-modern).\n\ncorpus:check: all 45 entries within tolerance — wsu 177/177 and\npentest 72/75 both restored. Full gate green.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Tab spreads keep separator characters in the document text (#186)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T18:51:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c8c478e097e566c31d2bda80d6e2b709b152fe66",
          "body": "#180 made twipsToMm sub-twip exact while #182's tabLayout tests were\nwritten against the old integer-mm rounding — the two were green on\ntheir own branches and collided on main (165mm vs the exact 165.1mm,\n13mm vs the exact 12.7mm = 720tw). The production values are the\ncorrect ones; only the expectations move.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Align tabLayout test expectations with sub-twip mm conversion (#185)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T18:12:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1d150276131e61b5002504b14972c3b095c4041a",
          "body": "CSS has no tab-stop model, so a trailing right-aligned stop\n(w:tabs val=\"right\", the TOC / list-of-figures line shape) was\napproximated as a LEFT stop via tab-size — the single tab consumed the\nfull line width, wrapped the page number, and doubled every TOC entry's\nheight (one extra page on a 27-pag\n[…]\naders and the TOC page split now\nmatches LibreOffice exactly. Full gate green (typecheck, check, test,\ndocs build, corpus:check, docs:coverage).\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Right-aligned tab stops: TOC-style \"entry … page number\" layout (#182)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T17:53:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "746e17138ff0cdda9f4a1db90c852a471b6c7cc7",
          "body": "Three distortions stacked up to push tightly-packed pages (a title\npage of ~45 single-spaced lines after a hard page break) one block\npast the budget, spawning an extra page vs Word/LibreOffice:\n\n1. Forced-break glue misattribution (buildItems): the whole CSS-\n   collapsed inter-block gap was charge\n[…]\number to a second line). All other real-world fixtures' page counts\nunchanged; full gate green including corpus:check within baseline\ntolerance.\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix page-fill overcharges that spilled thesis title pages (#180)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T17:50:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "09284745bdfd692fd300c8a89bef4c042ce036b0",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#179)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-02T09:34:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2837a1167224c78cea9af8ce0d3b62ea4efee96d",
          "body": "…count (#178)\n\n* Match Word's page-fill budget (space-before at page top + box double-count)\n\nTwo coupled fixes that close the systemic page-underfill vs Word:\n\n1. Space-before suppression at the top of a page. Word ignores a\n   paragraph's space-before when it lands at the top of a page via an\n   A\n[…]\npic.com>\n\n* ci: re-trigger scan after PR retarget\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Match Word's page-fill budget: page-top space-before + margin double-…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T09:30:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0772e5ea166807b229bd67d831c9faf91bd473b5",
          "body": "Word's heading styles declare <w:keepNext/> + <w:keepLines/> (ACM's\nHead2 inherits both from built-in Heading2 via basedOn), but the style\nimporter never read them, so the paginator stranded headings at the\nbottom of a page — acm-submission-template page 2 ended with the\n\"1.2 More about the submissi\n[…]\n\nparagraph to page 3. Full gate green; corpus within tolerance; oracle\nsnapshots re-recorded (diffs are pure flag/attr additions).\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Honour keepNext/keepLines from styles and direct formatting (#177)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-02T09:05:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7844eaac9575008083a4f4956aa2d6b037ef9cae",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#176)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-01T22:47:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "23f300d1db6013d1a2e31e9fcb34948e0524d494",
          "body": "…165)\n\nWord omits a paragraph's before/after spacing when the adjacent paragraph\nshares its style (ECMA-376 §17.3.1.9) — the double-spaced thesis body and\ntight bulleted list cases. Sobree ignored the flag, so every such paragraph\nkept its cascaded `after` (the docDefaults' 160 twips ≈ 3 mm rounded)\n[…]\n); docs without the flag are unchanged (ACM 13 = 13,\nNIST SSP 19). Oracle snapshots refreshed; full corpus stays within tolerance.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Honour w:contextualSpacing — tighten runs of same-style paragraphs (#…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-01T22:22:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "872b050141df63b73bd3f2bd8c37511a047cd73d",
          "body": "… (#156)\n\nThe rendering-fidelity oracle computed each block's effective leading as\nthe median Δy between its matched PDF lines. In a multi-column section\nthat line set is polluted: the matcher gathers lines in LibreOffice's\nreading order, which interleaves the OTHER column's lines (and a truncated\nb\n[…]\n: undp-evaluation-report 0.223). New drift.test.ts covers the callout,\npage-jump, all-cross-column, and clean-single-column cases.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fixtures: measure line-height drift over column-consistent lines only…",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-01T22:19:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0fcdb8cde7d311c289042bdb30b4450ab26c3729",
          "body": null,
          "is_bot": false,
          "headline": "Add architecture fitness tests (#175)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-01T22:11:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "46665e184059828683d8f024d1c94426b6225b11",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#174)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-01T15:07:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "69992a93a02f52efd3b8b63e148ea421b5c7ea63",
          "body": "* Unify the two <w:rPr> readers into one\n\n`<w:rPr>` is ONE OOXML concept with two homes — inside a `<w:r>` (direct\nrun formatting) and inside a `<w:style>` (a style's run defaults). The\nimporter parsed each with its own function (`readRunFormat` →\n`RunFormat` → `mapRunFormat`, vs a second `readRunPr\n[…]\n changeset for the rPr-reader unification release\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Unify the two <w:rPr> readers into one (#173)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-01T15:03:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "da4b3adf2233b1341f1338c14ec7cdc8d853059f",
          "body": "A paragraph/character style can turn OFF a toggle it inherits from its basedOn\nchain: ACM's `ACMRef` (the reference-format citation) carries `<w:b w:val=\"0\"/>`\nto switch off the bold it inherits from `Titledocument`, so the citation renders\nupright while the bold \"ACM Reference Format:\" heading (`AC\n[…]\nr styles. Verified: acm reference body upright, heading + keywords\nlabels bold, author names title-case; fedramp/others unchanged.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Honour an explicit toggle-off in a run style (w:b w:val=\"0\") (#172)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-01T14:57:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4b4bef936968900dda1ddb6297f2b51c0822029c",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#171)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-01T12:55:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b305cf55914378ee2050ee9a7a4559b10020b85f",
          "body": "OOXML toggle properties (caps/bold/italic/strike) combine by XOR across the\nstyle hierarchy. Sobree applied them as inheritable CSS at both the block and\neach run, and CSS only ORs — so a caps paragraph style plus a caps character\nstyle doubled into ALL-CAPS instead of cancelling (ACM author names).\n[…]\ne block no longer emits inheritable toggle CSS. Verified across docs;\nunit tests cover the resolution + import + Y.Doc round-trip.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Resolve toggle run properties by XOR across the style cascade (#170)",
          "author_name": "Balázs Korossy",
          "author_login": "khayll",
          "committed_at": "2026-07-01T12:51:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6f73e9f24481e46e6c9f17aa18aa3ec037d8819d",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#169)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-01T04:34:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a17d8f6376c958f3ce0520c3fae50e5e90701f71",
          "body": "Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>",
          "is_bot": true,
          "headline": "Version Packages (#168)",
          "author_name": "github-actions[bot]",
          "author_login": "github-actions[bot]",
          "committed_at": "2026-07-01T04:26:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 100,
      "commits_last_year": 298,
      "latest_release_at": "2026-07-18T07:15:10Z",
      "latest_release_tag": "@sobree/zoom-controls@0.1.71",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 8,
      "days_since_latest_release": 5,
      "mean_days_between_releases": 0.2
    },
    "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": "@sobree/mcp",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "sobree",
            "mcp",
            "model-context-protocol",
            "llm",
            "claude",
            "anthropic",
            "yjs",
            "wysiwyg",
            "editor"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@sobree/mcp",
          "is_deprecated": false,
          "latest_version": "0.1.71",
          "repository_url": "https://github.com/khayll/sobree",
          "versions_count": 69,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 7176,
          "first_published_at": "2026-06-02T13:08:41.028000Z",
          "latest_published_at": "2026-07-18T07:14:49.508000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@sobree/core",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "wysiwyg",
            "editor",
            "rich-text",
            "docx",
            "ooxml",
            "framework-free",
            "embeddable",
            "contenteditable",
            "pagination",
            "sobree"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@sobree/core",
          "is_deprecated": false,
          "latest_version": "0.1.71",
          "repository_url": "https://github.com/khayll/sobree",
          "versions_count": 69,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 8708,
          "first_published_at": "2026-06-02T13:08:32.163000Z",
          "latest_published_at": "2026-07-18T07:14:50.044000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@sobree/review",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "sobree",
            "wysiwyg",
            "editor",
            "track-changes",
            "comments",
            "review"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@sobree/review",
          "is_deprecated": false,
          "latest_version": "0.1.71",
          "repository_url": "https://github.com/khayll/sobree",
          "versions_count": 69,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 6938,
          "first_published_at": "2026-06-02T13:08:43.233000Z",
          "latest_published_at": "2026-07-18T07:14:49.588000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@sobree/keyboard",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "sobree",
            "wysiwyg",
            "editor",
            "keyboard",
            "shortcuts",
            "hotkeys"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@sobree/keyboard",
          "is_deprecated": false,
          "latest_version": "0.1.71",
          "repository_url": "https://github.com/khayll/sobree",
          "versions_count": 69,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 7071,
          "first_published_at": "2026-06-02T13:08:39.028000Z",
          "latest_published_at": "2026-07-18T07:14:49.638000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@sobree/block-tools",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "sobree",
            "wysiwyg",
            "editor",
            "toolbar",
            "ui",
            "floating",
            "block"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@sobree/block-tools",
          "is_deprecated": false,
          "latest_version": "0.1.71",
          "repository_url": "https://github.com/khayll/sobree",
          "versions_count": 69,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 6906,
          "first_published_at": "2026-06-02T13:08:34.762000Z",
          "latest_published_at": "2026-07-18T07:14:49.669000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@sobree/collab-server",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "sobree",
            "yjs",
            "collaboration",
            "crdt",
            "y-websocket",
            "relay",
            "websocket",
            "node"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@sobree/collab-server",
          "is_deprecated": false,
          "latest_version": "0.1.13",
          "repository_url": "https://github.com/khayll/sobree",
          "versions_count": 14,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 124,
          "first_published_at": "2026-06-02T13:08:04.948000Z",
          "latest_published_at": "2026-06-16T14:56:07.700000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 36
        },
        {
          "name": "@sobree/zoom-controls",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "sobree",
            "wysiwyg",
            "editor",
            "zoom",
            "viewport",
            "ui",
            "floating"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@sobree/zoom-controls",
          "is_deprecated": false,
          "latest_version": "0.1.71",
          "repository_url": "https://github.com/khayll/sobree",
          "versions_count": 69,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 7021,
          "first_published_at": "2026-06-02T13:08:45.203000Z",
          "latest_published_at": "2026-07-18T07:14:49.441000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@sobree/collab-providers",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "sobree",
            "wysiwyg",
            "editor",
            "yjs",
            "collaboration",
            "crdt",
            "y-websocket",
            "y-indexeddb",
            "y-webrtc"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@sobree/collab-providers",
          "is_deprecated": false,
          "latest_version": "0.1.71",
          "repository_url": "https://github.com/khayll/sobree",
          "versions_count": 69,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 6644,
          "first_published_at": "2026-06-02T13:08:37.073000Z",
          "latest_published_at": "2026-07-18T07:14:49.567000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 1,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": null,
      "open_issues_and_prs": 3
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": true,
      "has_dockerfile": false,
      "has_mcp_signal": true,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "apps/docs/tsconfig.json",
        "apps/playground/tsconfig.json",
        "packages/block-tools/tsconfig.json",
        "packages/collab-providers/tsconfig.json",
        "packages/collab-server/tsconfig.json",
        "packages/core/tsconfig.json",
        "packages/keyboard/tsconfig.json",
        "packages/mcp/tsconfig.json",
        "packages/review/tsconfig.json",
        "packages/zoom-controls/tsconfig.json",
        "tools/fixtures-gen/tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 54709,
      "source_files_sampled": 485,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "AGENTS.md"
      ],
      "agent_instruction_max_bytes": 22997
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [
          {
            "name": "@hono/node-server",
            "direct": false,
            "version": "1.19.14",
            "severity": "moderate",
            "ecosystem": "npm",
            "cvss_score": 5.9,
            "advisory_ids": [
              "GHSA-frvp-7c67-39w9"
            ],
            "fixed_version": "2.0.5",
            "advisory_count": 1,
            "oldest_advisory_days": 1
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "moderate": 1
        },
        "advisory_count": 1,
        "affected_count": 1,
        "assessed_count": 100,
        "malicious_count": 0,
        "assessed_package": "npm:@sobree/mcp@0.1.71",
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@sobree/block-tools",
          "manifest": "apps/playground/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@sobree/collab-providers",
          "manifest": "apps/playground/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@sobree/core",
          "manifest": "apps/playground/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@sobree/keyboard",
          "manifest": "apps/playground/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@sobree/review",
          "manifest": "apps/playground/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@sobree/zoom-controls",
          "manifest": "apps/playground/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "y-indexeddb",
          "manifest": "apps/playground/package.json",
          "ecosystem": "npm",
          "version_constraint": "^9.0.12"
        },
        {
          "name": "yjs",
          "manifest": "apps/playground/package.json",
          "ecosystem": "npm",
          "version_constraint": "^13.6.30"
        },
        {
          "name": "lib0",
          "manifest": "packages/collab-server/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.2.99"
        },
        {
          "name": "ws",
          "manifest": "packages/collab-server/package.json",
          "ecosystem": "npm",
          "version_constraint": "^8.18.0"
        },
        {
          "name": "y-protocols",
          "manifest": "packages/collab-server/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.0.7"
        },
        {
          "name": "fflate",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.8.2"
        },
        {
          "name": "yjs",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^13.6.30"
        },
        {
          "name": "@modelcontextprotocol/sdk",
          "manifest": "packages/mcp/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.29.0"
        },
        {
          "name": "@sobree/core",
          "manifest": "packages/mcp/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@napi-rs/canvas",
          "manifest": "tools/fixtures-gen/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.1.100"
        },
        {
          "name": "docx",
          "manifest": "tools/fixtures-gen/package.json",
          "ecosystem": "npm",
          "version_constraint": "^9.0.3"
        },
        {
          "name": "pdfjs-dist",
          "manifest": "tools/fixtures-gen/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.10.38"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 3,
        "merged_prs": 263,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 6
      },
      "bus_factor": 1,
      "bot_contributors": 1,
      "top_contributors": [
        {
          "type": "User",
          "login": "khayll",
          "commits": 231,
          "avatar_url": "https://avatars.githubusercontent.com/u/13990683?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "ik.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [
        "biome.json"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "pnpm-lock.yaml"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 3,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 8,
            "reason": "24 out of 30 merged PRs checked by a CI test -- score normalized to 8",
            "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/24 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 9,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "42 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "b944ee5398e7f80a9cdc3128717a8eb4d20467d0",
        "ran_at": "2026-07-23T14:48:11Z",
        "aggregate_score": 4.2,
        "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-23T02:56:39Z",
      "oldest_open_prs": [
        {
          "number": 266,
          "created_at": "2026-07-18T07:11:44Z",
          "last_comment_at": "2026-07-18T07:13:39Z",
          "last_comment_author": "cloudflare-workers-and-pages"
        },
        {
          "number": 267,
          "created_at": "2026-07-18T09:24:40Z",
          "last_comment_at": "2026-07-18T09:25:15Z",
          "last_comment_author": "github-actions"
        },
        {
          "number": 272,
          "created_at": "2026-07-23T03:45:06Z",
          "last_comment_at": "2026-07-23T03:46:35Z",
          "last_comment_author": "cloudflare-workers-and-pages"
        }
      ],
      "last_merged_pr_at": "2026-07-23T02:53:37Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/khayll/sobree",
    "host": "github.com",
    "name": "sobree",
    "owner": "khayll"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 58,
      "inputs": {
        "security": 51,
        "vitality": 82,
        "community": 37,
        "governance": 52,
        "engineering": 64
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 82,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "commits_last_year": 298,
              "human_commit_share": 0.72,
              "days_since_last_push": 0,
              "active_weeks_last_year": 8
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "8/52 weeks with commits",
                "points": 5.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 8
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "298 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 298
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 100,
              "latest_release_tag": "@sobree/zoom-controls@0.1.71",
              "releases_from_tags": false,
              "days_since_latest_release": 5,
              "mean_days_between_releases": 0.2
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "100 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 100
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~0.2 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 0.2
                    }
                  }
                ],
                "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": 37,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 1,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "1 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "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": "good",
            "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": 78,
            "inputs": {
              "packages": [
                "@sobree/mcp",
                "@sobree/core",
                "@sobree/review",
                "@sobree/keyboard",
                "@sobree/block-tools",
                "@sobree/collab-server",
                "@sobree/zoom-controls",
                "@sobree/collab-providers"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 50588
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "50,588 downloads/month across npm",
                "points": 62.7,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 50588,
                      "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": 52,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 70,
            "inputs": {
              "merged_prs": 263,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 6
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "263/269 decided PRs merged",
                "points": 37.4,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 263,
                      "decided": 269
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/24 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "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": 47,
            "inputs": {
              "followers": 9,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "khayll",
              "public_repos": 12,
              "account_age_days": 3983
            },
            "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": "9 followers of khayll",
                "points": 7.2,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 9,
                      "login": "khayll"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "12 public repos, account ~10 yr old",
                "points": 20.1,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 12
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 10
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@sobree/mcp",
                "@sobree/core",
                "@sobree/review",
                "@sobree/keyboard",
                "@sobree/block-tools",
                "@sobree/collab-server",
                "@sobree/zoom-controls",
                "@sobree/collab-providers"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 5
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "8 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 8,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 5 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "69 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 69
                    }
                  }
                ],
                "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": 64,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "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": "biome.json",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "biome.json"
                    }
                  }
                ],
                "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": "24 out of 30 merged PRs checked by a CI test -- score normalized to 8",
                "points": 16,
                "status": "partial",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "at_risk",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": false,
              "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 51,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Packaging, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "packaging",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 42,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 4.2
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection is not maximal on development and all release branches",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "24 out of 30 merged PRs checked by a CI test -- score normalized to 8",
                "points": 2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/24 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 6.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "42 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Matched the npm:@sobree/mcp@0.1.71 runtime dependency closure — what installing the published package pulls in — 100 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:@sobree/mcp@0.1.71",
                  "assessed": 100
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 88,
            "inputs": {
              "source": "osv",
              "advisories": 1,
              "affected_packages": 1,
              "assessed_packages": 100,
              "unassessed_packages": 0,
              "affected_by_severity": "moderate 1",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "1 affected: @hono/node-server 1.19.14 (moderate 5.9)",
                "points": 13.2,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "@hono/node-server 1.19.14 (moderate 5.9)"
                    }
                  }
                ],
                "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": 100,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 74,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "has_llms_txt": true,
              "legible_history_share": 0.986,
              "agent_instruction_files": [
                "AGENTS.md"
              ],
              "agent_instruction_max_bytes": 22997
            },
            "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": "llms.txt present",
                "points": 15,
                "status": "met",
                "details": [
                  {
                    "code": "llms_txt_present",
                    "params": {}
                  }
                ],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "71 of 72 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 71,
                      "sampled": 72
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 64,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "pnpm-lock.yaml"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "apps/docs/tsconfig.json",
                "apps/playground/tsconfig.json",
                "packages/block-tools/tsconfig.json",
                "packages/collab-providers/tsconfig.json",
                "packages/collab-server/tsconfig.json",
                "packages/core/tsconfig.json",
                "packages/keyboard/tsconfig.json",
                "packages/mcp/tsconfig.json",
                "packages/review/tsconfig.json",
                "packages/zoom-controls/tsconfig.json",
                "tools/fixtures-gen/tsconfig.json"
              ],
              "agent_commit_share": 0.36,
              "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": "biome.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "biome.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "apps/docs/tsconfig.json, apps/playground/tsconfig.json, packages/block-tools/tsconfig.json, packages/collab-providers/tsconfig.json, packages/collab-server/tsconfig.json, packages/core/tsconfig.json, packages/keyboard/tsconfig.json, packages/mcp/tsconfig.json, packages/review/tsconfig.json, packages/zoom-controls/tsconfig.json, tools/fixtures-gen/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "apps/docs/tsconfig.json, apps/playground/tsconfig.json, packages/block-tools/tsconfig.json, packages/collab-providers/tsconfig.json, packages/collab-server/tsconfig.json, packages/core/tsconfig.json, packages/keyboard/tsconfig.json, packages/mcp/tsconfig.json, packages/review/tsconfig.json, packages/zoom-controls/tsconfig.json, tools/fixtures-gen/tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "36 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 36,
                      "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": 54709,
              "source_files_sampled": 485,
              "oversized_source_files": 0
            },
            "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": "0/485 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 485,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "critical",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "example_dirs": [],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-23T14:48:30.824240Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/k/khayll/sobree.svg",
  "full_name": "khayll/sobree",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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