公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-27 17:31 UTC

groscy / data-loom

Local dashboard for spec-driven development: a phased OpenSpec roadmap (WHAT) and an MCP topology (HOW).

TypeScript · JavaScript · CSSMIT★ 0 星标⑂ 0 复刻始于 2026年6月在 GitHub 上查看 ↗

groscy/data-loom 的健康指数为 100 分中的 56 分,处于「中等」区间。 其得分最高的类别是Engineering Quality(76/100),最低的是Sustainability & Governance(33/100)。 最近一次更新在 2 天前。 近期的大部分工作由 1 位贡献者完成。

56
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

2 关注者15 个公开仓库始于 2021年10月

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布标签
npm@lyric_dev/data-loom0.13.03,047176 天前openspecmcpdashboardroadmapspec-driven-developmentclaude-code

按类别列示的指标

活力

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

69中等 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 2 天前
3.5/36提交节奏 — 52 周中有 5 周有提交
17.1/18提交量 — 最近一年 80 次提交
0/10OpenSSF Scorecard:Maintained — project was created within the last 90 days. Please review its contents carefully
所用输入
commits_last_year80
human_commit_share1
days_since_last_push2
active_weeks_last_year5

发布纪律

88优秀
评分方式
16.2/27有发布版本 — 24 个版本标签(无 GitHub 发布版本)
36/36发布时效 — 最近一次发布版本于 6 天前
27/27发布节奏 — 约每 1.6 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count24
latest_release_tagv0.13.0
releases_from_tags
days_since_latest_release6
mean_days_between_releases1.6
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

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

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

社区健康

77良好
评分方式
22.5/22.5README
22.5/22.5许可证 — 可识别的许可证(MIT)
18/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
6.3/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template
评分方式
46.5/80月度下载量 — npm 合计每月 3,047 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packages@lyric_dev/data-loom
dependents
ecosystemsnpm
total_downloads
monthly_downloads3,047
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

33存在风险 · 占总体的 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议题解决 — 没有议题或无数据
0/38.3PR 接受 — 已裁定的 PR 中 0/2 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs2
已排除计分(无数据或不适用):议题解决。 其余权重已重新归一化。
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
3.4/25所有者影响力 — groscy 有 2 位关注者
18.4/25既往记录 — 15 个公开仓库,账户约 4 年
所用输入
followers2
owner_typeUser
is_verified
owner_logingroscy
public_repos15
account_age_days1,751
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — npm 上有 1 个软件包
35/35发布时效 — 最近一次发布于 6 天前
20/20版本历史 — 17 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packages@lyric_dev/data-loom
ecosystemsnpm
any_deprecated
min_days_since_publish6

工程质量

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

76良好 · 占总体的 20%

工程实践

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

文档

100优秀
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://github.com/groscy/data-loom#readme
10/10仓库描述
10/10主题标签 — 6 个主题标签
10/10Wiki
所用输入
topicsclaude-code, dashboard, mcp, openspec, roadmap, spec-driven-development
has_wiki
homepagehttps://github.com/groscy/data-loom#readme
has_readme
has_docs_dir
has_description

安全

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

61中等 · 占总体的 16%

安全态势

54中等
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 无数据
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
7.5/7.5Dependency-Update-Tool — update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
5/5Packaging — packaging workflow detected
1.5/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 3
0/5SAST — no SAST tool detected
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — 无数据
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate5.4
已排除计分(无数据或不适用):ci_tests, signed_releases。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
13.2/25间接依赖不含已知公告 — 1 个受影响:@hono/node-server 1.19.15 (moderate 5.9)
40/40没有长期未处理的公告 — 没有公告公开超过 90 天
所用输入
sourceosv
advisories1
affected_packages1
assessed_packages96
unassessed_packages0
affected_by_severitymoderate 1
direct_affected_packages0
比对的是 npm:@lyric_dev/data-loom@0.13.0 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 96 个软件包。 未对可达性进行分析。

AI 就绪度

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

54中等 · 占总体的 0%
评分方式
0/45代理指令 — 没有 CLAUDE.md / AGENTS.md / 编辑器规则
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 80 次人类提交中有 67 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.838
agent_instruction_files
agent_instruction_max_bytes
评分方式
0/18一条命令的引导启动
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — tsconfig.json
10/10可复现环境 — lockfile
10/10已体现的代理实践 — 最近 80 次提交中有 76 次由代理编写或署名代理
5/8自动化维护 — 已配置依赖自动化,但在抽样提交中未观察到
3/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 3
所用输入
has_nix
has_tests
lockfilespackage-lock.json
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configstsconfig.json
agent_commit_share0.95
toolchain_manifests
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — TypeScript(静态类型)
52.7/55可控的文件大小 — 采样的 24 个源文件中有 1 个超过 60KB
所用输入
primary_languageTypeScript
largest_source_bytes83,024
source_files_sampled24
oversized_source_files1
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
20/20MCP 服务器
0/40可运行示例
所用输入
example_dirs
has_mcp_signal
api_schema_files

关键数据

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

更多细节

OpenSSF Scorecard 5.4 / 10
5.4综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
不适用CI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
10Dependency-Update-Toolupdate tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
10Packagingpackaging workflow detected
3Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 3
0SASTno SAST tool detected
10Security-Policysecurity policy file detected
不适用Signed-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
7Vulnerabilities3 existing vulnerabilities detected
直接依赖 2
注册表软件包版本约束清单文件
npm@modelcontextprotocol/sdk^1.29.0package.json
npmws^8.18.0package.json
全部依赖 117

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

注册表软件包版本关系
npm@modelcontextprotocol/sdk1.29.0直接
npmws8.21.0直接
npm@hono/node-server1.19.14间接
npm@types/node26.1.1间接
npm@types/ws8.18.1间接
npm@typescript/typescript-aix-ppc647.0.2间接
npm@typescript/typescript-darwin-arm647.0.2间接
npm@typescript/typescript-darwin-x647.0.2间接
npm@typescript/typescript-freebsd-arm647.0.2间接
npm@typescript/typescript-freebsd-x647.0.2间接
npm@typescript/typescript-linux-arm7.0.2间接
npm@typescript/typescript-linux-arm647.0.2间接
npm@typescript/typescript-linux-loong647.0.2间接
npm@typescript/typescript-linux-mips64el7.0.2间接
npm@typescript/typescript-linux-ppc647.0.2间接
npm@typescript/typescript-linux-riscv647.0.2间接
npm@typescript/typescript-linux-s390x7.0.2间接
npm@typescript/typescript-linux-x647.0.2间接
npm@typescript/typescript-netbsd-arm647.0.2间接
npm@typescript/typescript-netbsd-x647.0.2间接
npm@typescript/typescript-openbsd-arm647.0.2间接
npm@typescript/typescript-openbsd-x647.0.2间接
npm@typescript/typescript-sunos-x647.0.2间接
npm@typescript/typescript-win32-arm647.0.2间接
npm@typescript/typescript-win32-x647.0.2间接
npmaccepts2.0.0间接
npmajv8.20.0间接
npmajv-formats3.0.1间接
npmbody-parser2.3.0间接
npmbytes3.1.2间接
npmcall-bind-apply-helpers1.0.2间接
npmcall-bound1.0.4间接
npmcontent-disposition1.1.0间接
npmcontent-type1.0.5间接
npmcontent-type2.0.0间接
npmcookie0.7.2间接
npmcookie-signature1.2.2间接
npmcors2.8.6间接
npmcross-spawn7.0.6间接
npmdebug4.4.3间接
npmdepd2.0.0间接
npmdunder-proto1.0.1间接
npmee-first1.1.1间接
npmencodeurl2.0.0间接
npmes-define-property1.0.1间接
npmes-errors1.3.0间接
npmes-object-atoms1.1.2间接
npmescape-html1.0.3间接
npmetag1.8.1间接
npmeventsource3.0.7间接
npmeventsource-parser3.1.0间接
npmexpress5.2.1间接
npmexpress-rate-limit8.5.2间接
npmfast-deep-equal3.1.3间接
npmfast-uri3.1.2间接
npmfinalhandler2.1.1间接
npmforwarded0.2.0间接
npmfresh2.0.0间接
npmfunction-bind1.1.2间接
npmget-intrinsic1.3.0间接
npmget-proto1.0.1间接
npmgopd1.2.0间接
npmhas-symbols1.1.0间接
npmhasown2.0.4间接
npmhono4.12.27间接
npmhttp-errors2.0.1间接
npmiconv-lite0.7.2间接
npminherits2.0.4间接
npmip-address10.2.0间接
npmipaddr.js1.9.1间接
npmis-promise4.0.0间接
npmisexe2.0.0间接
npmjose6.2.3间接
npmjson-schema-traverse1.0.0间接
npmjson-schema-typed8.0.2间接
npmmath-intrinsics1.1.0间接
npmmedia-typer1.1.0间接
npmmerge-descriptors2.0.0间接
npmmime-db1.54.0间接
npmmime-types3.0.2间接
npmms2.1.3间接
npmnegotiator1.0.0间接
npmobject-assign4.1.1间接
npmobject-inspect1.13.4间接
npmon-finished2.4.1间接
npmonce1.4.0间接
npmparseurl1.3.3间接
npmpath-key3.1.1间接
npmpath-to-regexp8.4.2间接
npmpkce-challenge5.0.1间接
npmproxy-addr2.0.7间接
npmqs6.15.3间接
npmrange-parser1.3.0间接
npmraw-body3.0.2间接
npmrequire-from-string2.0.2间接
npmrouter2.2.0间接
npmsafer-buffer2.1.2间接
npmsend1.2.1间接
npmserve-static2.2.1间接
npmsetprototypeof1.2.0间接
npmshebang-command2.0.0间接
npmshebang-regex3.0.0间接
npmside-channel1.1.1间接
npmside-channel-list1.0.1间接
npmside-channel-map1.0.1间接
npmside-channel-weakmap1.0.2间接
npmstatuses2.0.2间接
npmtoidentifier1.0.1间接
npmtype-is2.1.0间接
npmtypescript7.0.2间接
npmundici-types8.3.0间接
npmunpipe1.0.0间接
npmvary1.1.2间接
npmwhich2.0.2间接
npmwrappy1.0.2间接
npmzod4.4.3间接
npmzod-to-json-schema3.25.2间接
依赖安全公告 1

