公开记录
软件健康报告模式 0.26.0 · 指标 1.13.0 · 2026-07-22 15:18 UTC

Rocapine / react-native-onboarding

TypeScript · MDX未检测到许可证★ 2 星标⑂ 1 复刻始于 2025年9月在 GitHub 上查看 ↗

Rocapine/react-native-onboarding 的健康指数为 100 分中的 61 分,处于「中等」区间。 其得分最高的类别是Vitality(89/100),最低的是Community & Adoption(32/100)。 最近一次更新在 5 天前。 近期的大部分工作由 2 位贡献者完成。

61
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

Rocapine组织
2 关注者10 个公开仓库始于 2024年6月

该仓库由组织支持——共同承担、可问责的托管责任,可延续于任何单一维护者之后。

软件包生态系统

按类别列示的指标

活力

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

89优秀 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 5 天前
18/36提交节奏 — 52 周中有 26 周有提交
18/18提交量 — 最近一年 290 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year290
human_commit_share1
days_since_last_push5
active_weeks_last_year26

发布纪律

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

社区与采用

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

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

社区健康

45存在风险
评分方式
22.5/22.5README
0/22.5许可证 — 未检测到许可证文件
18/18CONTRIBUTING 指南
0/13.5行为准则
0/7.2议题模板
0/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template
评分方式
52.2/80月度下载量 — npm 合计每月 8,244 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packages@rocapine/react-native-onboarding, @rocapine/react-native-onboarding-ui
dependents
ecosystemsnpm
total_downloads
monthly_downloads8,244
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

64中等 · 占总体的 24%
评分方式
25.2/54巴士系数 — 2 位贡献者贡献了半数提交
11.4/22.5提交分布 — 头号贡献者编写了 49% 的提交
5.4/13.5贡献者广度 — 4 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 7 contributing companies or organizations
所用输入
bus_factor2
contributors_sampled4
top_contributor_share0.493
评分方式
0/46.8议题解决 — 没有议题或无数据
37.3/38.3PR 接受 — 已裁定的 PR 中 117/120 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs117
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs3
已排除计分(无数据或不适用):议题解决。 其余权重已重新归一化。
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
3.4/25所有者影响力 — Rocapine 有 2 位关注者
11.8/25既往记录 — 10 个公开仓库,账户约 2 年
所用输入
followers2
owner_typeOrganization
is_verified
owner_loginRocapine
public_repos10
account_age_days775
评分方式
25/25已发布且可解析 — npm 上有 2 个软件包
35/35发布时效 — 最近一次发布于 5 天前
20/20版本历史 — 93 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packages@rocapine/react-native-onboarding, @rocapine/react-native-onboarding-ui
ecosystemsnpm
any_deprecated
min_days_since_publish5

工程质量

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

72良好 · 占总体的 20%

工程实践

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

文档

55中等
评分方式
30/30README
0/25文档目录
15/15文档 / 主页站点 — https://react-native-onboarding.pages.dev
0/10仓库描述
0/10主题标签
10/10Wiki
所用输入
topics
has_wiki
homepagehttps://react-native-onboarding.pages.dev
has_readme
has_docs_dir
has_description

安全

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

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

安全态势

37存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.5/2.5CI-Tests — 30 out of 30 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 7 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
0/2.5许可证 — license file not detected
7.5/7.5Maintained — 30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
1/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 2
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — 无数据
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 56 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate3.7
已排除计分(无数据或不适用):signed_releases。 其余权重已重新归一化。

AI 就绪度

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

79良好 · 占总体的 0%
评分方式
45/45代理指令 — CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 100 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share1
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes13,672
评分方式
0/18一条命令的引导启动
22/22自动化测试
11/11Lint / 格式化配置 — eslint.config.js
11/11静态类型检查 — example/tsconfig.json, packages/onboarding-ui/tsconfig.json, packages/onboarding/tsconfig.json, website/tsconfig.json
10/10可复现环境 — lockfile
10/10已体现的代理实践 — 最近 100 次提交中有 52 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
2/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 2
所用输入
has_nix
has_tests
lockfilespackage-lock.json
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configsexample/tsconfig.json, packages/onboarding-ui/tsconfig.json, packages/onboarding/tsconfig.json, website/tsconfig.json
agent_commit_share0.52
toolchain_manifests
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — TypeScript(静态类型)
55/55可控的文件大小 — 采样的 233 个源文件中有 0 个超过 60KB
所用输入
primary_languageTypeScript
largest_source_bytes47,028
source_files_sampled233
oversized_source_files0
评分方式
40/40API 模式(OpenAPI/GraphQL/proto) — openapi.yaml, website/static/openapi.yaml
0/20MCP 服务器
40/40可运行示例 — example
所用输入
example_dirsexample
has_mcp_signal
api_schema_filesopenapi.yaml, website/static/openapi.yaml

关键数据

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

数据采集警告

  • Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token
  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository
  • deps.dev does not index npm:@rocapine/react-native-onboarding@1.59.0; advisories assessed against the repository dependency graph instead

更多细节