安装 npm:@lyric_dev/data-loom@0.13.0 会引入 96 个包(直接与传递):其中 1 个存在已知公告,0 个为直接依赖。

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

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "claude-code",
        "dashboard",
        "mcp",
        "openspec",
        "roadmap",
        "spec-driven-development"
      ],
      "is_fork": false,
      "size_kb": 698,
      "has_wiki": true,
      "homepage": "https://github.com/groscy/data-loom#readme",
      "languages": {
        "CSS": 35094,
        "HTML": 6671,
        "JavaScript": 104682,
        "TypeScript": 133790
      },
      "pushed_at": "2026-07-25T11:47:42Z",
      "created_at": "2026-06-27T08:35:10Z",
      "owner_type": "User",
      "updated_at": "2026-07-20T23:11:08Z",
      "description": "Local dashboard for spec-driven development: a phased OpenSpec roadmap (WHAT) and an MCP topology (HOW).",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "master",
      "license_spdx_raw": "MIT",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript",
        "JavaScript",
        "CSS"
      ]
    },
    "owner": {
      "blog": null,
      "name": "Cyril Grossenbacher",
      "type": "User",
      "login": "groscy",
      "company": null,
      "location": null,
      "followers": 2,
      "avatar_url": "https://avatars.githubusercontent.com/u/92256856?v=4",
      "created_at": "2021-10-10T12:27:20Z",
      "is_verified": null,
      "public_repos": 15,
      "account_age_days": 1751
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.13.0",
          "kind": "minor",
          "published_at": "2026-07-20T23:10:53Z"
        },
        {
          "tag": "v0.12.1",
          "kind": "patch",
          "published_at": "2026-07-20T20:38:52Z"
        },
        {
          "tag": "v0.12.0",
          "kind": "minor",
          "published_at": "2026-07-20T17:07:09Z"
        },
        {
          "tag": "v0.11.0",
          "kind": "minor",
          "published_at": "2026-07-20T16:02:22Z"
        },
        {
          "tag": "v0.10.1",
          "kind": "patch",
          "published_at": "2026-07-18T21:26:18Z"
        },
        {
          "tag": "v0.10.0",
          "kind": "minor",
          "published_at": "2026-07-18T20:23:35Z"
        },
        {
          "tag": "v0.9.1",
          "kind": "patch",
          "published_at": "2026-07-17T21:46:42Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2026-07-11T10:38:56Z"
        },
        {
          "tag": "v0.8.1",
          "kind": "patch",
          "published_at": "2026-07-08T01:20:06Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-07-06T17:58:28Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-07-04T13:21:03Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-07-03T21:28:01Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-07-01T10:35:22Z"
        },
        {
          "tag": "v0.4.1",
          "kind": "patch",
          "published_at": "2026-06-29T21:31:52Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-06-29T21:04:22Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-06-29T18:51:09Z"
        },
        {
          "tag": "v0.2.4",
          "kind": "patch",
          "published_at": "2026-06-29T16:39:29Z"
        },
        {
          "tag": "v0.2.3",
          "kind": "patch",
          "published_at": "2026-06-29T05:49:26Z"
        },
        {
          "tag": "v0.2.2",
          "kind": "patch",
          "published_at": "2026-06-28T19:45:12Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2026-06-28T19:25:04Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-06-28T17:56:56Z"
        },
        {
          "tag": "v0.1.2",
          "kind": "patch",
          "published_at": "2026-06-27T12:58:20Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-06-27T11:31:18Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-06-27T11:11:51Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "a866d48a5db3424652915ff6aa57946a276fb78e",
          "body": "…nto the documentation\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.13.0 — the atlas opens on a navigable C4 map that drills i…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T23:10:53Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6ce1050005ad193fd5a1f2e884db96d8abf08471",
          "body": "The atlas map ships, so its change moves into the archive and its deltas land in\nspecs/: atlas-derivation gains the co-change relations requirement, atlas-view\nhas its subpage and building-block requirements rewritten, and atlas-map arrives\nas a capability in its own right.\n\nThe loop closes on itself — the archived change now appears in the map it added,\nand the two new edges it creates are labelled from the change that introduced\nthem.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: archive add-atlas-c4-map and sync the settled specs",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T22:52:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7d24be3722b022337ccbf47930bffb70a34fd551",
          "body": "…mentation\n\nThe atlas was the only view without a picture: 21 capabilities as one 9900px\nscrolling document that only got longer as the archive grew. It now opens on a\nC4-style board on the same canvas controller as the roadmap and topology —\nsystem, then domain, then capability — handing off to the\n[…]\ne window resizing and visual\nappearance remain unverified — the in-app browser pane delivers no\nResizeObserver callbacks and cannot screenshot.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: the atlas opens on a navigable C4 map that drills into the docu…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T22:31:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "20e56489c1062e0c982102a65261b9be2d4a9032",
          "body": "Both task lists ended with live window resizing unverified, because this\npreview environment never delivers ResizeObserver callbacks -- a freshly\nattached probe observer fired 0 times across a real viewport height change.\nConfirmed in a real browser after v0.12.1: resizing drives the minimap\ncrossover correctly on both the roadmap and the MCP topology. The observer\npath was correct as written.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: close the outstanding resize verification in both canvas archives",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T21:01:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6a0efe0f6658e83551d9c333f5a8978f32653b3b",
          "body": "…ridor\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.12.1 — MCP topology traces stay inside the hub-to-card cor…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T20:38:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "aa32289c4474329a950aaca14f1069e6e75c937d",
          "body": "Each connection turns at its own vertical channel, placed at 452 - i*22 on the\nleft bank and mirrored on the right. The corridor those channels must occupy is\nonly 178px wide (card edge 346 to chip edge 524), and nothing bounded the walk:\nfrom bank index 5 the final leg doubled back, from 14 the ver\n[…]\n share an ordering, so no trace's horizontal leg can fall inside\nanother's vertical span. Reordering would move traces without fixing anything.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: keep MCP topology traces inside the hub-to-card corridor",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T20:38:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6056d54c395a410f0d1815dc2016ea0755944a16",
          "body": "…ooms like the roadmap\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.12.0 — MCP topology grows with the server count and pans/z…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T17:07:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f5a1970fcd2135f2b930df50f80c353cd42a1e1b",
          "body": "…e roadmap\n\nThe topology board had the opposite problem to the roadmap: the canvas was\nfrozen at 1200x640 and servers were *compressed* into a constant 496px band,\nso from 19 servers the ~56px cards overlapped silently and from 42 the trace\nchannels left the viewBox. Nothing capped, wrapped or scrol\n[…]\ndecide without a\nmeasurable viewport, and the tab-switch handler revalidates the revealed view\nrather than relying on the ResizeObserver alone.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: MCP topology grows with the server count and pans/zooms like th…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T17:07:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e7b8412a792a0fd3c79e2f4a27022058925439a9",
          "body": "… retired to the Atlas\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.11.0 — roadmap pan/zoom canvas with minimap; archived band…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T16:02:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5e660dab2e34949d5a839742b1ddad56ee6d24ed",
          "body": "The archived \"done\" band predated the System Atlas, which now tells the\narchive's story properly: every archived change appears under Decisions &\nrationale with its date and recorded design, and each settled capability\nlinks back to the change that shaped it. The band was a bare list of names\ntaking\n[…]\nx card height. Real cards run 128-187px, so connectors met taller cards\nup to ~35px off centre. They now anchor to each card's measured centre.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: roadmap pan/zoom canvas with minimap; drop the archived done band",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-20T16:02:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "282a53265776cf41738e3dff5bb778257baef252",
          "body": null,
          "is_bot": false,
          "headline": "Release v0.10.1 — simplified README",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-18T21:26:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b104852f7ffe149c81123d2a0aa5054eebf86a13",
          "body": "Trim the README to a concise description plus Install and Use sections;\nmove the autostart internals, MCP-registration walkthrough, security\nmodel, and design principles out to their dedicated docs. Bring it up to\ndate with the Atlas view.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: simplify README to install + use",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-18T21:26:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c2cdceaf18983fb325b88fb4d272f313f43c70da",
          "body": "…e-last-visit overlay",
          "is_bot": false,
          "headline": "Release v0.10.0 — System Atlas: derived architecture docs with a sinc…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-18T20:23:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "47657b7e90816e60d2e054f82ec23bd712175d40",
          "body": "Layer a personalized \"what changed since your last visit\" overlay onto\nthe System Atlas. It reads the per-requirement provenance the atlas\nalready serves and compares it to a client-side cursor — no daemon\nchanges.\n\n- mark building blocks, their groups, and individual requirements whose\n  provenance\n[…]\norage (never written to\n  the workspace); the first visit seeds a clean baseline.\n\nImplements the add-atlas-recency OpenSpec change (archived).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: atlas since-last-visit recency overlay",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-18T18:47:12Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2ed082782654483e90e7ff9fae2ee061e7bd79c6",
          "body": "Add a System Atlas subpage that presents the settled system as living,\nArc42-flavored documentation, derived from the OpenSpec workspace and\nserved read-only over loopback like the roadmap.\n\n- daemon: assemble an AtlasModel (overview from config.yaml context,\n  building blocks from specs/ with requi\n[…]\nnce with deep-links, and a per-capability\n  \"shaping decisions & history\" section.\n\nImplements the add-system-atlas OpenSpec change (archived).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: System Atlas — derived Arc42-flavored architecture docs",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-18T18:45:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c0a4d5f70454413ab11b05b88ef072ef54503a5a",
          "body": "Integrates the two open Dependabot dev-dependency PRs. Both are\nbuild-time only — no change to the published runtime. Verified: the\nproject builds cleanly under TypeScript 7.0.2 and the emitted CLI runs.\n\nCloses #1\nCloses #2\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(deps-dev): bump @types/node to 26 and typescript to 7",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-17T22:02:11Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ec5d4a0dbde88838d6515229ae1fbd0a3e6262c8",
          "body": null,
          "is_bot": false,
          "headline": "Release v0.9.1 — hide flashing CLI console windows on Windows",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-17T21:46:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3433a8278c04aa6af4bfdb29087a63178e4d87e0",
          "body": "The daemon runs headless (detached / autostart, with no console of its\nown), so spawning the `openspec` and `claude` CLIs through a Windows shell\n— and spawning `clip` for the tray's copy-URL — made Windows allocate a\nfresh console window that flashed to the foreground and stole focus. It was\nmost v\n[…]\nuts across\ngenuine context switches produced zero visible console windows, with\npositive-control windows confirming the check could detect one.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: stop CLI console windows flashing on Windows",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-17T21:43:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ec2f52c84b8a91003150b6a1fb96b6ede08fb36b",
          "body": "Add the standard GitHub repository files: CONTRIBUTING and SECURITY\nguides, issue templates (bug/feature + config), a pull request\ntemplate, a build/typecheck CI workflow across Node 20 and 22, and a\nDependabot config for the npm and github-actions ecosystems.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: add community health files, CI, and dependabot",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-13T21:27:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bbf643fbb931b2b1f6571f915a71e449edaa969e",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.9.0 — proposal task list in the change detail panel",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-11T10:38:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5177a365e47760667c7b1ca7e840f20ef53d3d5f",
          "body": "Move the completed show-proposal-tasks change into the dated archive and\nfold its deltas into the settled specs: the new \"Per-change task list\nattached to the model\" requirement into roadmap-derivation, and the\nexpanded \"Node detail inspection\" requirement into roadmap-view.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: archive show-proposal-tasks and sync its specs",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-11T10:38:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fbcfc91286e2bfbf31e4d31b0156035dc861253c",
          "body": "Read each non-archived change's tasks.md directly (the CLI exposes only\ncounts, not task text) and attach a structured, section-grouped task list\nto its node, riding the existing model broadcast. The detail panel renders\nthe full list below the kept progress bar: done items get a check and\nstrikethr\n[…]\nd progress bar live-update on a tasks.md edit without re-selecting the\nnode, skipping the slide-in animation when the panel is already visible.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: show the proposal task list in the change detail panel",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-11T10:38:00Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "13bb7d08f0a800a1829d788b9e55aa30a6ecbe25",
          "body": "Document the daemon's three tiers, its four subsystems, the live\nwrite-back loop, and a module map, with an architecture diagram. Link it\nfrom the README.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add ARCHITECTURE.md with module map and diagram",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-11T10:37:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a2d8ee02e16b2effbb7906391beb89915882f76e",
          "body": "Move the completed add-dashboard-command-handoff change into the dated\narchive and fold its command-handoff requirements into the roadmap-view\nspec. Housekeeping left over from the v0.8.0 release.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: archive add-dashboard-command-handoff and sync its spec",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-11T10:37:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "52125fadd79f7af3c91a547e0313ce3784e2a662",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.8.1 — horizontally scrollable roadmap for deep plans",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-08T01:20:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "92b6b5efa9ee85a89f4f3f4ca3b301ee4cf8a20c",
          "body": "Applies the roadmap-view delta to the canonical spec: adds \"Phase columns\nkeep a fixed footprint at any depth\" and \"Horizontal scrolling for wide\nroadmaps\", and removes the stale \"Vertically stacked phase bands\"\nrequirement (the shipped layout is horizontal columns, not vertical bands).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: archive horizontal-scroll-roadmap and sync its spec",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-08T01:19:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d10e3dcf98792315e6c9706183ced1564bf1d82d",
          "body": "The roadmap laid phases left-to-right across a fixed-width design canvas,\ndividing that width evenly among however many phases existed. Past ~3-4\nphases the per-phase spacing shrank below a card's width, so phase frames\nand change cards overlapped and clipped -- a 9-phase plan was unreadable.\n\nGive \n[…]\ntacking are\nunchanged (they already worked in canvas units). Client-side only -- the\ndaemon, phase derivation, and roadmap model are untouched.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: make the roadmap horizontally scrollable for deep plans",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-08T01:19:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e986e3b21540bfd733669f612a25307ed2011c78",
          "body": "…the dashboard\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.8.0 — copy weave/apply/archive commands to clipboard from …",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-06T17:58:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c21084e1177bed739e79ecce07ea4352793bf545",
          "body": "Surface the three agent-driven workflows as contextual, clipboard-copy\nactions on the roadmap view, each shown only where DataLoom already proves\nthe precondition:\n\n- Weave on the dependency-review banner -> /loom:weave\n- Apply on a change's card and detail panel -> /opsx:apply <name>\n- Archive on a\n[…]\nds -- it\nnever executes the workflows, and the daemon/MCP server are unchanged.\n\nCaptured under openspec/changes/add-dashboard-command-handoff.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: copy weave/apply/archive commands to clipboard from the dashboard",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-06T16:59:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "39ace3621e4dee2ab916562d7c6a05a184c0a7c9",
          "body": "…t, and one-command setup\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.7.0 — on-demand shim, supervised always-on, weave-as-promp…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T13:21:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bda3fdfc71a6a9a6ba91681a2d3a6cb5d89578fd",
          "body": "Move one-command-setup (the `data-loom up` verb, implemented in 7613a7a)\ninto openspec/changes/archive/2026-07-04-one-command-setup, and sync its\nnew guided-setup capability into openspec/specs. All 19 specs validate; no\nopen changes remain.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: archive one-command-setup and sync its spec",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T13:18:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7613a7a1e28e3fef6456d8afd49cc23d90d324d5",
          "body": "`data-loom up [project]` takes a fresh machine to a fully working always-on\nDataLoom in one paste: it verifies the openspec prerequisite up front (and\nexits non-zero with the install command, changing nothing, when it's\nmissing), then runs the same enable sequence as `autostart enable` (register\naut\n[…]\ned: composed flow + idempotent double-run (no duplicate registrations),\nand the missing-openspec abort leaves the system untouched and exits 1.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add `data-loom up` one-command setup verb",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T10:58:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3140098a60359e25a4634be242aca7dac0dd8604",
          "body": "On Linux and macOS, `autostart enable` starts the daemon via the supervisor\nitself (systemd `enable --now`, launchd `RunAtLoad`), so the follow-up\n`lifecycle.start()` spawned a second detached instance that raced the\nsupervised one for the loopback port — the loser exited 0 via the\nsingle-instance g\n[…]\ny fire on next login), and runAutostart\nstarts the daemon itself only when registration didn't. Found during\nharden-always-on WSL verification.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: skip redundant daemon start when the supervisor already launched it",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T10:45:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b1d3942555f50a23068dc5aacb0e31bdf18555af",
          "body": "Move harden-always-on (implemented in 31d0857, verified on real systemd)\ninto openspec/changes/archive/2026-07-04-harden-always-on, and sync its\ndeltas into openspec/specs: startup-autolaunch's Per-OS mechanism becomes\nthe supervising form (Scheduled Task / LaunchAgent KeepAlive / systemd unit)\nwith\n[…]\ngacy-registration migration; daemon-lifecycle gains the update\ncommand. All 18 specs validate.\n\none-command-setup remains the only open change.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: archive harden-always-on and sync its specs",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T10:34:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a4256a93341ecdb480138d98fb8c6c4e29a759f6",
          "body": "Tasks 4.1/4.2 verified end-to-end on the Linux systemd path via a real\n`systemctl --user` unit in WSL2 (portable node + isolated prefix, torn down\nafter):\n- crash (kill -9 of MainPID) → systemd auto-restarts (NRestarts 0→1, new\n  pid, reachable again)\n- `data-loom stop` → unit inactive, not restarte\n[…]\nk creation); the systemd unit proves\nthe same restart-on-failure contract. Windows clean-stop exit-0 was verified\nseparately via /api/shutdown.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: verify harden-always-on supervised restart on real systemd",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T10:07:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c7ce91189253c76ab217b4938cdc321149c6b69b",
          "body": "Dependency declared during the weave review — `up` should register the\nsupervised autostart form and rewrite the README once, after harden-always-on\nlands.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: record one-command-setup depends on harden-always-on",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T09:50:12Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2b2fae9a4c110f78238be66d646e224b0b5c7fb4",
          "body": "Move add-tray-icon and add-connect-claude-code (shipped in v0.6.0) plus\non-demand-daemon and serve-weave-as-prompt (implemented in 31d0857) into\nopenspec/changes/archive/2026-07-04-*, and sync their delta specs into\nopenspec/specs: new capabilities tray-indicator, claude-code-integration\n(merged con\n[…]\nlaude Code registration on enable) and\nroadmap-mcp-server (weave served as an MCP prompt).\n\nharden-always-on and one-command-setup remain open.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: archive four completed changes and sync capability specs",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T09:50:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "32fb8a47fe9e49b0c16cccfe99a718412bb83ab5",
          "body": "Finish the harden-always-on apply (implementation landed in 31d0857).\nVerification found that on Windows `data-loom stop` force-terminated the\ndaemon with exit 1 (process.kill -> TerminateProcess, handler skipped),\nwhich a restart-on-failure supervisor would misread as a crash and relaunch\n— breakin\n[…]\nopen: the\nOS-triggered restart can't be exercised on this host (non-elevated Task\nScheduler access denied) and needs a real supervised session.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: record harden-always-on apply — Windows clean-stop fix",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T09:48:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "31d0857975b3a692581dbe4cb88cbb3865ecbcb2",
          "body": "Add `data-loom mcp-shim`: a client-spawned stdio MCP endpoint that starts\nthe daemon through the existing detached lifecycle path when the loopback\nport is dead, waits (bounded) for it to answer, then proxies MCP traffic to\nthe daemon's HTTP `/mcp` for the life of the session. The shim defines no\nto\n[…]\nht work from the serve-weave-as-prompt and harden-always-on changes;\nthey are included here because the shim wiring won't compile without them.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: on-demand daemon launch via a stdio MCP shim",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-04T09:26:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8000002e9fa91ea53bc36d6067c42eff805b7aa5",
          "body": "Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.6.0 — system-tray indicator and Claude Code auto-registration",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T21:28:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b7bb107733f57715e990613cefaf5b3fb13a0e0b",
          "body": "Capture a change to make the daemon's weave review workflow an MCP prompt\n(the single source of truth, always matching the running server), with\nthe installed /loom:weave file shrinking to a thin, version-stamped alias\nprovisioned by `connect claude-code` and self-healed on daemon startup —\nreplacing the current agent-mediated install path that drifts and never\nrefreshes.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: propose serving the weave workflow as an MCP prompt",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T20:56:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4dae11ea290d781af060b28888ed5f57fab4c569",
          "body": "Capture a change for a client-spawned stdio shim that starts the daemon\nwhen it isn't running and proxies MCP traffic to its loopback HTTP\nendpoint, removing \"remember to start DataLoom\" as a failure class for\nClaude Code sessions. Registered via a new `connect claude-code\n--on-demand` mode, complementary to (and independent of) the always-on\nsupervision path.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: propose an on-demand daemon launch via a stdio MCP shim",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T20:56:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "523fb4fdb3aa0b8d0f107d38a1cee8d9108035cf",
          "body": "Capture a `data-loom up` change: check the openspec prerequisite up front\n(fail fast, no partial setup), then run the existing enable sequence\n(login autostart, daemon start, Claude Code registration), finishing with\na state summary. Re-runnable and idempotent, so it doubles as a setup\nhealth check.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: propose a one-command guided setup verb",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T20:56:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8e3b5b4ef436f9b2b5ed4d66bbe0fe8db6344d32",
          "body": "Capture a change to replace fire-and-forget login items with native\nper-user supervisors (Windows Scheduled Task, macOS LaunchAgent KeepAlive,\nLinux systemd user unit) so a crashed daemon restarts automatically, a\nstable launcher so autostart survives Node version-manager churn and npm\nrelocations, and a `data-loom update` verb tying upgrade + restart +\nre-registration together.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: propose hardening the always-on daemon with real OS supervision",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T20:56:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e661c568ae60f63a112b97272c4827777acb6aa0",
          "body": "Add `data-loom connect/disconnect claude-code`, registering the daemon's\nloopback MCP endpoint at user scope through Claude Code's own CLI (never\nwriting ~/.claude.json directly), with graceful fallback to the manual\n`claude mcp add` line when the `claude` CLI is absent. `autostart enable`\nnow chain\n[…]\nregistration in as a best-effort step (--no-connect to\nskip), so enabling always-on can both host and register the MCP endpoint\nin one command.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: register DataLoom with Claude Code via a connect command",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T20:55:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "868ce54037fd0e33b129f4121563cb88e047de16",
          "body": "Give the detached background daemon a glanceable \"is DataLoom running?\"\nsignal plus one-click open/copy/stop, since there is no console or window\nonce it starts in background mode. Hardens daemon startup with graceful\nEADDRINUSE handling (point at the already-running instance instead of\ncrashing) so a foreground launch never fights the tray of a background one.\n\nCo-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: add a system-tray indicator for the running daemon",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T20:54:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4ceabcfee859396e668cbac35b4a35ed37faa040",
          "body": "The serverInfo version was hardcoded and stuck at 0.4.1 through the 0.5.0\nrelease. Read it from the package.json shipped next to the compiled code so\nit can never drift again.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: advertise the real package version in the MCP server info",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T20:50:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3d73ff412fac92a56cd04626885632c41c5c6b1d",
          "body": "The background daemon keeps serving the previously installed global package\nuntil it is both reinstalled and restarted, so a release could leave a stale\ndaemon answering on the port (as happened with the MCP parse-error fix).\n\nAdd scripts/sync-global.mjs — build, pack to a temp tarball, install it\ng\n[…]\nreshly installed CLI shim — wired to postpublish so every `npm publish`\ndoes it automatically. Also runnable manually via `npm run sync-global`.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: sync the global install and restart the daemon on publish",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T20:46:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "66d1c850c146a5afe762127abb67721ec787eced",
          "body": "… not a 500\n\nA tools/call body containing unescaped Windows-path backslashes\n(\"D:\\projects\\...\" — \\p is not a valid JSON escape) failed JSON.parse in\nreadJsonBody, and the SyntaxError fell through handleMcp's generic catch as an\nopaque HTTP 500 {\"error\":\"internal error\"} — misreporting a client enco\n[…]\nrse failure to HTTP 400 with a JSON-RPC -32700 error whose message\nechoes the parser's complaint and hints at escaping Windows path backslashes.\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: answer malformed MCP request bodies with a JSON-RPC parse error,…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-03T20:39:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c1f77b0d547108e53c63540c1eb756c3db9a1750",
          "body": "…op support\n\nAdd detached background run mode with start/stop/restart/status lifecycle\ncommands and a single-instance port guard; per-user login autostart\n(Windows Startup shortcut, macOS LaunchAgent, Linux XDG) via\nautostart enable|disable|status; and Claude Desktop registration\n(connect/disconnect\n[…]\norm with an\nmcp-remote stdio bridge fallback. All served by the one existing\nloopback daemon; foreground launch and security posture unchanged.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.5.0 — background daemon, login autostart, and Claude Deskt…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-07-01T10:35:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "21750a1aa149053427b51187c223eff34760c9ec",
          "body": "Security hardening for the HTTP MCP endpoint added in v0.4.0. Moving the\nMCP server onto the loopback HTTP daemon made it reachable by the browser\nand other local processes; this closes that surface.\n\n- Host + Origin guard on every HTTP request and the WebSocket upgrade:\n  reject a non-loopback Host\n[…]\ndual local-process risk is documented.\n\nArchives openspec change harden-mcp-endpoint and syncs the roadmap-daemon\nand roadmap-mcp-server specs.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.4.1 — harden the daemon-hosted MCP endpoint",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-29T21:31:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0161b4cabf221504846ca91e8bac5c679be176c0",
          "body": "Serve the MCP server from the running dashboard daemon over Streamable-HTTP\ninstead of a per-project stdio process, so setup is once per machine rather\nthan once per project.\n\n- Daemon hosts an MCP endpoint at /mcp (127.0.0.1:4317) via\n  StreamableHTTPServerTransport; one registration serves every p\n[…]\nistrations with the single user-scope HTTP registration.\n\nArchives openspec change serve-mcp-from-daemon and syncs the roadmap-mcp-server\nspec.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.4.0 — daemon-hosted HTTP MCP server",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-29T21:04:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3170a85a05b663514e9a347b33af36b4c1fe26bf",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.3.0 — blueprint redesign",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-29T18:51:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5853c676f85455394e0c9c1e4eb78adb34c4db24",
          "body": "…opology\n\nRe-skin both views into a drafting-paper blueprint system with a light/dark\ntheme switch (persisted to localStorage), all colours driven by CSS variables.\n\n- Roadmap: framed dependency graph — phase-band frames, full proposal cards\n  (status bar, pills, waiting note, caps/tasks, NEXT-UP), \n[…]\npx) with slide-in.\n- Project dropdown options themed so the native popup is readable in both themes.\n\nFront-end only — no daemon/model changes.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: blueprint redesign — framed roadmap graph + circuit-board MCP t…",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-29T18:49:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5cca2bed5ec588370d93245cf7ee0b019c786eee",
          "body": "The embedded /loom:weave command (written by install_weave_skill) still\npointed `claude mcp add` at the unscoped `npx data-loom`; correct it to\nthe published scoped package name.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Scope the weave command's register example to @lyric_dev/data-loom",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-29T16:45:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b9d3e561292a9eeb57c4476f1f35b5bcf6b53db2",
          "body": "Unscoped `data-loom` is blocked by npm's name-similarity rule (too close\nto the existing `dataloom` package), so publish as `@lyric_dev/data-loom`.\nThe installed bin command stays `data-loom`. Update README install/MCP docs.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Publish under @lyric_dev scope (v0.2.4)",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-29T16:39:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "58ee0a3ce7e71e98135f719e8b702451d7cbff18",
          "body": "First release on the npm-distribution pipeline (npx data-loom). Bumped to\n0.2.3 because v0.2.2 is taken by the prior exe release.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.2.3 — first npm publish",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-29T05:49:26Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "99a00ea172af769d2842d800d418e5b6c023d0d7",
          "body": "The unsigned DataLoom.exe tripped Windows SmartScreen and AV false\npositives; code signing is the only real fix and carries cost/eligibility\nfriction. The app is already a Node daemon + browser SPA with a `data-loom`\nbin, so publish to npm instead: `npx data-loom` runs under the user's\nalready-signe\n[…]\ned-launch, and app-branding\ncapabilities; supersedes the strip-corrupted-signature exploration (both\narchived under openspec/changes/archive/).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Distribute via npm; remove the Windows SEA executable build",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-29T05:28:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3841271c7480e238f245b2430198b37f938fc1da",
          "body": "Maintenance release: tag the esbuild advisory fix and Node 24 CI action\nupgrades (6a3a16f) as a build, exercising the new node24 actions.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Release v0.2.2",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-28T19:45:12Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6a3a16fa8448bda1d6871d1ff4b6464f9c83b875",
          "body": "- Bump esbuild ^0.24.0 -> ^0.25.0 (resolved 0.25.12), clearing\n  GHSA-67mh-4wv8-2f99 (the dev-server CORS advisory); npm audit is now\n  clean. We only use esbuild for bundling, not its dev server, so it was\n  not exploitable here, but this clears the Dependabot alert.\n- Upgrade release workflow acti\n[…]\n v4 -> v6, softprops/action-gh-release\n  v2 -> v3 (files/fail_on_unmatched_files inputs unchanged), clearing the\n  Node 20 deprecation warning.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix esbuild dev-server advisory and modernize CI action runtimes",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-28T19:43:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "15d94f85c6fab5e4862dbfca76c356d9c576019c",
          "body": "- install_weave_skill MCP tool writes a global /loom:weave command that\n  runs the dependency review (list -> propose -> confirm -> apply); the\n  server advertises it in its connect-time instructions\n- release workflow now publishes a SHA-256 checksum (DataLoom.exe.sha256)\n  beside the exe; README d\n[…]\nx, still to come)\n- Archive add-weave-skill and add-release-checksums; sync the\n  roadmap-mcp-server and release-pipeline specs\n- Bump to 0.2.1\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add /loom:weave skill provisioning and release checksums (v0.2.1)",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-28T19:25:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "75527385f4833a91e70d0a7ab792ff6f8f865d5d",
          "body": "- data-loom mcp: stdio MCP server exposing open proposals plus\n  dependency tools (list_open_proposals, set_dependency,\n  mark_independent), reasoned under the user's own authenticated Claude\n- Dependency-review state derived from `## Depends On` presence;\n  pending proposals get a roadmap \"needs re\n[…]\ncy-review; sync the\n  roadmap-mcp-server / roadmap-derivation / roadmap-view specs\n- Bump version to 0.2.0; document the new tool in the README\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add MCP server mode and dependency-review workflow (v0.2.0)",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-28T17:56:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cb37feaf2989493b4450eb3bb64d0c5241c6ee61",
          "body": "- Extend roadmap-view (8 -> 10 requirements) with the stacked-band layout\n- Move the change to openspec/changes/archive/2026-06-27-phase-band-layout/\n\nAll changes archived; 0 active.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive phase-band-layout; settle into roadmap-view baseline",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T12:58:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c6d458070c599a4c27f598ed7ea32923289c4114",
          "body": "Render phases as vertically stacked dashed bands (earliest on top) with\ncards in a row, a downward phase-progression arrow between bands, and\ndashed dependency connectors between cards. Status/readiness badges,\nconflicts, the project selector, and the done-band are unchanged.\nView-only (public/).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Restructure roadmap into stacked phase bands",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T12:58:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "002cc5066a219513a8ec7c22b14a0d04bf3b6266",
          "body": "- Create openspec/specs/phase-planning/spec.md\n- Move the change to openspec/changes/archive/2026-06-27-add-phase-planning/\n\nAll changes archived; 0 active.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive add-phase-planning; settle phase-planning into baseline",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T12:48:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a03155289323900c8daddeddb2c24d8288e66729",
          "body": "- Proposals can declare `## Depends On: <change names>`; the derivation\n  merges those edges with capability-derived ones, so interdependent open\n  proposals sequence into phases even when they only touch baseline\n  capabilities\n- Classify each open proposal ready/blocked/done — finer than phase: a\n\n[…]\new\n\nVerified against a synthetic Depends-On graph (blocked, ready-before-\narchive, archived-satisfied, unknown->conflict) and the live roadmap.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Implement phase planning: explicit deps + readiness guidance",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T12:47:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7354f54baec8e2b71c2297f95b0ef88c52f43d92",
          "body": "- Extend self-contained-launch (3->5) and project-selection (4->5)\n- Move the change to openspec/changes/archive/2026-06-27-fix-exe-first-run/\n\nAll changes archived; 0 active.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive fix-exe-first-run; settle launch fixes into baseline",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T11:31:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1004fb72442125cd1c905cc0e66f9c09f1c5e6c1",
          "body": "Make a double-clicked DataLoom.exe usable:\n- Resilient launch: if the launch dir has no openspec/ workspace, use the\n  first discovered project, else start in a no-project picker state —\n  never exit (except for the missing openspec prerequisite)\n- Open the default browser to the dashboard on startu\n[…]\nprompt; discoverProjects no longer offers a non-openspec dir as current\n- Bump version to 0.1.1; suppress browser-open in the dev launch config\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix exe first-run: serve without a project + open browser",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T11:30:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "857e8cca9b4a6441519da8cea92342149f29d155",
          "body": "- Create openspec/specs/app-branding/spec.md (4 requirements)\n- Move the change to openspec/changes/archive/2026-06-27-brand-dataloom/\n\nAll changes archived; 0 active, 10 baseline capabilities.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive brand-dataloom; settle app-branding into baseline",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T11:11:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4b510f9f8fec582c1b4b6ef92a7b2b2b00887cbf",
          "body": "- Add public/icon.svg: a woven warp/weft tile with data-node dots\n- Header logo + \"DataLoom\" name, favicon, and page title\n- Packaging: render DataLoom.ico from the SVG, set it + ProductName on\n  the exe via rcedit, output DataLoom.exe, embed icon.svg as a SEA asset\n- Release workflow and README reference DataLoom / DataLoom.exe\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Brand the app as DataLoom with an app icon",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T11:11:40Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8ff06f3f3e3616b2dc8c5b405b3157e20d324bc8",
          "body": "- Create openspec/specs/{project-selection,self-contained-launch,release-pipeline}\n- Extend roadmap-daemon (6->7), roadmap-view (7->8), mcp-discovery (3->4)\n- Move the change to openspec/changes/archive/2026-06-27-self-contained-multi-project/\n\nAll changes archived; 0 active, 9 baseline capabilities.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive self-contained-multi-project; settle specs into baseline",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T10:55:55Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "121fc2fa4598ec2e986f35159dbeeae7a2832018",
          "body": "Implement self-contained-multi-project:\n\n- Standalone Windows .exe via Node SEA (esbuild bundle + embedded\n  public/ assets + postject). openspec stays an external prerequisite\n  the exe invokes, exiting with install guidance if missing.\n- Runtime-selectable project: launch arg + in-app header selec\n[…]\ne runs from a directory with no public/ (embedded\nassets), lists real projects, switches live, and exits with guidance\nwhen openspec is absent.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add standalone exe, multi-project selection, and README",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T10:55:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2badb23223f7df1782477a7ca6e3c0ee71c001c7",
          "body": "Archive the final change and sync its capabilities:\n\n- Extend openspec/specs/roadmap-derivation (6 -> 9 requirements) with\n  cycle detection, dangling-dependency detection, and conflict info\n- Extend openspec/specs/roadmap-view (5 -> 7) with conflict marking and\n  relationship surfacing\n- Move the change to\n  openspec/changes/archive/2026-06-27-add-roadmap-conflict-detection/\n\nAll changes are now archived; data_loom is feature-complete.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive add-roadmap-conflict-detection; settle final specs into baseline",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T10:18:16Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c6485299b2326e7b6df638917bc6faadf57a2469",
          "body": "Build add-roadmap-conflict-detection — surface ordering problems on the\nroadmap:\n\n- Derivation: detect dependency cycles (DFS back-edge), promote\n  unsatisfied (Modified-but-unowned, non-baseline) capabilities to\n  dangling conflicts, attach a conflicts[] to the model defensively\n- View: a conflicts\n[…]\nerified:\nclean workspace reports zero conflicts; a synthetic cycle and dangling\ndependency are both detected; the banner and node marks render.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Implement conflict detection (cycle + dangling deps)",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T10:15:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "299c059fbf096af7bee668a896210c9602368c6c",
          "body": "Archive the completed MCP topology change and sync its capabilities:\n\n- Create openspec/specs/{mcp-discovery,mcp-availability,topology-view}\n- Extend openspec/specs/roadmap-daemon (4 -> 6 requirements) with the\n  config-reading and topology-serving requirements\n- Move the change to openspec/changes/archive/2026-06-27-add-mcp-topology/\n\nOnly add-roadmap-conflict-detection remains (Phase 1).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive add-mcp-topology; settle Phase 2 specs into baseline",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T10:05:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "da23af0fc2a4dce263d7c5e0bf7e13e278554cda",
          "body": "Build add-mcp-topology — the \"how / with what do I develop?\" view:\n\n- Discovery: merge MCP servers from ~/.claude.json (global + project)\n  and ~/.claude/.mcp.json, dedupe across scopes/path-variants, detect\n  transport, and redact secrets at the boundary (env/tokens never reach\n  the client)\n- Pass\n[…]\ntasks.md and marks all\n19 tasks complete. Verified against the real local config: comfyui\nalready-running, unreal on-demand, no secrets leaked.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Implement Phase 2: MCP topology (HOW tab)",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T10:01:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1a6128e01c08225347fc9506776991f8602a6c31",
          "body": "Archive the completed Phase 1 change and sync its three capabilities\ninto the spec baseline:\n\n- Create openspec/specs/{roadmap-daemon,roadmap-derivation,roadmap-view}\n  (15 requirements total)\n- Move the change to\n  openspec/changes/archive/2026-06-27-scaffold-roadmap-daemon/\n\nWith the foundation se\n[…]\nhanges (add-mcp-topology,\nadd-roadmap-conflict-detection) now resolve their dependencies against\nthe baseline and are unblocked (both Phase 1).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Archive scaffold-roadmap-daemon; settle Phase 1 specs into baseline",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T09:44:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2db648414040a22e47f311ebb1bc287ce40fa341",
          "body": "Build the data_loom foundation (scaffold-roadmap-daemon):\n\n- Node daemon: loopback HTTP + WebSocket push, debounced openspec/\n  file-watcher, startup openspec CLI availability check\n- Derivation: capability-ownership dependency DAG, topological phases,\n  task-based status (independent axis), cycle/d\n[…]\nn and recomputes live on\nedit. Marks all 26 tasks complete and records the derivation\ndata-source clarification in the roadmap-derivation spec.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Implement Phase 1: roadmap daemon, derivation, and live view",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T09:37:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f1b3bf8198a28c3e56a741c0592c0d12a39e30dc",
          "body": "Set up the spec-driven workflow and propose the initial phased roadmap\nas three dependency-linked changes:\n\n- scaffold-roadmap-daemon (Phase 1): local Node daemon + browser SPA,\n  derived dependency DAG, phased \"what to develop\" roadmap, live\n  file-watching\n- add-mcp-topology (Phase 2): hub-and-spo\n[…]\ne 2): surface dependency cycles\n  and dangling / out-of-order dependencies\n\nProject context and decisions are recorded in openspec/config.yaml.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add OpenSpec proposals for the data_loom dashboard",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T09:15:20Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6b958f5d3b59ba70166b197cd6a9401e58f527f7",
          "body": null,
          "is_bot": false,
          "headline": "Initial commit",
          "author_name": "Cyril Grossenbacher",
          "author_login": "groscy",
          "committed_at": "2026-06-27T08:35:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 24,
      "commits_last_year": 80,
      "latest_release_at": "2026-07-20T23:10:53Z",
      "latest_release_tag": "v0.13.0",
      "releases_from_tags": true,
      "days_since_last_push": 2,
      "active_weeks_last_year": 5,
      "days_since_latest_release": 6,
      "mean_days_between_releases": 1.6
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 85,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@lyric_dev/data-loom",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "openspec",
            "mcp",
            "dashboard",
            "roadmap",
            "spec-driven-development",
            "claude-code"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@lyric_dev/data-loom",
          "is_deprecated": false,
          "latest_version": "0.13.0",
          "repository_url": "https://github.com/groscy/data-loom",
          "versions_count": 17,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 3047,
          "first_published_at": "2026-06-29T16:41:36.897000Z",
          "latest_published_at": "2026-07-20T23:11:24.457000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 6
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0,
        "collected_at": null
      },
      "open_issues_and_prs": 3
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": true,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 83024,
      "source_files_sampled": 24,
      "oversized_source_files": 1,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [
          {
            "name": "@hono/node-server",
            "direct": false,
            "version": "1.19.15",
            "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": 5
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "moderate": 1
        },
        "advisory_count": 1,
        "affected_count": 1,
        "assessed_count": 96,
        "malicious_count": 0,
        "assessed_package": "npm:@lyric_dev/data-loom@0.13.0",
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@modelcontextprotocol/sdk",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.29.0"
        },
        {
          "name": "ws",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^8.18.0"
        }
      ],
      "all_dependencies": {
        "error": null,
        "source": "github-sbom",
        "packages": [
          {
            "name": "@modelcontextprotocol/sdk",
            "direct": true,
            "version": "1.29.0",
            "ecosystem": "npm"
          },
          {
            "name": "ws",
            "direct": true,
            "version": "8.21.0",
            "ecosystem": "npm"
          },
          {
            "name": "@hono/node-server",
            "direct": false,
            "version": "1.19.14",
            "ecosystem": "npm"
          },
          {
            "name": "@types/node",
            "direct": false,
            "version": "26.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "@types/ws",
            "direct": false,
            "version": "8.18.1",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-aix-ppc64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-darwin-arm64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-darwin-x64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-freebsd-arm64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-freebsd-x64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-linux-arm",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-linux-arm64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-linux-loong64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-linux-mips64el",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-linux-ppc64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-linux-riscv64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-linux-s390x",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-linux-x64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-netbsd-arm64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-netbsd-x64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-openbsd-arm64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-openbsd-x64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-sunos-x64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-win32-arm64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "@typescript/typescript-win32-x64",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "accepts",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "ajv",
            "direct": false,
            "version": "8.20.0",
            "ecosystem": "npm"
          },
          {
            "name": "ajv-formats",
            "direct": false,
            "version": "3.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "body-parser",
            "direct": false,
            "version": "2.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "bytes",
            "direct": false,
            "version": "3.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "call-bind-apply-helpers",
            "direct": false,
            "version": "1.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "call-bound",
            "direct": false,
            "version": "1.0.4",
            "ecosystem": "npm"
          },
          {
            "name": "content-disposition",
            "direct": false,
            "version": "1.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "content-type",
            "direct": false,
            "version": "1.0.5",
            "ecosystem": "npm"
          },
          {
            "name": "content-type",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "cookie",
            "direct": false,
            "version": "0.7.2",
            "ecosystem": "npm"
          },
          {
            "name": "cookie-signature",
            "direct": false,
            "version": "1.2.2",
            "ecosystem": "npm"
          },
          {
            "name": "cors",
            "direct": false,
            "version": "2.8.6",
            "ecosystem": "npm"
          },
          {
            "name": "cross-spawn",
            "direct": false,
            "version": "7.0.6",
            "ecosystem": "npm"
          },
          {
            "name": "debug",
            "direct": false,
            "version": "4.4.3",
            "ecosystem": "npm"
          },
          {
            "name": "depd",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "dunder-proto",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "ee-first",
            "direct": false,
            "version": "1.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "encodeurl",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "es-define-property",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "es-errors",
            "direct": false,
            "version": "1.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "es-object-atoms",
            "direct": false,
            "version": "1.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "escape-html",
            "direct": false,
            "version": "1.0.3",
            "ecosystem": "npm"
          },
          {
            "name": "etag",
            "direct": false,
            "version": "1.8.1",
            "ecosystem": "npm"
          },
          {
            "name": "eventsource",
            "direct": false,
            "version": "3.0.7",
            "ecosystem": "npm"
          },
          {
            "name": "eventsource-parser",
            "direct": false,
            "version": "3.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "express",
            "direct": false,
            "version": "5.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "express-rate-limit",
            "direct": false,
            "version": "8.5.2",
            "ecosystem": "npm"
          },
          {
            "name": "fast-deep-equal",
            "direct": false,
            "version": "3.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "fast-uri",
            "direct": false,
            "version": "3.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "finalhandler",
            "direct": false,
            "version": "2.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "forwarded",
            "direct": false,
            "version": "0.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "fresh",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "function-bind",
            "direct": false,
            "version": "1.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "get-intrinsic",
            "direct": false,
            "version": "1.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "get-proto",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "gopd",
            "direct": false,
            "version": "1.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "has-symbols",
            "direct": false,
            "version": "1.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "hasown",
            "direct": false,
            "version": "2.0.4",
            "ecosystem": "npm"
          },
          {
            "name": "hono",
            "direct": false,
            "version": "4.12.27",
            "ecosystem": "npm"
          },
          {
            "name": "http-errors",
            "direct": false,
            "version": "2.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "iconv-lite",
            "direct": false,
            "version": "0.7.2",
            "ecosystem": "npm"
          },
          {
            "name": "inherits",
            "direct": false,
            "version": "2.0.4",
            "ecosystem": "npm"
          },
          {
            "name": "ip-address",
            "direct": false,
            "version": "10.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "ipaddr.js",
            "direct": false,
            "version": "1.9.1",
            "ecosystem": "npm"
          },
          {
            "name": "is-promise",
            "direct": false,
            "version": "4.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "isexe",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "jose",
            "direct": false,
            "version": "6.2.3",
            "ecosystem": "npm"
          },
          {
            "name": "json-schema-traverse",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "json-schema-typed",
            "direct": false,
            "version": "8.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "math-intrinsics",
            "direct": false,
            "version": "1.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "media-typer",
            "direct": false,
            "version": "1.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "merge-descriptors",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "mime-db",
            "direct": false,
            "version": "1.54.0",
            "ecosystem": "npm"
          },
          {
            "name": "mime-types",
            "direct": false,
            "version": "3.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "ms",
            "direct": false,
            "version": "2.1.3",
            "ecosystem": "npm"
          },
          {
            "name": "negotiator",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "object-assign",
            "direct": false,
            "version": "4.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "object-inspect",
            "direct": false,
            "version": "1.13.4",
            "ecosystem": "npm"
          },
          {
            "name": "on-finished",
            "direct": false,
            "version": "2.4.1",
            "ecosystem": "npm"
          },
          {
            "name": "once",
            "direct": false,
            "version": "1.4.0",
            "ecosystem": "npm"
          },
          {
            "name": "parseurl",
            "direct": false,
            "version": "1.3.3",
            "ecosystem": "npm"
          },
          {
            "name": "path-key",
            "direct": false,
            "version": "3.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "path-to-regexp",
            "direct": false,
            "version": "8.4.2",
            "ecosystem": "npm"
          },
          {
            "name": "pkce-challenge",
            "direct": false,
            "version": "5.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "proxy-addr",
            "direct": false,
            "version": "2.0.7",
            "ecosystem": "npm"
          },
          {
            "name": "qs",
            "direct": false,
            "version": "6.15.3",
            "ecosystem": "npm"
          },
          {
            "name": "range-parser",
            "direct": false,
            "version": "1.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "raw-body",
            "direct": false,
            "version": "3.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "require-from-string",
            "direct": false,
            "version": "2.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "router",
            "direct": false,
            "version": "2.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "safer-buffer",
            "direct": false,
            "version": "2.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "send",
            "direct": false,
            "version": "1.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "serve-static",
            "direct": false,
            "version": "2.2.1",
            "ecosystem": "npm"
          },
          {
            "name": "setprototypeof",
            "direct": false,
            "version": "1.2.0",
            "ecosystem": "npm"
          },
          {
            "name": "shebang-command",
            "direct": false,
            "version": "2.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "shebang-regex",
            "direct": false,
            "version": "3.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "side-channel",
            "direct": false,
            "version": "1.1.1",
            "ecosystem": "npm"
          },
          {
            "name": "side-channel-list",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "side-channel-map",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "side-channel-weakmap",
            "direct": false,
            "version": "1.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "statuses",
            "direct": false,
            "version": "2.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "toidentifier",
            "direct": false,
            "version": "1.0.1",
            "ecosystem": "npm"
          },
          {
            "name": "type-is",
            "direct": false,
            "version": "2.1.0",
            "ecosystem": "npm"
          },
          {
            "name": "typescript",
            "direct": false,
            "version": "7.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "undici-types",
            "direct": false,
            "version": "8.3.0",
            "ecosystem": "npm"
          },
          {
            "name": "unpipe",
            "direct": false,
            "version": "1.0.0",
            "ecosystem": "npm"
          },
          {
            "name": "vary",
            "direct": false,
            "version": "1.1.2",
            "ecosystem": "npm"
          },
          {
            "name": "which",
            "direct": false,
            "version": "2.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "wrappy",
            "direct": false,
            "version": "1.0.2",
            "ecosystem": "npm"
          },
          {
            "name": "zod",
            "direct": false,
            "version": "4.4.3",
            "ecosystem": "npm"
          },
          {
            "name": "zod-to-json-schema",
            "direct": false,
            "version": "3.25.2",
            "ecosystem": "npm"
          }
        ],
        "collected": true,
        "truncated": false,
        "total_count": 117,
        "direct_count": 2,
        "indirect_count": 115
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 3,
        "merged_prs": 0,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 2
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "groscy",
          "commits": 80,
          "avatar_url": "https://avatars.githubusercontent.com/u/92256856?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "release.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 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": 10,
            "reason": "update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 3,
            "reason": "dependency not pinned by hash detected -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "a866d48a5db3424652915ff6aa57946a276fb78e",
        "ran_at": "2026-07-27T17:31:25Z",
        "aggregate_score": 5.4,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": true
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-25T20:35:25Z",
      "oldest_open_prs": [
        {
          "number": 3,
          "created_at": "2026-07-18T13:22:31Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 4,
          "created_at": "2026-07-18T13:22:57Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 5,
          "created_at": "2026-07-25T11:47:43Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": null,
      "ci_last_conclusion": "FAILURE",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/groscy/data-loom",
    "host": "github.com",
    "name": "data-loom",
    "owner": "groscy"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 56,
      "inputs": {
        "security": 61,
        "vitality": 69,
        "community": 42,
        "governance": 33,
        "engineering": 76
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "moderate",
        "name": "Vitality",
        "value": 69,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 57,
            "inputs": {
              "commits_last_year": 80,
              "human_commit_share": 1,
              "days_since_last_push": 2,
              "active_weeks_last_year": 5
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 2 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 2
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "5/52 weeks with commits",
                "points": 3.5,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "80 commits in the last year",
                "points": 17.1,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 80
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 88,
            "inputs": {
              "releases_count": 24,
              "latest_release_tag": "v0.13.0",
              "releases_from_tags": true,
              "days_since_latest_release": 6,
              "mean_days_between_releases": 1.6
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "24 version tags (no GitHub releases)",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "version_tags_no_releases",
                    "params": {
                      "count": 24
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 6 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~1.6 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 1.6
                    }
                  }
                ],
                "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": 42,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "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": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 77,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (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": 18,
                "status": "met",
                "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": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 58,
            "inputs": {
              "packages": [
                "@lyric_dev/data-loom"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 3047
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "3,047 downloads/month across npm",
                "points": 46.5,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 3047,
                      "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": "at_risk",
        "name": "Sustainability & Governance",
        "value": 33,
        "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": "critical",
            "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": 1,
            "inputs": {
              "merged_prs": 0,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 2
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "0/2 decided PRs merged",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 0,
                      "decided": 2
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "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": 40,
            "inputs": {
              "followers": 2,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "groscy",
              "public_repos": 15,
              "account_age_days": 1751
            },
            "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": "2 followers of groscy",
                "points": 3.4,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 2,
                      "login": "groscy"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "15 public repos, account ~4 yr old",
                "points": 18.4,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 15
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 4
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@lyric_dev/data-loom"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 6
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 6 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "17 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 17
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 76,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "topics": [
                "claude-code",
                "dashboard",
                "mcp",
                "openspec",
                "roadmap",
                "spec-driven-development"
              ],
              "has_wiki": true,
              "homepage": "https://github.com/groscy/data-loom#readme",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://github.com/groscy/data-loom#readme",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "6 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 6
                    }
                  }
                ],
                "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": 61,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "moderate",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 54,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 5.4
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 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": "update tool detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 3",
                "points": 1.5,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "3 existing vulnerabilities detected",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Matched the npm:@lyric_dev/data-loom@0.13.0 runtime dependency closure — what installing the published package pulls in — 96 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:@lyric_dev/data-loom@0.13.0",
                  "assessed": 96
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 88,
            "inputs": {
              "source": "osv",
              "advisories": 1,
              "affected_packages": 1,
              "assessed_packages": 96,
              "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.15 (moderate 5.9)",
                "points": 13.2,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "@hono/node-server 1.19.15 (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": 96,
              "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
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 54,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.838,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "67 of 80 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 67,
                      "sampled": 80
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 61,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "package-lock.json"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "tsconfig.json"
              ],
              "agent_commit_share": 0.95,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "76 of the last 80 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 76,
                      "sampled": 80
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "dependency automation configured, none observed in the sampled commits",
                "points": 5,
                "status": "partial",
                "details": [
                  {
                    "code": "dependency_bot_config_only",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 98,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 83024,
              "source_files_sampled": 24,
              "oversized_source_files": 1
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "1/24 source files over 60KB",
                "points": 52.7,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 24,
                      "oversized": 1
                    }
                  }
                ],
                "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": [],
  "report_type": "repository",
  "generated_at": "2026-07-27T17:31:30.757942Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/g/groscy/data-loom.svg",
  "full_name": "groscy/data-loom",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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