OpenSSF Scorecard 3.7 / 10
3.7综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
10CI-Tests30 out of 30 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
10Contributorsproject has 7 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
0Licenselicense file not detected
10Maintained30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
2Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 2
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities56 existing vulnerabilities detected
直接依赖 15
注册表软件包版本约束清单文件
npm@docusaurus/core3.9.1website/package.json
npm@docusaurus/preset-classic3.9.1website/package.json
npm@mdx-js/react^3.0.0website/package.json
npmclsx^2.0.0website/package.json
npmprism-react-renderer^2.3.0website/package.json
npmreact^19.0.0website/package.json
npmreact-dom^19.0.0website/package.json
npmlucide-react-native^0.545.0packages/onboarding-ui/package.json
npmreact-native-gesture-handler>=2.0.0packages/onboarding-ui/package.json
npmreact-native-reanimated>=3.0.0packages/onboarding-ui/package.json
npmreact-native-svg>=13.0.0packages/onboarding-ui/package.json
npmzod^4.1.11packages/onboarding-ui/package.json
npm@react-native-async-storage/async-storage^2.1.0packages/onboarding/package.json
npm@tanstack/react-query^5.64.2packages/onboarding/package.json
npmzod^4.1.11packages/onboarding/package.json
全部依赖 未采集

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 3053,
      "has_wiki": true,
      "homepage": "https://react-native-onboarding.pages.dev",
      "languages": {
        "CSS": 1950,
        "MDX": 192131,
        "HTML": 2312,
        "Shell": 9540,
        "JavaScript": 6875,
        "TypeScript": 903618
      },
      "pushed_at": "2026-07-17T13:27:08Z",
      "created_at": "2025-09-30T12:47:24Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-17T13:27:35Z",
      "description": null,
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": null,
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript",
        "MDX"
      ]
    },
    "owner": {
      "blog": "rocapine.com",
      "name": "Rocapine",
      "type": "Organization",
      "login": "Rocapine",
      "company": null,
      "location": "France",
      "followers": 2,
      "avatar_url": "https://avatars.githubusercontent.com/u/172039437?v=4",
      "created_at": "2024-06-07T12:11:05Z",
      "is_verified": null,
      "public_repos": 10,
      "account_age_days": 775
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [
        {
          "tag": "v1.59.0",
          "kind": "minor",
          "published_at": "2026-07-17T13:27:09Z"
        },
        {
          "tag": "v1.58.0",
          "kind": "minor",
          "published_at": "2026-07-16T15:06:11Z"
        },
        {
          "tag": "v1.57.4",
          "kind": "patch",
          "published_at": "2026-07-09T12:47:16Z"
        },
        {
          "tag": "v1.57.3",
          "kind": "patch",
          "published_at": "2026-07-09T10:01:46Z"
        },
        {
          "tag": "v1.57.2",
          "kind": "patch",
          "published_at": "2026-07-09T09:53:04Z"
        },
        {
          "tag": "v1.57.1",
          "kind": "patch",
          "published_at": "2026-07-09T09:27:16Z"
        },
        {
          "tag": "v1.57.0",
          "kind": "minor",
          "published_at": "2026-07-01T08:50:07Z"
        },
        {
          "tag": "v1.56.0",
          "kind": "minor",
          "published_at": "2026-06-30T09:55:22Z"
        },
        {
          "tag": "v1.55.1",
          "kind": "patch",
          "published_at": "2026-06-26T07:47:14Z"
        },
        {
          "tag": "v1.55.0",
          "kind": "minor",
          "published_at": "2026-06-25T15:51:48Z"
        },
        {
          "tag": "v1.54.0",
          "kind": "minor",
          "published_at": "2026-06-23T16:19:45Z"
        },
        {
          "tag": "v1.53.0",
          "kind": "minor",
          "published_at": "2026-06-22T09:56:59Z"
        },
        {
          "tag": "v1.52.0",
          "kind": "minor",
          "published_at": "2026-06-22T09:38:01Z"
        },
        {
          "tag": "v1.51.2",
          "kind": "patch",
          "published_at": "2026-06-22T08:48:36Z"
        },
        {
          "tag": "v1.51.1",
          "kind": "patch",
          "published_at": "2026-06-22T08:20:58Z"
        },
        {
          "tag": "v1.51.0",
          "kind": "minor",
          "published_at": "2026-06-22T07:52:43Z"
        },
        {
          "tag": "v1.50.1",
          "kind": "patch",
          "published_at": "2026-06-19T15:15:40Z"
        },
        {
          "tag": "v1.50.0",
          "kind": "minor",
          "published_at": "2026-06-19T13:17:04Z"
        },
        {
          "tag": "v1.49.1",
          "kind": "patch",
          "published_at": "2026-06-19T12:45:00Z"
        },
        {
          "tag": "v1.49.0",
          "kind": "minor",
          "published_at": "2026-06-19T09:50:10Z"
        },
        {
          "tag": "v1.48.0",
          "kind": "minor",
          "published_at": "2026-06-19T09:15:21Z"
        },
        {
          "tag": "v1.47.0",
          "kind": "minor",
          "published_at": "2026-06-19T07:57:10Z"
        },
        {
          "tag": "v1.46.0",
          "kind": "minor",
          "published_at": "2026-06-18T14:39:51Z"
        },
        {
          "tag": "v1.45.0",
          "kind": "minor",
          "published_at": "2026-06-18T13:54:42Z"
        },
        {
          "tag": "v1.44.7",
          "kind": "patch",
          "published_at": "2026-06-18T13:13:27Z"
        },
        {
          "tag": "v1.44.6",
          "kind": "patch",
          "published_at": "2026-06-18T09:35:10Z"
        },
        {
          "tag": "v1.44.5",
          "kind": "patch",
          "published_at": "2026-06-16T13:40:42Z"
        },
        {
          "tag": "v1.44.4",
          "kind": "patch",
          "published_at": "2026-06-16T09:06:14Z"
        },
        {
          "tag": "v1.44.3",
          "kind": "patch",
          "published_at": "2026-06-16T08:30:33Z"
        },
        {
          "tag": "v1.44.2",
          "kind": "patch",
          "published_at": "2026-06-15T16:14:09Z"
        },
        {
          "tag": "v1.44.1",
          "kind": "patch",
          "published_at": "2026-06-15T14:00:42Z"
        },
        {
          "tag": "v1.44.0",
          "kind": "minor",
          "published_at": "2026-06-11T14:03:20Z"
        },
        {
          "tag": "v1.43.0",
          "kind": "minor",
          "published_at": "2026-06-11T09:05:17Z"
        },
        {
          "tag": "v1.42.1",
          "kind": "patch",
          "published_at": "2026-06-11T08:27:46Z"
        },
        {
          "tag": "v1.42.0",
          "kind": "minor",
          "published_at": "2026-06-10T16:00:55Z"
        },
        {
          "tag": "v1.41.2",
          "kind": "patch",
          "published_at": "2026-06-10T08:05:39Z"
        },
        {
          "tag": "v1.41.1",
          "kind": "patch",
          "published_at": "2026-06-09T15:22:14Z"
        },
        {
          "tag": "v1.41.0",
          "kind": "minor",
          "published_at": "2026-06-09T15:16:35Z"
        },
        {
          "tag": "v1.40.0",
          "kind": "minor",
          "published_at": "2026-06-09T15:01:36Z"
        },
        {
          "tag": "v1.39.0",
          "kind": "minor",
          "published_at": "2026-06-08T16:00:20Z"
        },
        {
          "tag": "v1.38.2",
          "kind": "patch",
          "published_at": "2026-06-08T13:57:18Z"
        },
        {
          "tag": "v1.38.1",
          "kind": "patch",
          "published_at": "2026-06-08T10:50:25Z"
        },
        {
          "tag": "v1.38.0",
          "kind": "minor",
          "published_at": "2026-06-08T10:17:30Z"
        },
        {
          "tag": "v1.37.0",
          "kind": "minor",
          "published_at": "2026-06-08T09:29:22Z"
        },
        {
          "tag": "v1.36.2",
          "kind": "patch",
          "published_at": "2026-06-08T08:33:55Z"
        },
        {
          "tag": "v1.36.1",
          "kind": "patch",
          "published_at": "2026-06-04T15:27:28Z"
        },
        {
          "tag": "v1.36.0",
          "kind": "minor",
          "published_at": "2026-06-04T11:33:31Z"
        },
        {
          "tag": "v1.35.0",
          "kind": "minor",
          "published_at": "2026-06-02T14:20:04Z"
        },
        {
          "tag": "v1.34.1",
          "kind": "patch",
          "published_at": "2026-06-02T13:39:48Z"
        },
        {
          "tag": "v1.34.0",
          "kind": "minor",
          "published_at": "2026-06-02T09:57:23Z"
        },
        {
          "tag": "v1.33.0",
          "kind": "minor",
          "published_at": "2026-06-01T16:01:43Z"
        },
        {
          "tag": "v1.32.0",
          "kind": "minor",
          "published_at": "2026-06-01T14:01:05Z"
        },
        {
          "tag": "v1.31.0",
          "kind": "minor",
          "published_at": "2026-06-01T12:28:58Z"
        },
        {
          "tag": "v1.30.0",
          "kind": "minor",
          "published_at": "2026-06-01T08:10:18Z"
        },
        {
          "tag": "v1.29.0",
          "kind": "minor",
          "published_at": "2026-05-29T13:41:40Z"
        },
        {
          "tag": "v1.28.0",
          "kind": "minor",
          "published_at": "2026-05-29T09:44:42Z"
        },
        {
          "tag": "v1.27.0",
          "kind": "minor",
          "published_at": "2026-05-29T08:57:34Z"
        },
        {
          "tag": "1.1.0",
          "kind": "minor",
          "published_at": "2026-01-09T10:50:35Z"
        },
        {
          "tag": "1.0.1",
          "kind": "patch",
          "published_at": "2026-01-09T10:42:12Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "8a0267bb1407ed5aa8abd78b9273ba10dc9c7be8",
          "body": "…123)\n\n* ✨ feat: onboarding start/end nodes + onComplete completion callback\n\nFormalize the flow as an explicit id-based graph with studio-authored\nentry/exit semantics. All additive and backward compatible.\n\n- metadata.startStepId (optional, unique): entry point decoupled from\n  array position. New\n[…]\n (ends the flow), and validation no longer flags it.\n- page-types.mdx: added a Start & End nodes tip (startStepId + \"__END__\").\n\nClaude-Session: https://claude.ai/code/session_01VUXHpGxRqW5MM3bt7onP9o",
          "is_bot": false,
          "headline": "✨ feat: onboarding start/end nodes + onComplete callback — v1.59.0 (#…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-07-17T13:26:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d8dceb8aa8ecac0004bcf46a930a2dd2c2336ddc",
          "body": "…58.0 (#121)\n\n* ✨ feat(composable): setVariable setter in custom Button actions — v1.58.0\n\nCustom action handlers (`{ type: \"custom\" }`) now receive a `setVariable`\nsetter alongside `variables`, so host-registered handlers can write back into\nthe ComposableScreen variable context — the imperative co\n[…]\nons'\n  `variables` in the same chain (press-time snapshot), only to rendering and the\n  following \"continue\" branch.\n\nClaude-Session: https://claude.ai/code/session_01MVCJefYKiW4DyzA2tkgsLs\n\n---------",
          "is_bot": false,
          "headline": "✨ feat(composable): setVariable setter in custom Button actions — v1.…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-07-16T15:05:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "950e714735f197e3612134f446325ed62f529dbc",
          "body": "…lash (#120)\n\nOnboarding images flashed / re-decoded every time a screen was shown.\nRoot cause: both expo-image render sites (imageSource.renderRaster and\nProgressiveBlurImageElement) and the preloadAssets prefetch used\nexpo-image's default cachePolicy \"disk\", which is memory-less — every\nimage-view\n[…]\n OnboardingProvider\ncalls preloadAssets on load) — only the cache policy was missing.\n\nBumps both packages + plugin to 1.57.4.\n\n\nClaude-Session: https://claude.ai/code/session_01JiC2wJTHZDNzAoqvwjMTaJ",
          "is_bot": false,
          "headline": "🐛 fix(composable): cache onboarding images in memory to stop reload f…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-07-09T12:44:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "265cffcb48070f65b8e445ba0f2233b6c91cc0b4",
          "body": "…ROC-2984 #1) (#119)\n\n* 🐛 fix(composable): bordered rounded images fill their frame cleanly\n\nROC-2984 finding #1. On the week-good / week-bad ComposableScreen steps the\noption photos left a white gap at the corners of their white card frame\n(borderRadius:24, borderWidth:2, cover, drop shadow).\n\nRoot\n[…]\not padding. A border + padding + rounded Image (with a\nshadow/gradient) would inset the raster past this radius and reintroduce a\nsmall corner gap. Unusual on a photo element; documented, not handled.",
          "is_bot": false,
          "headline": "🐛 fix(composable): bordered rounded images fill their frame cleanly (…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-07-09T09:55:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "54ac8914d4d438e5abc137bbea8577876d70654a",
          "body": "…creen background (ROC-2984 #2) (#118)\n\n* 🐛 fix(composable): keyboard-avoiding padding no longer reveals grey screen background\n\nROC-2984 finding #2. On a ComposableScreen with a text input (e.g. the\n\"How should we call you?\" name step), a grey band appeared between the\nContinue button and the keybo\n[…]\n template background shows through.\n- Document the known gap in the CHANGELOG: a gradient-only root\n  (backgroundGradient, no solid backgroundColor) is not yet covered.\n\ntype:check + build (ui) green.",
          "is_bot": false,
          "headline": "🐛 fix(composable): keyboard-avoiding padding no longer reveals grey s…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-07-09T09:49:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "988689f001f5678bee9bb3c97ab6a0054da99878",
          "body": "…(fake-loader fix) (#117)\n\n* 🐛 fix(composable): renderWhen reacts to live ProgressIndicator sweep\n\nA stepped loader — one autoplay ProgressIndicator driving sibling\ncheckmarks via renderWhen thresholds (loaderProgress gte 33 / 67 / 100)\n— stayed on the first step for the whole sweep, then flipped ev\n[…]\nate changelogs and docs\n\nPatch release for the ComposableScreen loader renderWhen fix (#117).\nUI-only change; headless kept in lockstep. Plugin manifest realigned to\nthe SDK version (1.56.0 → 1.57.1).",
          "is_bot": false,
          "headline": "🐛 fix(composable): renderWhen reacts to live ProgressIndicator sweep …",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-07-09T09:26:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "198202ef25ff31163f7f1d42aec7049c0a8ccf8a",
          "body": null,
          "is_bot": false,
          "headline": "skill: use npx expo install and add reanimated (#94)",
          "author_name": "Sammy Teillet",
          "author_login": "Samox",
          "committed_at": "2026-07-03T10:21:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c680afe3629da88e4e5de6df4963e3f005e937af",
          "body": "…1.57.0) (#116)\n\n* perf(composable): stop full-tree re-render on every variable write\n\nThe ComposableScreen runtime renderer re-rendered the entire element tree\non every variable write (Input keystroke, Carousel page change,\nProgressIndicator autoplay boundary tick), rebuilding every leaf's inline\ns\n[…]\nsableScreen render-performance refactor (Changed + Fixed).\nHeadless: version-only lockstep bump note. Website changelog pages import\nthese CHANGELOG.md files directly, so no separate docs edit needed.",
          "is_bot": false,
          "headline": "perf(composable): stop full-tree re-render on every variable write (v…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-07-01T08:49:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f8617fd961a6fd94e8d5969fe62d8582cf5fc38f",
          "body": "…l, loop + follow-cursor (v1.56.0) (#115)\n\n* ✨ feat(composable): TypewriterText element — per-char staggered reveal, loop + follow-cursor\n\nNew ComposableScreen UIElement that reveals text one character at a time.\nEach character mounts its own react-native-reanimated entering animation\n(delay = delay\n[…]\n loop no longer re-keys characters mid-spring. [#3,#4]\n- Split the string once (buildGroups → flattenGroups), reused by both modes,\n  rather than calling Array.from(text) on every gen/typed tick. [#5]",
          "is_bot": false,
          "headline": "✨ feat(composable): TypewriterText element — per-char staggered revea…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-30T09:54:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b64fbb81ab5b6042d195c6e04fb25fa4bcedcfab",
          "body": "…ers — v1.55.1 (#114)\n\nAdd `justifyContent` / `alignItems` to the `ZStack` element so each\ncontent-sized layer can be anchored within the full-bleed stack (e.g. a\nfloating bottom CTA with `justifyContent: \"flex-end\"`). A layer that fills\nvia flex/height ignores them; the per-child wrapper stays `box\n[…]\ning.\n\n- headless + UI element schema/type\n- ZStackElement renderer applies both to each absolute child wrapper\n- docs (page-types.mdx) + zstack example demo\n- CHANGELOGs + version bump 1.55.0 → 1.55.1",
          "is_bot": false,
          "headline": "✨ feat(composable): ZStack justifyContent/alignItems for floating lay…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-26T07:46:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f738a1f1d4064c2a6930f24d37ea3dcab14c8db4",
          "body": "GradientBackground is now a linear|radial discriminated union. Radial\nrenders via react-native-svg (bundled), sizes like the linear/plain-View\npaths. Adds examples, docs, schema mirror in both packages.",
          "is_bot": false,
          "headline": "✨ feat(composable): radial backgroundGradient option — v1.55.0 (#113)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-25T15:51:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b321781687843c50c20dedcbec17629ae61f41e9",
          "body": "Opt into app-controlled cache persistence. Default behavior unchanged\n(stale-while-revalidate under \"rocapine-onboarding-studio\"). Passing\ncacheKey persists payload under \"rocapine-onboarding-sdk-{cacheKey}\",\nserves cache-first with no background revalidation, and is part of the\nReact Query key. Adds OnboardingStudioClient.clearCache(), exports\ngetOnboardingCacheKey / DEFAULT_ONBOARDING_CACHE_KEY. UI bumped in\nlockstep (no UI changes).",
          "is_bot": false,
          "headline": "✨ feat(headless): cacheKey client option + clearCache() — v1.54.0 (#111)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-23T16:18:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b5d7ca3142a830256a0c3348ccfb03aed354b58c",
          "body": "…110)\n\nAdd `format` prop (Intl.DateTimeFormatOptions subset) to the DatePicker\nelement so authors control the displayed/stored label across date/time/\ndatetime modes (12h vs 24h, day/month/year style, etc.). Forwarded to\ntoLocale*String per mode; defaults unchanged when omitted. Also thread\n`locale` into the label formatter (previously ignored).",
          "is_bot": false,
          "headline": "✨ feat(composable): DatePicker configurable label format — v1.53.0 (#…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-22T09:56:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "165d65109bde968c4bb1abf15ae9d8d8da465c8e",
          "body": "… v1.52.0 (#109)\n\n* ✨ feat(progressbar): publish measured header height so step content offsets correctly\n\nThe host-rendered ProgressBar is absolute-positioned, so its real footprint\n(top inset + bar + padding) was never known to SDK content — layout relied on a\nhardcoded `paddingTop: 40` guess and \n[…]\nge — they already render <ProgressBar/>, which now\nself-publishes.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📦 chore(release): bump to 1.52.0, update changelogs and docs",
          "is_bot": false,
          "headline": "✨ feat(progressbar): measured header height for correct step layout —…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-22T09:37:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c6445a138a72a60365b8b41ff5eed0eebd07675b",
          "body": "…eckboxGroup container — v1.51.2 (#108)\n\nGroup container style only threaded width/height, so flex:1 on a group was a\nno-op — groups sized to content and image-grid columns rendered unequal. Apply\nflex/flexGrow/flexShrink from BaseBoxProps so a flex:1 group fills its parent\nand columns go fluid without fixed-% widths.",
          "is_bot": false,
          "headline": "🐛 fix(composable): thread flex/flexGrow/flexShrink into RadioGroup/Ch…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-22T08:47:52Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "076cc174518cba817e186d42f78038a74cdb573b",
          "body": "…l with itemAlignItems — v1.51.1 (#107)\n\ncontentNode now flexGrow:1 + alignSelf:stretch so it fills the item card;\nitemAlignItems:\"center\"/\"flex-end\" centers/right-aligns in the card instead\nof within a content-width block. Label/subLabel <Text> get matching textAlign\nso multi-line copy aligns. Default (unset) still left-aligns.",
          "is_bot": false,
          "headline": "🐛 fix(composable): center RadioGroup/CheckboxGroup item label/subLabe…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-22T08:20:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9c2ffc471b42d0fce4887ed14fc10679e43c5854",
          "body": "…ignment/gap — v1.51.0 (#106)\n\nAdd optional per-item `image` ({url,width?,height?,aspectRatio?,resizeMode?,\nborderRadius?}) to RadioGroup/CheckboxGroup items, rendered above the\nlabel/sub-label as a column. Add group-level `itemAlignItems` (cross-axis,\ndefault center) and `itemGap` (inner spacing, d\n[…]\nrendering into a shared imageSource helper\nreused by ImageElement and both groups.\n\nMirrors headless schema + UI renderers, example payloads, skill/website docs.\nBump both packages + plugin to 1.51.0.",
          "is_bot": false,
          "headline": "✨ feat(composable): RadioGroup/CheckboxGroup per-item image + item al…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-22T07:51:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "474e3c0f7c495324d6ddf7d4566380b76f4e1879",
          "body": "…th tickPosition end — v1.50.1 (#105)\n\nItem row had no justifyContent, so label + tick clumped left instead of\nthe tick sitting at the full-width card's right edge. Apply\njustifyContent: \"space-between\" when tickPosition === \"end\".",
          "is_bot": false,
          "headline": "🐛 fix(composable): pin RadioGroup/CheckboxGroup tick to right edge wi…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-19T15:14:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "01bef817fab19fcbf63590583917fb0fb0591194",
          "body": "…zation — v1.50.0 (#104)\n\nAdd tick placement (tickPosition start/end), per-state tick styling\n(tickColor / tickSelectedColor / tickBorderRadius / tickSize), and an\noptional per-item subLabel with state-aware styling (itemSubLabel* +\nitemSelectedSubLabelColor) to both RadioGroup and CheckboxGroup.\n\nt\n[…]\n zod), onboarding-ui (renderers), the\nLLM JSON schemas, examples, docs (page-types.mdx) and plugin skills.\nBumps both SDK packages to 1.50.0 + CHANGELOGs, and plugin.json\n(1.49.0 → 1.50.0, was stale).",
          "is_bot": false,
          "headline": "✨ feat(composable): RadioGroup/CheckboxGroup tick + sub-label customi…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-19T13:16:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "545a857fe4f1a5e698617f2e984d171e9cd48575",
          "body": "* 🐛 Fix Carousel active dot sizing not applied\n\nComposableScreen Carousel used Pagination.Basic, which sizes each dot's\nbox from dotStyle only (overflow:hidden) and never applies\nactiveDotStyle width/height — active resizing is a commented-out TODO in\nreact-native-reanimated-carousel. So activeDotWi\n[…]\nctiveDotStyle), so the swap is type-identical. Drop the now\nredundant overflow:\"hidden\".\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n* 📦 chore(release): bump to 1.49.1, update changelogs",
          "is_bot": false,
          "headline": "🐛 Fix ComposableScreen Carousel active dot sizing — v1.49.1 (#103)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-19T12:44:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5514683a6b844c611ba39b43b98dc481274fdb86",
          "body": "….0 (#102)\n\n* ✨ Add customizable Carousel pagination dots — v1.48.0\n\nCarousel step payload gains an optional `pagination` object controlling dot\ncolor, active/inactive width & height, gap, vertical placement (top/bottom),\nmargins, and visibility. Defaults reproduce the previous hardcoded styling, so\n[…]\ne, default to dot size), dotsPosition (top/bottom), and\ndotsMarginBottom. Renderer applies active size to Pagination.Basic and renders\nthe dot row above or below the carousel. Examples + docs updated.",
          "is_bot": false,
          "headline": "✨ Active-dot sizing + placement for ComposableScreen Carousel — v1.49…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-19T09:49:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c1c1c2d1dded197b0f9a8a353d007dd93bf81dd9",
          "body": "* ✨ Add customizable Carousel pagination dots — v1.48.0\n\nCarousel step payload gains an optional `pagination` object controlling dot\ncolor, active/inactive width & height, gap, vertical placement (top/bottom),\nmargins, and visibility. Defaults reproduce the previous hardcoded styling, so\nexisting onboardings are unchanged.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 🔖 Bump claude-plugin to 1.48.0 + document page-type schema mirroring",
          "is_bot": false,
          "headline": "✨ Add customizable Carousel pagination dots — v1.48.0 (#101)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-19T09:14:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7b572fc6cb62a59f3d88ac48bf419dc839eae171",
          "body": "…(#100)\n\n* ♻️ Decouple SDK packages from expo-router via injectable navigation adapter\n\nNavigation is now dependency-injected. Both packages no longer hard-depend on\nexpo-router; it becomes an optional peer with a lazy-loaded default adapter so\nexisting apps keep working with zero config.\n\n- Add Onb\n[…]\nion with expo-router default vs\n  custom adapter injection; add navigation to the peer-dep list\n- setup-headless-sdk: note expo-router is an optional peer, adapter injection\n  for non-expo-router apps",
          "is_bot": false,
          "headline": "♻️ Decouple SDK from expo-router via injectable navigation — v1.47.0 …",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-19T07:56:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2182aab381eeb3561956e7fdc887d9ee55a92447",
          "body": "* ✨ Add DrawingPad ComposableScreen element (freehand draw/signature → variables)\n\nGeneric freehand drawing / signature canvas as a composable UIElement.\nMulti-stroke capture via react-native-gesture-handler + Skia paths; on each\ncompleted stroke it serializes the drawing into runtime variable(s):\n-\n[…]\n look\n(top-right, 32px, neutral.higher bg, opposite ✕). Mirrored in headless\ntype+schema and the UI renderer; docs, CHANGELOGs, and the example screen\nupdated. Folded into the unreleased 1.46.0 entry.",
          "is_bot": false,
          "headline": "✨ Add DrawingPad ComposableScreen element — v1.46.0 (#98)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-18T14:39:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f7add66cbe78b4f36a909a700ef9f5acd49ddc74",
          "body": "* ✨ Add Slider UIElement to ComposableScreen\n\nContinuous numeric input bound to a variable (stored as float string,\nkind:\"float\"), mirroring the Input/RadioGroup stateful pattern. Renders\nvia the optional @react-native-community/slider peer dep, degrading to an\nempty box when absent.\n\n- headless: Sl\n[…]\ncom>\n\n* 🐛 Snap Slider value to step grid, trim float32 noise\n\nNative slider emits raw float32 (0.10000000149011612). Round to the\nstep grid and trim trailing float noise before storing the variable so",
          "is_bot": false,
          "headline": "✨ Add Slider UIElement to ComposableScreen — v1.45.0 (#97)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-18T13:53:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c031b23a650b69f93c2e3ea7f8d3c42482b8baba",
          "body": "…— v1.44.7 (#96)\n\n* 🐛 Fix gradient elements filling the screen in flex/ZStack containers — v1.44.7\n\nThe ComposableScreen gradient render path forced an inner `flex: 1` (GradientBox\n+ inner view) while the non-gradient path was content-sized. Inside a ZStack or\nflex container that `flex: 1` grabbed t\n[…]\nng: a renderer's gradient branch must size identically\nto its non-gradient branch. Hardcoded inner `flex: 1` in the gradient path made\ncontent-sized elements fill the screen in ZStack/flex containers.",
          "is_bot": false,
          "headline": "🐛 Fix gradient elements filling the screen in flex/ZStack containers …",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-18T13:12:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2133cf90215a9d2a22199dcf82fb3dc97d72d19e",
          "body": "… (#95)\n\n* 🐛 Fix asset prefetch skipping all ComposableScreen elements — v1.44.6\n\nThe extractAssetUrls walker recursed into `props.children`, but the UIElement\nschema stores `children` as a top-level sibling of `props`. Container recursion\nnever fired, so every nested Image/Video/Lottie/Rive asset w\n[…]\ntext) <noreply@anthropic.com>\n\n* 🔖 Sync onboarding-ui + claude plugin to v1.44.6\n\nVersion-sync bump to match the headless v1.44.6 ComposableScreen asset prefetch\nfix. No UI or plugin behavior changes.",
          "is_bot": false,
          "headline": "🐛 Fix asset prefetch skipping all ComposableScreen elements — v1.44.6…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-18T09:34:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4a8f5360aeea5877270bdf85b3e1de1590b3de15",
          "body": "….44.5 (#93)\n\nSeveral autoplay linear ProgressIndicator bars on one screen (e.g. a\n\"curating…\" loader) painted empty for early-finishing bars while only the\nlast stayed filled — though every bar's bound variable reached its max\n(eq-max checkmarks stayed on). Each bar wrote its variable every step\n(~\n[…]\niably on Fabric).\n- Seed autoplay progress from the bound variable on mount so a completed bar is\n  restored after a subtree remount.\n- Add deps arrays to the animated worklets to reduce mapper churn.",
          "is_bot": false,
          "headline": "🐛 Fix staggered autoplay ProgressIndicator loader bars resetting — v1…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-16T13:39:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a98f5e027972f5fadc4868bf38ccbeee8b76e97c",
          "body": "* 🐛 Fall back to theme default for empty/null fontFamily — v1.44.4\n\n`resolveInheritedFontFamily` only returned `theme.typography.defaultFontFamily`\nwhen an element's `fontFamily` was `undefined` or `\"inherit\"`. The CMS emits an\nempty string (\"\") or null for \"no font selected\", which passed through\nu\n[…]\nDisplay-Italic) was never selected — text\ngot synthetic italic over the upright face. Thread fontStyle into resolution so\nthe real italic variant is picked when registered, matching Text/AnimatedText.",
          "is_bot": false,
          "headline": "🐛 Fall back to theme default for empty/null fontFamily — v1.44.4 (#92)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-16T09:05:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1aec2fee48f22b18f46583f84d52c6167bd25281",
          "body": "The production onboarding query was cache-first with `staleTime: Infinity`: it\nreturned the AsyncStorage cache and never called the edge function again, and\ncached whatever `getSteps` returned — including the offline fallback. So a\nsingle first-launch fetch failure (timeout / offline / cold-start) c\n[…]\nrst paint while\n  refreshing from the network in the background, so studio re-deploys\n  propagate and a stale cache recovers.\n\nBump both packages + plugin to 1.44.3, update changelogs, add query test.",
          "is_bot": false,
          "headline": "🐛 Fix production onboarding pinned to offline fallback — v1.44.3 (#91)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-16T08:29:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "27b755ad8e6b31f4d66921da357f181cbd0bea52",
          "body": "….2 (#90)\n\nTwo font bugs in ComposableScreen font handling:\n\n1. Italic variants were dropped. The runtime registry keyed variants by\n   weight only, so a 700-italic face was overwritten by 700-normal — any\n   fontStyle:\"italic\" text rendered upright. Variants are now keyed by\n   weight+style, both f\n[…]\ntem font with\n   fontWeight; on Android the bundled faces register normally.\n\nAdds isSystemFontFamily / normalizeStyle exports + FontStyleKey /\nRegisteredFace types, and a resolveFontFamily unit test.",
          "is_bot": false,
          "headline": "🐛 Fix dropped italic faces + iOS SF Pro system-font collision — v1.44…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-15T16:13:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1716830bd8179367a7055758e201eaddcb566b77",
          "body": "buildRegisteredName now derives the registered font name from the font\nfile URL (base name minus directory/query/extension) instead of a\nsynthesized <family>-<weight> string.",
          "is_bot": false,
          "headline": "📦 Register runtime fonts under PostScript name — v1.44.1 (#89)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-15T13:59:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "defda305ec8274430f26590fa8f1cc369cd3c7bc",
          "body": "* ✨ keyboardVerticalOffset prop on OnboardingPage → ComposableScreen KeyboardAvoidingView\n\nHosts that render OnboardingPage below a fixed header push the view down,\nso the renderer's KeyboardAvoidingView (behavior=padding) under-compensates\nby exactly the header height and the bottom CTA stays under\n[…]\nrough\nOnboardingPage into the ComposableScreen KeyboardAvoidingView (default 0).\n\nCo-Authored-By: Claude Fable 5 <noreply@anthropic.com>\n\n* 📦 chore(release): bump to 1.44.0, update changelogs and docs",
          "is_bot": false,
          "headline": "✨ keyboardVerticalOffset prop on OnboardingPage — v1.44.0 (#88)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-11T14:02:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c09796110415a81bcc4e0fb1b7881be5e2f094a1",
          "body": "…3.0 (#87)\n\nAdd optional blurAppear { delay?, duration?, easing? } on ProgressiveBlurImage.\nSharp base image renders immediately; the masked-blur + tint layer fades in\n(opacity 0→1) after delay over duration, via a reanimated wrapper reusing the\nshared EASING_MAP. Omitting it keeps the legacy static-on-mount blur. Degraded\nscrim fallback unaffected.",
          "is_bot": false,
          "headline": "✨ ProgressiveBlurImage blurAppear — delayed blur-layer fade-in — v1.4…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-11T09:04:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "721772083d775c6200097f8ca07a54c68215f9fa",
          "body": "* 🐛 Forward flex/flexShrink/flexGrow on ButtonElement\n\nButtonElement dropped the flex BaseBoxProps fields in both outer\nAnimated.View branches (gradient + default), so a Button with flex:1\nalways sized to its content. Forward eff.flex/flexShrink/flexGrow\nalongside width/alignSelf so equal-width/prop\n[…]\ntons work\ninside an XStack. alignSelf \"stretch\" default unchanged.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📦 chore(release): bump to 1.42.1, update changelogs and docs",
          "is_bot": false,
          "headline": "🐛 Fix ButtonElement ignoring flex prop — v1.42.1 (#86)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-11T08:27:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4c1e0a5a39a669107b9a28f419a67909034c2fa6",
          "body": "* ✨ Per-item shadow props on RadioGroup + CheckboxGroup items\n\nAdd itemShadowColor/itemShadowOffset/itemShadowOpacity/itemShadowRadius/\nitemElevation to RadioGroup and CheckboxGroup (headless schema + UI mirror).\nEach item row spreads buildShadowStyle so authors can give radio/checkbox\nitems a per-i\n[…]\nop shadow. Mirrors docs (page-types, customize skill) and\nexample payloads.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📦 chore(release): bump to 1.42.0, update changelogs",
          "is_bot": false,
          "headline": "✨ Per-item shadow on RadioGroup + CheckboxGroup — v1.42.0 (#85)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-10T16:00:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "43548840de86ba0df7e68dd104ac6bd7e6c142fe",
          "body": "* 🐛 Apply shadow* props on XStack/YStack/ZStack containers\n\nbuildShadowStyle was only wired into ButtonElement + ImageElement, so\nshadowColor/Offset/Opacity/Radius/elevation on Stack containers were\nsilently dropped. Spread buildShadowStyle(p) into both StackElement and\nZStackElement style objects. \n[…]\n 📦 chore(release): bump to 1.41.2, update changelogs and docs\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📝 Document buildShadowStyle must be spread per container renderer",
          "is_bot": false,
          "headline": "🐛 Apply shadow* props on XStack/YStack/ZStack containers — v1.41.2 (#84)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-10T08:04:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "666b3e6e9bb9ea1d212efd5b8e7cf0f5c54e5090",
          "body": "…v1.41.1 (#83)\n\n* 🐛 Apply static transform from frame 0 when an element also has an entering animation\n\nReanimated's entering/exiting/layout builders take over the host view's\ntransform for the duration of the transition, so a static `transform` placed on\nthe same AnimatedBox view was suppressed unt\n[…]\ncated \"Entering + Transform\" example screen demonstrating the fix.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📦 chore(release): bump to 1.41.1, update changelogs and docs",
          "is_bot": false,
          "headline": "🐛 Apply static transform from frame 0 alongside entering animation — …",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-09T15:21:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d30f31e7beb303d6e54eac000f585a7ee35a15fa",
          "body": "… (#82)\n\nAdd optional `autoFocus?: boolean` to the ComposableScreen Input element\n(headless schema + UI mirror). When true, the TextInput focuses on mount and\nthe soft keyboard opens automatically (native RN TextInput behavior). Defaults\nto false.\n\n- Headless type + Zod schema, UI mirror type/schema\n[…]\n composable-screen.tsx demo)\n- Docs: page-types.mdx Input table, compose-screen-builder (moved to supported),\n  create-step-json name-input archetype\n- Bump both packages 1.39.0 -> 1.40.0 + CHANGELOGs",
          "is_bot": false,
          "headline": "✨ Input autoFocus prop — focus on mount + open keyboard — SDK v1.40.0…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-09T15:13:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9fa894a92e11b229a54e210ec8f8f51143a3172f",
          "body": "Warm every remote image/video/Lottie/Rive/SVG asset from the onboarding\npayload right after fetch, so later screens render without a load flash.\nFully non-blocking (never gates first render) and always on (no config).\n\n- extractAssetUrls: pure walk of ComposableScreen element trees +\n  MediaContent/\n[…]\nst.\n- Hooked into OnboardingDataGate via a once-per-payload effect.\n- expo-image added as optional peer dep of the headless package.\n- Unit tests for extraction (kinds, recursion, dedupe, robustness).",
          "is_bot": false,
          "headline": "✨ Background asset preloader for onboarding — SDK v1.40.0 (#81)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-09T15:00:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b34e71f1eb4aaf32587c5978d5703811ddee3d2a",
          "body": "….0 (#80)\n\n* ✨ AnimatedText UIElement — UI-thread count-up, zero re-renders (SDK v1.39.0)\n\nAdd an `AnimatedText` ComposableScreen element: a number that count-animates\n`from`→`to` and renders as formatted text. The animation runs entirely on the\nUI thread (reanimated) and writes straight into a nati\n[…]\nen-runtime.md: the zero-re-render animated number/text pattern\n  (AnimatedTextInput + useAnimatedProps), including the defaultValue-in-worklet\n  gotcha that makes a finished count snap back to `from`.",
          "is_bot": false,
          "headline": "✨ AnimatedText UIElement + ProgressIndicator native label — SDK v1.39…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-08T15:59:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7fcf61a47be6e24e660c752cb4c99136ff0ce5f7",
          "body": "…estart on re-render (v1.38.2) (#79)\n\nAnimatedBox rebuilt its entering/exiting/layout reanimated builders inline on\nevery render, handing Animated.View a fresh `entering` instance each time and\nre-firing the entry transition. An autoplay ProgressIndicator writes its bound\nvariable each step → re-renders the whole ComposableScreen tree → every\nsibling's entry animation reloaded. Builders are now memoized on their stable\nspec objects (from the memoized parsed step).",
          "is_bot": false,
          "headline": "🐛 Memoize AnimatedBox transition builders so entry animations don't r…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-08T13:56:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7792cd4a6057056c97c25b3fab2487994f323a66",
          "body": "…ee (v1.38.1) (#78)\n\n* 🐛 Fix excessive re-renders in Loader animations + ComposableScreen tree\n\n- CircularProgress: round inside useAnimatedReaction reader + prev-guard + deps\n  array. Was firing setPercentage every frame (~60×/s re-render) and rebuilding\n  the mapper on every render (no deps). Now \n[…]\nrelease): bump to 1.38.1, update changelogs and docs\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📝 Document precomputed ctx.flatVariables in composable-screen runtime rule",
          "is_bot": false,
          "headline": "🐛 Fix excessive re-renders in Loader animations + ComposableScreen tr…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-08T10:49:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b7dd148f88a6c502ae2e0f3b39ebbfce1f727964",
          "body": "…— v1.38.0 (#77)\n\n* ✨ ProgressIndicator value range (minValue/maxValue/step/labelSuffix) — v1.38.0\n\nDecouple fill fraction from displayed value so ProgressIndicator can drive an\nanimated count-up to N (not just 0–100). autoplay animates initialValue→maxValue;\nthe bound variable + label carry the raw\n[…]\n) <noreply@anthropic.com>\n\n* 📝 Note worklets can't call JS closures (inline + capture primitives)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📦 Sync package-lock to 1.38.0",
          "is_bot": false,
          "headline": "✨ ProgressIndicator value range (minValue/maxValue/step/labelSuffix) …",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-08T10:16:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "497abda62081e40a8465296ad5c59f654867b24a",
          "body": "… SDK v1.37.0 (#76)\n\n* ✨ onPress action on every ComposableScreen UIElement — SDK v1.37.0\n\nAdd optional `onPress: ButtonAction[]` to BaseBoxProps so any non-pressable\nelement can dispatch the same action list as Button (continue/setVariable/custom),\nrun sequentially. Wired via a single central Press\n[…]\nw > YStack > XStack rows) that toggle into a `symptoms` multi-select\nvia onPress + setVariable arrayOp:\"toggle\"; the circle fills via renderWhen\ncontains. Pure YStack/XStack — no CheckboxGroup widget.",
          "is_bot": false,
          "headline": "✨ onPress on every UIElement + setVariable arrayOp for multi-select —…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-08T09:28:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d3b183b9439f524f70c4b62e8ed18828ce4898c2",
          "body": "…36.2) (#75)\n\n* 🐛 fix(ui): apply theme default font to all ComposableScreen text elements — v1.36.2\n\nRadioGroup/CheckboxGroup item labels, WheelPicker items, and the Android\nDatePicker trigger label ignored theme.typography.defaultFontFamily when\nfontFamily was omitted, rendering in the system font.\n[…]\nr dep used only by the Commitment signature variant\n(lazy require). CI build is pure tsc and publish packs dist/ — neither needs\nthe native binary its postinstall downloads, which intermittently 504s.",
          "is_bot": false,
          "headline": "🐛 Apply theme default font to all ComposableScreen text elements (v1.…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-08T08:33:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "06906e85c77a167e5dff30dd27f8f6b767da0de2",
          "body": "* ⬆️ Upgrade example app to Expo SDK 56 (RN 0.85); bump SDK to v1.36.1\n\nExample app:\n- expo SDK 55 → 56 (latest 56.0.8); `expo install --fix` aligned all deps\n- add SDK 56 config plugins: expo-status-bar, @react-native-community/datetimepicker\n- remove @react-navigation/{bottom-tabs,elements,native}\n[…]\no; npm dedupe after.\n- RN 0.85: absoluteFillObject removed → absoluteFill; native peer deps must match SDK.\n- expo-modules-jsi weak let error = Xcode indexer noise, not the real SPM xcframework build.",
          "is_bot": false,
          "headline": "⬆️ Upgrade example app to Expo SDK 56 (RN 0.85) — SDK v1.36.1 (#72)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-04T15:26:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2cbfc7205d8d3283c188a1199230f008b408ee9e",
          "body": "…veBlurImage, linear+radial mask) — v1.36.0 (#71)\n\n* ✨ Progressive blur for ComposableScreen: Image blurRadius + ProgressiveBlurImage element (v1.36.0)\n\nAdds two blur capabilities so onboarding screens can reproduce the Figma\n\"welcome screen\" hero (sharp photo up top, progressively blurred toward th\n[…]\npic.com>\n\n* 🔖 Release v1.36.0 instead of 1.37.0 (no version gap)\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 🔒 Sync package-lock for masked-view dep (drop stray expo-blur)",
          "is_bot": false,
          "headline": "✨ Progressive blur for ComposableScreen (Image blurRadius + Progressi…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-04T11:32:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "694dc919696c8c3b59204932a9d6c934c84aae1b",
          "body": null,
          "is_bot": false,
          "headline": "🚚 Rename claude plugin to react-native-onboarding (#70)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-03T09:58:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "61b8e4fd37c38ea71860a41357605c617a033419",
          "body": "… plugin skills (#69)\n\nPatterns extracted from gold-standard onboarding dc0fd3d0 (21-step ComposableScreen flow):\n- New screen-patterns.md cookbook: universal skeleton + canonical CTA, select-and-advance\n  questions, carousel state machine, staggered FadeIn choreography, self-completing loader,\n  so\n[…]\nsabledWhen/renderWhen gates on a variable the screen\n  never captures (copy-paste bug seen in production)\n- inspect-target-app: optional DP tokens (radius.xl, gutter, accent.gold/pastels, shadow.card)",
          "is_bot": false,
          "headline": "📝 Encode beautiful-onboarding patterns from production reference into…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-03T09:38:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c835e14db3872e81e7e0c1fb760a65d4d2802d1f",
          "body": "…p (v1.35.0) (#68)\n\n* ✨ Haptic feedback for ComposableScreen Button/RadioGroup/CheckboxGroup (v1.35.0)\n\nAdd optional, opt-in `haptic` prop (\"none\"|\"light\"|\"medium\"|\"heavy\"|\"soft\"|\"rigid\")\nto the clickable ComposableScreen elements, mapping to expo-haptics\nImpactFeedbackStyle. Fires on press (Button)\n[…]\natching Button (guards first). A no-variable\n  group no longer buzzes on a tap that changes nothing.\n- Headless prop comments corrected: feedback fires on press, before the\n  selection/toggle commits.",
          "is_bot": false,
          "headline": "✨ Haptic feedback for ComposableScreen Button/RadioGroup/CheckboxGrou…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-02T14:19:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c6ceb5a5d105c68960af89a0ed6f0eb10e2331c3",
          "body": "* 🐛 Fix ProgressIndicator resetting after finishing\n\nuseAnimatedReaction had no dependency array, so reanimated 4 tore down\nand rebuilt the mapper on every render. A looping showLabel indicator\nre-renders ~40x/s forever (one setPercentage per frame), churning\nstartMapper/stopMapper on the UI-thread \n[…]\n): bump to 1.34.1, update changelogs and docs\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📝 Document reanimated useAnimatedReaction deps rule + worktree example-run gotcha",
          "is_bot": false,
          "headline": "🐛 Fix ProgressIndicator resetting after finishing (v1.34.1) (#67)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-02T13:38:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "51c0cb4515c796d5dbcaa3b69de7602b8f289f4c",
          "body": "…hText align (v1.34.0) (#66)\n\n* 🐛 Fix webp/svg images, horizontal ScrollView, RichText align (v1.34.0)\n\nComposableScreen UIElement fixes:\n\n- Image webp: render via expo-image (new optional peer dep) with RN Image\n  fallback — RN's built-in Image is flaky for webp on iOS. resizeMode maps\n  to content\n[…]\nentType flexShrink default + the new XScroll (horizontal scroll children).\n- ImageElement webp (expo-image) / svg (.svg → SvgUri) rendering.\n- RichText textAlign mapping onto the row's justifyContent.",
          "is_bot": false,
          "headline": "🐛 ComposableScreen fixes: webp/svg images, horizontal ScrollView, Ric…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-02T09:56:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "855e39c2c87b7e2713cab031101ea1376687ee99",
          "body": "* ✨ RichText container UIElement for ComposableScreen (v1.33.0)\n\nAdd a `RichText` multi-element container that lays out child `Text`\nelements as a wrapping flex row — words and styled \"chip\" segments\n(padded/rounded/rotated pills) that wrap and align together, matching the\nhost-app parseTitleWithChi\n[…]\nnd isFlowingText so a child with margin or explicit\nsize stays atomic (avoids per-word application); null renderWhen on chip push\n(no double-eval); use mode: undefined instead of the non-enum \"plain\".",
          "is_bot": false,
          "headline": "✨ RichText container UIElement for ComposableScreen (v1.33.0) (#65)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-01T16:00:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8c55cb1742db44f2ec4d827f47f5b06857a5834f",
          "body": "…es (v1.32.0) (#64)\n\n* ✨ Animations/transitions/effects for ComposableScreen (v1.32.0)\n\nAdd a reanimated-aligned motion surface to BaseBoxProps so any UIElement\ncan declare animation. `preset` values are exact reanimated builder names;\nmodifier fields map to builder methods.\n\n- transform: static { t\n[…]\n(spans are not UIElements and RN\nignores transform on inline nested Text).\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\n\n* 📝 Document ComposableScreen motion + TextSpan-not-UIElement rules",
          "is_bot": false,
          "headline": "✨ Animations/transitions/effects for ComposableScreen + TextSpan styl…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-01T14:00:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4241ec5037a22852fd40db226526225742ecc7d7",
          "body": "* ✨ Inline rich-text spans for ComposableScreen Text (v1.31.0)\n\nText element `content` now accepts `string | TextSpan[]`. A span array\nrenders styled fragments inline (nested <Text>) that wrap on one baseline.\nPer-span fontWeight/fontStyle/fontFamily/fontSize/letterSpacing/color/\ntextDecorationLine;\n[…]\np-json skills\n- bump both packages + plugin to 1.31.0, changelogs\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📝 docs: worktree metro port + step .safeParse required fields",
          "is_bot": false,
          "headline": "✨ Inline rich-text spans for ComposableScreen Text (v1.31.0) (#63)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-01T12:28:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2293ddcfc800d19e65c5e42eb5f9ed2e461604f2",
          "body": "* ✨ feat(composable-screen): ProgressIndicator UIElement (linear/circular)\n\nLinear or circular progress display bound to an int variable (0-100).\nProps: variant, variableName, value, autoplay, loop, initialValue,\nduration, easing (linear/ease-in/ease-out/ease-in-out), color, trackColor,\nthickness, s\n[…]\nme — fixes per-frame setVariable context\n  re-render storm when autoplay+variableName bound (P1).\n- Only call setPercentage when showLabel is set (P2).\n- Add easing to both animation effect deps (P3).",
          "is_bot": false,
          "headline": "✨ ProgressIndicator UIElement (linear/circular) + delay prop (#62)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-06-01T08:09:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7864916e658ef9b264dc746fe95cc536c9572774",
          "body": "* ✨ feat(composable-screen): DatePicker \"now\" sentinel for date bounds (v1.29.0)\n\ndefaultValue/minimumDate/maximumDate now accept the literal \"now\",\nresolved to the current date/time at render so bounds don't go stale.\nUpdates headless + UI schemas, renderer, examples, docs, changelogs.\n\nCo-Authored\n[…]\nonAction variant (+ schema/type exports) into headless.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📝 docs(claude): note bidirectional schema drift + payload debug gotchas",
          "is_bot": false,
          "headline": "✨ DatePicker \"now\" sentinel for date bounds (v1.29.0) (#61)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-29T13:40:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "87063d0ee9bd603bb3a9382c14d368e1bb10cc1d",
          "body": "* ✨ feat(composable-screen): showTick toggle for Radio/Checkbox\n\nAdd optional `showTick?: boolean` (default true) to RadioGroup and\nCheckboxGroup UIElements. When false, the radio circle / checkbox box\nindicator is hidden while the item label and selected background/border\nstyling still render.\n\n- H\n[…]\n* 📦 chore(release): bump to 1.28.0, update changelogs and docs\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n* 📝 docs(rules): note stale main ref + lockfile noise in worktrees",
          "is_bot": false,
          "headline": "✨ showTick toggle for RadioGroup/CheckboxGroup (v1.28.0) (#60)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-29T09:43:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "102bda07e56424ad806f5bd09c16f68b4c108ec8",
          "body": "* ✨ feat(tooling): example app error-watch agent\n\nAdd a headless error detector for the example app with three modes:\n\n- oneshot: start/reuse Metro, force a bundle compile per platform, report\n  bundling/resolve/syntax errors, exit 0/1/2.\n- metro: run Metro for example/ mirrored to a logfile (long-l\n[…]\node frame survives instead of being\n  buried under Babel's internal stack.\n\nValidated end-to-end: a syntax error in app/_layout.tsx now triggers Shell B\nto exit 1 with a clean, diagnosis-ready report.",
          "is_bot": false,
          "headline": "✨ feat(tooling): example app error-watch agent (#59)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-29T09:40:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2a7c60c92a698b95de2bb8e0d686d0dbf4a7132b",
          "body": "* ✨ feat(composable-screen): WheelPicker UIElement\n\nAdd a scrolling wheel selector element to the ComposableScreen system\n(both headless SDK + onboarding-ui).\n\n- Options from explicit `items` OR auto-generated numeric `range`\n  {min,max,step?,unit?} (exactly one required)\n- Binds a variable via vari\n[…]\nops\n- example-app: peer-dep elements need explicit example deps for native\n  autolinking + dev-client rebuild; prebuild needs google-font ttf in assets;\n  worktree symlink fix also applies to build:ui",
          "is_bot": false,
          "headline": "feat: WheelPicker UIElement + unary condition operators (v1.27.0) (#57)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-29T08:56:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ff8929f60c8310da7e0a81652346d67cb00b77df",
          "body": "Two failures in the Publish workflow:\n\n1. Headless publish failed with npm E422: the OIDC provenance check\n   rejected the package because `repository.url` pointed to\n   `rocapine/react-native-onboarding-studio`, not the building repo\n   `Rocapine/react-native-onboarding`. Corrected the URL (name + \n[…]\nrocapine/react-native-onboarding'\": the matrix job built only the\n   UI package, but its types resolve from the headless package's dist/.\n   Build headless first before the matrix package's own build.",
          "is_bot": false,
          "headline": "🐛 fix(ci): repair publish workflow (provenance + build order) (#58)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-29T08:44:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a879cc25808488d1ac1be555b138970b28b7cb93",
          "body": "* ✨ feat(composable-screen): Icon fill + fillOpacity (v1.26.0)\n\nAdds optional `fill` and `fillOpacity` props to the `Icon` UIElement so\nauthors can render filled / tinted Lucide icons from CMS payload. Schema\nmirrored in headless + UI; renderer passes both through to\n`lucide-react-native` (extends `\n[…]\neference.\n\nBumps both packages + plugin manifest to 1.26.0.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n* 📝 docs(claude.md): widen UI-mirror watchlist to include IconElement",
          "is_bot": false,
          "headline": "✨ feat(composable-screen): Icon fill + fillOpacity (v1.26.0) (#56)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-28T13:49:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "faa36c4f9a527b7185f3617c8b12ce6c13328f06",
          "body": "Adds .github/workflows/publish.yml. On every push to main, runs a\nmatrix job per package that compares packages/<pkg>/package.json\nversion against the npm registry; if different, builds and publishes\nvia OIDC trusted publishers (no NPM_TOKEN required). The headless\nmatrix leg also tags vX.Y.Z and cr\n[…]\n(manual, one-time, per package on npmjs.com):\n- Trusted Publisher → GitHub Actions\n- Repository: rocapine/react-native-onboarding-studio\n- Workflow filename: publish.yml\n- Allowed actions: npm publish",
          "is_bot": false,
          "headline": "ci: auto-publish SDKs to npm on main when version changes (#55)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-28T12:54:32Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a3b5c5b8539a3d96cd4603f827ec68e064887dd7",
          "body": "* fix(composable-screen): remove page-level ScrollView wrapper\n\nScrollView's contentContainer (flexGrow:1) gave inner flex:1 children\nno bounded height — Carousel(flex:1) grew with its intrinsic content\nand pushed siblings (Button, footer) past the viewport, also blocking\nthe payload's root SafeArea\n[…]\night defaults to 200\",\n  document aspectRatio and the FitWidth fallback.\n- CHANGELOG: migration note for the ScrollView wrapper removal.\n- package-lock.json: refresh after npm install in the worktree.",
          "is_bot": false,
          "headline": "fix(composable-screen): layout + shadow + Rive + schema (v1.25.1) (#54)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-28T12:33:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4523405f2d5b616a0f58e5773a9ed532b0293bb3",
          "body": "… (OS-162) (#53)\n\n* feat(composable-screen): add ScrollView + KeyboardAvoidingView UIElements\n\nAdd two container UIElements so authors can make sections scroll and avoid\nthe keyboard from the CMS payload instead of chaining manual spacers (OS-162).\n\n- ScrollView: bounces, indicators, contentInset, c\n[…]\nthored-By: Claude Opus 4.7 <noreply@anthropic.com>\n\n* docs(plugin): fix contradictory kebab-case element id in workflow step\n\nWorkflow step 5 still said kebab-case IDs, contradicting the UUID v4 rule.",
          "is_bot": false,
          "headline": "feat(composable-screen): ScrollView + KeyboardAvoidingView UIElements…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-27T14:41:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7ca162be7be236df7b6426119d8b58587fea9fa4",
          "body": "Update skills + agents so generated flows link each step to the next\nvia an explicit nextStep.defaultTargetStepId (linear by default) and\nadd branches where a routing condition applies, instead of relying on\nthe implicit null + array-order fallback.\n\n- create-step-json: nextStep field guidance + aut\n[…]\ns: new \"Step linking (auto-link via multi-path)\" section\n- validate-step-json: flow-level chain integrity checks + failure modes\n- step-json-reviewer: chain integrity review bullets + finding examples",
          "is_bot": false,
          "headline": "docs(plugin): auto-link steps via explicit multi-path nextStep (#52)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-27T12:41:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "426f1951a1dfa746120e2cc17ef6f2e644a7792f",
          "body": "…) (#51)\n\n* ✨ feat(composable-screen): button pressed/disabled state overrides + shadow\n\nAdd per-state styling to ComposableScreen Button and shadow fields to\nBaseBoxProps (OS-161).\n\n- BaseBoxProps: shadowColor, shadowOffset, shadowOpacity, shadowRadius, elevation\n- Button: pressedStyle / disabledSt\n[…]\nmirrors + worktree install gotcha\n\n- CLAUDE.md schema-sync: add plugin skills + website page-types.mdx as mirror targets\n- example-app rule: fresh-worktree node_modules resolution gotcha + install fix",
          "is_bot": false,
          "headline": "✨ feat(composable-screen): Button per-state styling + shadow (v1.24.0…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-27T08:41:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c1971577ade793d4b9e6bf4e58cc6874216a7162",
          "body": "* ✨ feat(composable-screen): renderWhen on any UIElement + element-default context overlay\n\n- Every UIElement variant accepts optional `renderWhen?: LeafCondition | ConditionGroup`\n  (reuses Branch/Button condition schemas). renderElement evaluates against\n  ctx.variables; returns null and skips sub\n[…]\n defaulted elements must mirror any runtime clamp in collectDefaults\n  to avoid drift between overlaid default and rendered state.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(composable-screen): renderWhen on any UIElement (v1.23.0) (#50)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-27T06:46:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5963e9079dd09126181d2a1aa533df32f7673106",
          "body": null,
          "is_bot": false,
          "headline": "feat: rocapine-onboarding-sdk plugin v1.22.0 (#49)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-22T14:31:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "683d8eb4ddfca6693ab9a7a0022d62bca5d966cf",
          "body": "…0) (#48)\n\n* feat(composable-screen): carousel defaultIndex + variableName (v1.21.0)\n\nAdd `defaultIndex` (number, nullable) and `variableName` (string) to\nComposableScreen Carousel UIElement. `variableName` binds carousel index\nto the variable store: `setVariable` button actions scroll the carousel,\n[…]\n new expression.ts (tokenizer + recursive\n  descent parser, zero deps); ButtonElement handler dispatches expression\n  vs literal mode\n- example: carousel Prev/Next use {{carouselPage}} ± 1 expressions",
          "is_bot": false,
          "headline": "feat(composable-screen): carousel defaultIndex + variableName (v1.21.…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-11T15:36:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f457947410b4e7a2199d6e6b1285f7c41318151b",
          "body": "* ✨ feat(composable-screen): conditional button disable (v1.20.0)\n\nButtonElement gains optional `disabledWhen` (LeafCondition | ConditionGroup,\nsame schema as Branch.condition). When the condition evaluates truthy\nagainst current onboarding variables, the button blocks all press actions\n(continue, s\n[…]\n-blocking.\n- composable-screen-runtime.md: add rule for flattening\n  `ComposableVariableEntry.value` before passing `ctx.variables` to\n  `evaluateCondition` / `evaluateLeaf` / `resolveNextStepNumber`.",
          "is_bot": false,
          "headline": "feat(composable-screen): conditional button disable (v1.20.0) (#47)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-11T12:45:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1de9ba0b7fc81683717bba0e1afefe9f5bb82935",
          "body": "* feat(composable-screen): opt out of template top padding\n\nAdd a disableTopPadding flag on OnboardingTemplate and pass it from the\nComposableScreen renderer so its own SafeAreaView root controls the top\ninset. Prevents the template's 40px header padding from stacking on\ntop of the composable screen\n[…]\noth SDK packages to 1.19.0, document `typography.defaultFontFamily`\n+ `fontFamily: \"inherit\"` in CHANGELOGs and the theming guide.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: font inheritance via theme defaultFontFamily (v1.19.0) (#46)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-07T14:43:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d761a8dfe259ab9d41f924afa97a3aa40d90ec82",
          "body": "* ✨ feat(composable-screen): setVariable button action + locale picker\n\nAdd setVariable button action variant so buttons can write to onboarding\nvariables (name/value/label) alongside continue and custom actions.\nInclude locale picker in example app and split CLAUDE.md guidance into\npath-scoped rule\n[…]\nnching ref fix)\ninto both CHANGELOGs and documents the new ButtonAction variant in the\nwebsite page-types and custom-actions docs.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "🔖 chore(release): v1.18.0 — setVariable action + branching fix (#45)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-06T12:27:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e319ab4ceb870ef022cfef62a157cac9574b5014",
          "body": "…1.17.1) (#44)\n\nBackend returns `fonts: { family: [{ weight, style, url }, ...] }` but\nregisterFonts iterated values as `Record<weightKey, urlString>`, producing\nnumeric indices and `[object Object]` urls — native expo-font then threw\n`loadSingleFontAsync expected resource of type Asset`.\n\nnormalize\n[…]\nhapes, dedupes by weight, prefers\nstyle: \"normal\" over italic. Types widened: FontFamilyManifestInput +\nFontVariantEntry exported.\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "🐛 fix(fonts): accept array-shape variants in runtime font manifest (v…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-04T13:16:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "11d9e3007a81a74ab8c49895645e44b75c44fcc7",
          "body": "* 🔨 chore: add composable-screen skills and fix carousel sizing\n\n- add update-uielement, sync-studio-schema, composable-screen-layout-debug skills\n- document ComposableScreen UIElement conventions in CLAUDE.md\n- allow type/lint bash perms in .claude/settings.json\n- fix CarouselElement to measure con\n[…]\ns without\nexplicit sizing still see the carousel.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "✨ feat: runtime font download + load (v1.17.0) (#43)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-05-04T12:04:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b8a75de21c1e1650725f8dd4c8845f2b3541a19f",
          "body": "…ection (v1.16.0) (#42)\n\n* ✨ feat(composable-screen): button supports ordered actions + custom action injection\n\n- Button.actions: ordered ButtonAction[] (continue | { type: \"custom\", function, variables? })\n- OnboardingProvider.customActions: name → handler map, awaited sequentially, terminal conti\n[…]\nzation/custom-actions: new doc covering schema, handler, patterns\n- customization/intro: add Level 2b Custom Actions card + next-steps link\n- core-concepts: customActions in OnboardingProvider snippet",
          "is_bot": false,
          "headline": "✨ feat(composable-screen): button ordered actions + customActions inj…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-29T09:29:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "83f4457d8a2254f7f49e84c3fcf522f936c0b0bd",
          "body": "* ✨ feat(composable-screen): add SafeAreaView UIElement (v1.15.0)\n\n- New SafeAreaView UIElement, mirrors react-native-safe-area-context props\n  (mode, edges array or per-edge object), extends BaseBoxProps, accepts children\n- Strip safe-area inset logic from OnboardingTemplate; keep +40 progress-head\n[…]\nith z.strictObject\n- include left/right edges in Picker SafeAreaView usages\n- add alwaysBounceVertical={false} to Loader/Question/Ratings ScrollViews\n- add backend schema-sync note to CHANGELOG 1.15.0",
          "is_bot": false,
          "headline": "✨ feat(composable-screen): add SafeAreaView UIElement (v1.15.0) (#41)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-29T08:36:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f794758dffcbca111cc5a9fdde1c853befa094a1",
          "body": "* ✨ feat(composable-screen): add ZStack UIElement (v1.13.1)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n\n* 📦 chore(release): bump to v1.14.0, update changelogs and docs\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n\n* 🧪 example(composable-screen): add ZStack subscreen wit\n[…]\now props like\n  gap/alignItems/justifyContent are not honored on ZStack\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "✨ feat(composable-screen): add ZStack UIElement (v1.14.0) (#40)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-28T14:33:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "29b791c9c7dcd06ab16c999b1ee7b8070e6df0dd",
          "body": "…nts (v1.13.0) (#39)\n\n* ✨ feat(composable-screen): add gradient background support to all UIElements\n\n- add `backgroundGradient` to `BaseBoxProps` (both packages) with `GradientEdge` named positions\n- introduce `GradientBox` component wrapping `expo-linear-gradient` with `View` fallback\n- update all\n[…]\n: preserve intrinsic sizing in gradient mode\n\n- remove forced `flex: 1` on `<Text>` when gradient is set; use `p.flex` unconditionally\n- restore `flexShrink` parentType fallback regardless of gradient",
          "is_bot": false,
          "headline": "✨ feat(composable-screen): gradient background support on all UIEleme…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-28T09:48:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "589bfe4fc55f77cb0fd64be4f295537957806c6d",
          "body": "* ✨ feat(onboarding): add multi-path branching + base step schema\n\n- add branching schemas (LeafCondition, ConditionGroup, Branch, NextStep) to common.types.ts\n- add BaseStepTypeSchema; refactor all 8 step schemas to extend it\n- add variables/setVariable to headless OnboardingProgressContext\n- add r\n[…]\n- NextStepSchema branches default to [] so omitting branches field is valid\n- add 8 new tests covering all fixed cases (75 total)\n\n* 📚 docs(changelog): add 1.12.0 entries + bump both packages to minor",
          "is_bot": false,
          "headline": "feat(onboarding): multi-path branching (#38)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-28T08:30:34Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2aef9a5dc04725268e8dfade9c46c61d889e5c9e",
          "body": "* ✨ feat(composable-screen): add Carousel UIElement\n\n- CarouselElement.ts — Zod schema + TypeScript type (headless)\n- CarouselElement.tsx — renderer using react-native-reanimated-carousel\n- Auto-play, loop, pagination dots, per-slide image/title/description\n- Graceful fallback when peer dep is absen\n[…]\nt, letterSpacing props\n- fix autoplay → autoPlay in all example files\n\n* 📦 chore(release): bump to 1.11.1, update changelogs\n\n* 🐛 fix(composable-screen): use flexGrow on scroll content instead of flex",
          "is_bot": false,
          "headline": "✨ feat(composable-screen): add Carousel UIElement (v1.11.1) (#37)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-27T09:08:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "807fe956052ce45aca814ee27ea9306ed7230cc0",
          "body": "* ✨ feat(composable-screen): add DatePicker UIElement (v1.10.0)\n\n- new DatePicker element saves selected date as ISO string + human-readable label to variable\n- supports mode (date/time/datetime), display style, min/max date, textColor, accentColor, locale\n- adds @react-native-community/datetimepick\n[…]\nt value/label breakdown table; update deps note\n- docs/changelog/headless.mdx + ui.mdx: import both package CHANGELOGs as\n  live MDX pages under a new \"Changelog\" sidebar category (sidebar_position 8)",
          "is_bot": false,
          "headline": "✨ feat(composable-screen): add DatePicker UIElement (v1.10.0) (#36)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-23T12:28:06Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f1cf88e9bfb23be91c1459ff5eb5d3fa51926282",
          "body": "* 🔨 chore(claude): add add-uielement and bump-version skills + agent\n\n* ✨ feat(composable-screen): add CheckboxGroup UIElement\n\n- add CheckboxGroupElement.ts headless schema (multi-select string[])\n- update headless types.ts union and Zod schema\n- add CheckboxGroupElement.tsx UI renderer with checkb\n[…]\nuse per-index path\n- correct 1.9.0 CHANGELOG entries (Checkbox → CheckboxGroup)\n- fix SKILL.md bare fences and wrong props import template\n- reorder add-uielement agent: stage before git diff --cached",
          "is_bot": false,
          "headline": "✨ feat(composable-screen): add CheckboxGroup UIElement (v1.9.0) (#35)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-23T08:39:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "876415a8b9ce5aed46350cea2c5e70ecea646a09",
          "body": "…pse, flatten Input (v1.8.1) (#34)\n\n* 🐛 fix(composable-screen): add alignSelf to elements, fix radio item text collapse\n\n- add alignSelf prop to BaseBoxProps and StackElement (both packages)\n- wire alignSelf in Input, RadioGroup, and Stack renderers\n- flatten InputElement to single TextInput (remove\n[…]\ndate changelogs and docs\n\n- bump both packages to 1.8.1\n- add 1.8.1 changelog entries (alignSelf, Input flatten, RadioGroup fix)\n- add alignSelf to Stack, Input, RadioGroup prop tables in website docs",
          "is_bot": false,
          "headline": "🐛 fix(composable-screen): alignSelf on elements, fix radio text colla…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-22T13:52:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "122eed1ce8b6403310282aaa37a1de7178d7662d",
          "body": "…v1.8.0) (#33)\n\n* ✨ feat(composable-screen): add Button UIElement type\n\n- add Button to UIElement union in both packages with label, action, variant (filled/outlined/ghost), color, typography and BaseBoxProps\n- render Button via TouchableOpacity; tap calls onContinue\n- thread onContinue through rend\n[…]\nroupElement: fix useEffect deps\n- VideoElement: sync player props on prop changes\n- IconElement: forward backgroundColor to container View\n- examples: add plan-display expression text after RadioGroup",
          "is_bot": false,
          "headline": "feat(composable-screen): Button, RadioGroup UIElements + file split (…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-22T07:19:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9e5afb40247eff614243e33f8861f1b0e717a57b",
          "body": "* ✨ feat(composable-screen): add fontFamily prop to Text UIElement\n\n* 📦 build: bump both packages to v1.7.0\n\n- add fontFamily to Text UIElement changelogs\n- update website docs Text props table",
          "is_bot": false,
          "headline": "feat(composable-screen): add fontFamily prop to Text UIElement (#32)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-21T13:37:54Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "efe0613af37fa293f0c8288039df726cc767bbba",
          "body": "…pression text (#31)\n\n* ✨ feat(composable-screen): add Input UIElement type\n\n* ✨ feat(composable-screen): add variable context and expression text\n\n- Add `variableName` prop to Input elements — writes value to shared context on change\n- Add `mode: \"plain\" | \"expression\"` to Text elements — expressio\n[…]\ntive() in both schemas\n- Use theme.typography.textStyles.body.fontSize as fontSize fallback\n- Wire fontWeight into TextInput style\n- Fix invalid JSON example block in docs; add url to keyboardType row",
          "is_bot": false,
          "headline": "feat(composable-screen): Input UIElement with variable context and ex…",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-21T12:39:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "debc3582ba007fba45bae7fe7c40ba715dd829e8",
          "body": "* ✨ feat(composable-screen): add Icon and Video UIElement types\n\n- add Icon element rendered via lucide-react-native (name, size, color, strokeWidth)\n- add Video element rendered via expo-video (url, autoPlay, loop, muted, controls)\n- update Zod schemas and TypeScript union types in both headless an\n[…]\n- Remove alignSelf:\"center\" from Icon wrapper View\n- Update onboarding CHANGELOG to describe schema contract (not renderer detail)\n- Fix borderWidth/borderRadius/borderColor docs to show correct types",
          "is_bot": false,
          "headline": "feat(composable-screen): add Icon and Video UIElement types (#30) (#30)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-21T09:24:22Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7e2ff64a33c6b7565f3fdb91e7cbe1f0df802121",
          "body": "* ✨ feat(composable-screen): add Lottie UIElement type\n\n- add Lottie element to UIElement union in both packages\n- optional require of lottie-react-native with fallback view\n- update onboarding-example and composable-screen example\n\n--wip-- [skip ci]\n\n✨ feat(composable-screen): add Lottie UIElement \n[…]\nnt mapping from rive-react-native module\n- Fix fallback message: reference \"rive-react-native\" not \"@rive-app/react-native\"\n- Add lottie-react-native and rive-react-native as optional peerDependencies",
          "is_bot": false,
          "headline": "feat(composable-screen): add Lottie and Rive UIElement types (#29)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-21T07:51:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "333855af8800720cc1e1254e5dcaea0230259090",
          "body": "* ✨ feat(composable-screen): add Image UIElement type\n\n- Add `Image` variant to `UIElement` union and `UIElementSchema` in both packages\n- Render `<Image>` in `Renderer.tsx` with `resizeMode`, sizing, and layout props\n- Update `onboarding-example.ts` and example screen to showcase the new element\n- \n[…]\n changelogs\n\n* 📚 docs(page-types): fix Image props table types\n\n- width: number → number | string (matches \"100%\" default)\n- split borderRadius/borderWidth/borderColor into two rows with correct types",
          "is_bot": false,
          "headline": "feat(composable-screen): add Image UIElement type (#28)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-17T13:30:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ccbe94bf25f597be9bab3f27b0c8b39a12447ba4",
          "body": "* ✨ feat(pages): add NewCustomScreen page type\n\n- add Zod schema and types in headless package\n- add Renderer, types, and index in onboarding-ui\n- register new type in OnboardingPage router and type unions\n- update CLAUDE.md with full monorepo architecture docs\n- add VS Code workspace file\n\n* ♻️ ref\n[…]\nreen.tsx example showcasing nested stacks, borders, badges, and opacity\n- register \"Composable Screen\" in the examples index\n- constrain opacity to [0, 1] via z.number().min(0).max(1) in both packages",
          "is_bot": false,
          "headline": "feat(composable-screen): add ComposableScreen page type (#27)",
          "author_name": "Paul Briand",
          "author_login": "P0labrD",
          "committed_at": "2026-04-16T12:39:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5752da39cff1d5ef911575b72da768c884b0c672",
          "body": "feat: add ButtonSectionSchema and integrate into various onboarding s…",
          "is_bot": false,
          "headline": "Merge pull request #26 from Rocapine/samet/btn-label-improvements",
          "author_name": "Samet Salih",
          "author_login": "Sametaien",
          "committed_at": "2026-03-26T08:40:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "83865e47218a3e92e56880c9e02e2959b5773c09",
          "body": "…ish icon properties\n\nModified the ButtonSectionSchema in both onboarding and onboarding-ui to make the label optional and the icon property nullish, enhancing flexibility in button configuration.",
          "is_bot": false,
          "headline": "refactor: update ButtonSectionSchema to allow optional label and null…",
          "author_name": "Samet Salih Türk",
          "author_login": "Sametaien",
          "committed_at": "2026-03-26T08:35:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e1f09e87750c0a458cd9ef6d32c0d68f5c9448be",
          "body": null,
          "is_bot": false,
          "headline": "chore: update package versions to 1.1.6 for onboarding and onboarding-ui",
          "author_name": "Samet Salih Türk",
          "author_login": "Sametaien",
          "committed_at": "2026-03-26T08:28:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d2a6dbfee9236710d295ebc91a25dfdaa698cdf8",
          "body": "…tep types\n\nIntroduced ButtonSectionSchema to define button properties, including label and icon. Updated multiple onboarding step types (Carousel, Commitment, Loader, MediaContent, Picker, Question, Ratings) to include an optional buttonSection field, enhancing button customization across the onboarding UI.",
          "is_bot": false,
          "headline": "feat: add ButtonSectionSchema and integrate into various onboarding s…",
          "author_name": "Samet Salih Türk",
          "author_login": "Sametaien",
          "committed_at": "2026-03-26T06:40:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bd16076d816da090c443829191ce58be523ba989",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version",
          "author_name": "Sammy Teillet",
          "author_login": "Samox",
          "committed_at": "2026-03-24T15:56:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "32dd7204c98735bed55d49e7adbfe1cf817f2b34",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version",
          "author_name": "Sammy Teillet",
          "author_login": "Samox",
          "committed_at": "2026-03-24T14:10:04Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7ad2065e4c04beacf0e8ecd1f28ba6e3d1b6a180",
          "body": "Samet/fix media layout style",
          "is_bot": false,
          "headline": "Merge pull request #25 from Rocapine/samet/fix-media-layout-style",
          "author_name": "Sammy Teillet",
          "author_login": "Samox",
          "committed_at": "2026-03-24T13:58:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d7ebf63884d088c3e534a1886732d2a10fc8cdfd",
          "body": null,
          "is_bot": false,
          "headline": "fix: update version to 1.1.4 in package.json",
          "author_name": "Samet Salih Türk",
          "author_login": "Sametaien",
          "committed_at": "2026-03-23T20:12:17Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 59,
      "commits_last_year": 290,
      "latest_release_at": "2026-07-17T13:27:09Z",
      "latest_release_tag": "v1.59.0",
      "releases_from_tags": false,
      "days_since_last_push": 5,
      "active_weeks_last_year": 26,
      "days_since_latest_release": 5,
      "mean_days_between_releases": 2.4
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "has_description": false,
      "has_contributing": true,
      "health_percentage": 37,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@rocapine/react-native-onboarding",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "react-native",
            "onboarding",
            "rocapine",
            "headless",
            "cms",
            "onboarding-studio"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@rocapine/react-native-onboarding",
          "is_deprecated": false,
          "latest_version": "1.59.0",
          "repository_url": "https://github.com/Rocapine/react-native-onboarding",
          "versions_count": 93,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 6,
          "monthly_downloads": 4304,
          "first_published_at": "2025-11-18T15:14:20.590000Z",
          "latest_published_at": "2026-07-17T13:27:06.673000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@rocapine/react-native-onboarding-ui",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "react-native",
            "onboarding",
            "rocapine",
            "ui",
            "components",
            "onboarding-studio"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@rocapine/react-native-onboarding-ui",
          "is_deprecated": false,
          "latest_version": "1.59.0",
          "repository_url": "https://github.com/Rocapine/react-native-onboarding",
          "versions_count": 89,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 6,
          "monthly_downloads": 3940,
          "first_published_at": "2025-11-18T15:14:44.287000Z",
          "latest_published_at": "2026-07-17T13:27:13.414000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 2,
      "watchers": 0,
      "fork_history": {
        "days": [
          {
            "date": "2026-01-15",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 3
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "example"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [
        "openapi.yaml",
        "website/static/openapi.yaml"
      ],
      "has_devcontainer": false,
      "typecheck_configs": [
        "example/tsconfig.json",
        "packages/onboarding-ui/tsconfig.json",
        "packages/onboarding/tsconfig.json",
        "website/tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 47028,
      "source_files_sampled": 233,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 13672
    },
    "dependencies": {
      "manifests": [
        "example/package.json",
        "package.json",
        "website/package.json"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@docusaurus/core",
          "manifest": "website/package.json",
          "ecosystem": "npm",
          "version_constraint": "3.9.1"
        },
        {
          "name": "@docusaurus/preset-classic",
          "manifest": "website/package.json",
          "ecosystem": "npm",
          "version_constraint": "3.9.1"
        },
        {
          "name": "@mdx-js/react",
          "manifest": "website/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.0.0"
        },
        {
          "name": "clsx",
          "manifest": "website/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.0.0"
        },
        {
          "name": "prism-react-renderer",
          "manifest": "website/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.3.0"
        },
        {
          "name": "react",
          "manifest": "website/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.0.0"
        },
        {
          "name": "react-dom",
          "manifest": "website/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.0.0"
        },
        {
          "name": "lucide-react-native",
          "manifest": "packages/onboarding-ui/package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.545.0"
        },
        {
          "name": "react-native-gesture-handler",
          "manifest": "packages/onboarding-ui/package.json",
          "ecosystem": "npm",
          "version_constraint": ">=2.0.0"
        },
        {
          "name": "react-native-reanimated",
          "manifest": "packages/onboarding-ui/package.json",
          "ecosystem": "npm",
          "version_constraint": ">=3.0.0"
        },
        {
          "name": "react-native-svg",
          "manifest": "packages/onboarding-ui/package.json",
          "ecosystem": "npm",
          "version_constraint": ">=13.0.0"
        },
        {
          "name": "zod",
          "manifest": "packages/onboarding-ui/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.1.11"
        },
        {
          "name": "@react-native-async-storage/async-storage",
          "manifest": "packages/onboarding/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.0"
        },
        {
          "name": "@tanstack/react-query",
          "manifest": "packages/onboarding/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.64.2"
        },
        {
          "name": "zod",
          "manifest": "packages/onboarding/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.1.11"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 3,
        "merged_prs": 117,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 3
      },
      "bus_factor": 2,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "Samox",
          "commits": 143,
          "avatar_url": "https://avatars.githubusercontent.com/u/6906559?v=4"
        },
        {
          "type": "User",
          "login": "P0labrD",
          "commits": 91,
          "avatar_url": "https://avatars.githubusercontent.com/u/57703518?v=4"
        },
        {
          "type": "User",
          "login": "Arlevoy",
          "commits": 49,
          "avatar_url": "https://avatars.githubusercontent.com/u/26787996?v=4"
        },
        {
          "type": "User",
          "login": "Sametaien",
          "commits": 7,
          "avatar_url": "https://avatars.githubusercontent.com/u/60843980?v=4"
        }
      ],
      "contributors_sampled": 4,
      "top_contributor_share": 0.493
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "build.yml",
        "deploy-docs.yml",
        "publish.yml"
      ],
      "has_docs_dir": false,
      "linter_configs": [
        "eslint.config.js"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "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": 10,
            "reason": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 7 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 0,
            "reason": "license file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 2,
            "reason": "dependency not pinned by hash detected -- score normalized to 2",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "56 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "8a0267bb1407ed5aa8abd78b9273ba10dc9c7be8",
        "ran_at": "2026-07-22T15:18:04Z",
        "aggregate_score": 3.7,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-17T13:27:48Z",
      "oldest_open_prs": [
        {
          "number": 74,
          "created_at": "2026-06-05T12:31:22Z",
          "last_comment_at": "2026-06-05T12:32:29Z",
          "last_comment_author": "cloudflare-workers-and-pages"
        },
        {
          "number": 112,
          "created_at": "2026-06-24T10:16:08Z",
          "last_comment_at": "2026-06-24T10:17:46Z",
          "last_comment_author": "cloudflare-workers-and-pages"
        },
        {
          "number": 122,
          "created_at": "2026-07-16T15:46:11Z",
          "last_comment_at": "2026-07-16T15:47:35Z",
          "last_comment_author": "cloudflare-workers-and-pages"
        }
      ],
      "last_merged_pr_at": "2026-07-17T13:26:24Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/Rocapine/react-native-onboarding",
    "host": "github.com",
    "name": "react-native-onboarding",
    "owner": "Rocapine"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 61,
      "inputs": {
        "security": 37,
        "vitality": 89,
        "community": 32,
        "governance": 64,
        "engineering": 72
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 89,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 82,
            "inputs": {
              "commits_last_year": 290,
              "human_commit_share": 1,
              "days_since_last_push": 5,
              "active_weeks_last_year": 26
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "26/52 weeks with commits",
                "points": 18,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 26
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "290 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 290
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 59,
              "latest_release_tag": "v1.59.0",
              "releases_from_tags": false,
              "days_since_latest_release": 5,
              "mean_days_between_releases": 2.4
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "59 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 59
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~2.4 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 2.4
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 5,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 5 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "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": 32,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 1,
              "stars": 2,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "2 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "at_risk",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 45,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "no license file detected",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "license_absent",
                    "params": {}
                  }
                ],
                "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 65,
            "inputs": {
              "packages": [
                "@rocapine/react-native-onboarding",
                "@rocapine/react-native-onboarding-ui"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 8244
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "8,244 downloads/month across npm",
                "points": 52.2,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 8244,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 64,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "moderate",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 52,
            "inputs": {
              "bus_factor": 2,
              "contributors_sampled": 4,
              "top_contributor_share": 0.493
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "2 contributor(s) cover half of all commits",
                "points": 25.2,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 49% of commits",
                "points": 11.4,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 49
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "4 contributors",
                "points": 5.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 7 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 70,
            "inputs": {
              "merged_prs": 117,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 3
            },
            "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": "117/120 decided PRs merged",
                "points": 37.3,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 117,
                      "decided": 120
                    }
                  }
                ],
                "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": null,
            "notes": [],
            "value": 45,
            "inputs": {
              "followers": 2,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "Rocapine",
              "public_repos": 10,
              "account_age_days": 775
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "organization-owned",
                "points": 30,
                "status": "met",
                "details": [
                  {
                    "code": "owner_organization",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "2 followers of Rocapine",
                "points": 3.4,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 2,
                      "login": "Rocapine"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "10 public repos, account ~2 yr old",
                "points": 11.8,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 10
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 2
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@rocapine/react-native-onboarding",
                "@rocapine/react-native-onboarding-ui"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 5
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "2 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 2,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 5 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "93 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 93
                    }
                  }
                ],
                "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": 72,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "3 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "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": "eslint.config.js",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.js"
                    }
                  }
                ],
                "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": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 55,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": "https://react-native-onboarding.pages.dev",
              "has_readme": true,
              "has_docs_dir": false,
              "has_description": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://react-native-onboarding.pages.dev",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 37,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 37,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 3.7
            },
            "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": "30 out of 30 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 7 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow 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 2",
                "points": 1,
                "status": "partial",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "56 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 6
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "good",
        "name": "AI Readiness",
        "value": 79,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 13672
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 66,
            "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": true,
              "typecheck_configs": [
                "example/tsconfig.json",
                "packages/onboarding-ui/tsconfig.json",
                "packages/onboarding/tsconfig.json",
                "website/tsconfig.json"
              ],
              "agent_commit_share": 0.52,
              "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": "eslint.config.js",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.js"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "example/tsconfig.json, packages/onboarding-ui/tsconfig.json, packages/onboarding/tsconfig.json, website/tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "example/tsconfig.json, packages/onboarding-ui/tsconfig.json, packages/onboarding/tsconfig.json, website/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": "52 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 52,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 2",
                "points": 2,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 47028,
              "source_files_sampled": 233,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/233 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 233,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "good",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "example_dirs": [
                "example"
              ],
              "has_mcp_signal": false,
              "api_schema_files": [
                "openapi.yaml",
                "website/static/openapi.yaml"
              ]
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": "openapi.yaml, website/static/openapi.yaml",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "openapi.yaml, website/static/openapi.yaml"
                    }
                  }
                ],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "example",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "example"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
    "deps.dev does not index npm:@rocapine/react-native-onboarding@1.59.0; advisories assessed against the repository dependency graph instead"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-22T15:18:24.110238Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/r/Rocapine/react-native-onboarding.svg",
  "full_name": "Rocapine/react-native-onboarding",
  "license_state": "absent",
  "license_spdx": null
}

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

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

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