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

reticlehq / reticle

AI agents can generate code, but they still struggle to understand what they build. Reticle gives them runtime perception of web applications.

TypeScript · JavaScript自定义许可证★ 191 星标⑂ 18 复刻始于 2026年6月在 GitHub 上查看 ↗

reticlehq/reticle 的健康指数为 100 分中的 68 分,处于「中等」区间。 其得分最高的类别是Engineering Quality(88/100),最低的是Security(47/100)。 最近一次更新在 3 天前。 近期的大部分工作由 1 位贡献者完成。

68
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

Reticle组织
2 关注者1 个公开仓库始于 2026年6月

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

软件包生态系统

按类别列示的指标

活力

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

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

发布纪律

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

社区与采用

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

68中等 · 占总体的 18%
评分方式
37/60星标 — 191 个星标
10.3/25复刻 — 18 个复刻
3.3/15关注者 — 5 位关注者
所用输入
forks18
stars191
watchers5
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

86优秀
评分方式
22.5/22.5README
16.9/22.5许可证 — 存在许可证文件,但不是可识别的许可证
18/18CONTRIBUTING 指南
13.5/13.5行为准则
0/7.2议题模板
6.3/6.3PR 模板
所用输入
has_readme
has_license
has_contributing
has_issue_template
has_code_of_conduct
has_pull_request_template
评分方式
55.4/80月度下载量 — npm 合计每月 14,330 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packages@reticlehq/core, @reticlehq/next, @reticlehq/react, @reticlehq/server, @reticlehq/browser, @reticlehq/vite-plugin, @reticlehq/babel-plugin, @reticlehq/eslint-plugin
dependents
ecosystemsnpm
total_downloads
monthly_downloads14,330
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

57中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
2.7/13.5贡献者广度 — 2 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 4 contributing companies or organizations
所用输入
bus_factor1
contributors_sampled2
top_contributor_share0.998
评分方式
46.8/46.8议题解决 — 100% 的议题已关闭
38.2/38.3PR 接受 — 已裁定的 PR 中 13/13 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs13
open_issues0
closed_issues15
issue_closed_ratio1
closed_unmerged_prs0
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
3.4/25所有者影响力 — reticlehq 有 2 位关注者
2.3/25既往记录 — 1 个公开仓库,账户约 0 年
所用输入
followers2
owner_typeOrganization
is_verified
owner_loginreticlehq
public_repos1
account_age_days23
评分方式
25/25已发布且可解析 — npm 上有 8 个软件包
35/35发布时效 — 最近一次发布于 5 天前
20/20版本历史 — 5 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packages@reticlehq/core, @reticlehq/next, @reticlehq/react, @reticlehq/server, @reticlehq/browser, @reticlehq/vite-plugin, @reticlehq/babel-plugin, @reticlehq/eslint-plugin
ecosystemsnpm
any_deprecated
min_days_since_publish5

工程质量

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

88优秀 · 占总体的 20%

工程实践

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

文档

100优秀
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://www.reticle.sh
10/10仓库描述
10/10主题标签 — 8 个主题标签
10/10Wiki
所用输入
topicsagent-testing, ai-testing-tool, automated-testing, testing-tool, agent-verification, playwright-mcp, proof-layer, reticle-mcp
has_wiki
homepagehttps://www.reticle.sh
has_readme
has_docs_dir
has_description

安全

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

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

安全态势

34存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 无数据
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 4 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
2.2/2.5许可证 — license file detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
5/5Security-Policy — security policy file detected
0/7.5Signed-Releases — 无数据
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 24 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate3.4
已排除计分(无数据或不适用):ci_tests, signed_releases。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
25/25间接依赖不含已知公告 — 没有间接依赖携带已知公告
0/40没有长期未处理的公告 — 没有公告带有发布日期
所用输入
sourceosv
advisories0
affected_packages0
assessed_packages1
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
已排除计分(无数据或不适用):没有长期未处理的公告。 其余权重已重新归一化。 比对的是 npm:@reticlehq/core@2.1.0 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 1 个软件包。 未对可达性进行分析。

AI 就绪度

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

80良好 · 占总体的 0%
评分方式
45/45代理指令 — CLAUDE.md
15/15机器可读文档(llms.txt) — 存在 llms.txt
40/40可读的提交历史 — 100 次人类提交中有 97 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.97
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes5,224
评分方式
0/18一条命令的引导启动
22/22自动化测试
11/11Lint / 格式化配置 — eslint.config.mjs
11/11静态类型检查 — apps/bench-app/tsconfig.json, apps/demo/tsconfig.json, apps/examples/next/tsconfig.json, apps/examples/remix/tsconfig.json, apps/next-smoke/tsconfig.json, packages/babel-plugin/tsconfig.json, packages/browser/tsconfig.json, packages/core/tsconfig.json, packages/eslint-plugin/tsconfig.json, packages/protocol/tsconfig.json, packages/react/tsconfig.json, packages/server/tsconfig.json, packages/test/tsconfig.json, packages/vite-plugin/tsconfig.json, tsconfig.json
10/10可复现环境 — lockfile
10/10已体现的代理实践 — 最近 100 次提交中有 93 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
所用输入
has_nix
has_tests
lockfilespnpm-lock.yaml
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configsapps/bench-app/tsconfig.json, apps/demo/tsconfig.json, apps/examples/next/tsconfig.json, apps/examples/remix/tsconfig.json, apps/next-smoke/tsconfig.json, packages/babel-plugin/tsconfig.json, packages/browser/tsconfig.json, packages/core/tsconfig.json, packages/eslint-plugin/tsconfig.json, packages/protocol/tsconfig.json, packages/react/tsconfig.json, packages/server/tsconfig.json, packages/test/tsconfig.json, packages/vite-plugin/tsconfig.json, tsconfig.json
agent_commit_share0.93
toolchain_manifests
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — TypeScript(静态类型)
55/55可控的文件大小 — 采样的 574 个源文件中有 0 个超过 60KB
所用输入
primary_languageTypeScript
largest_source_bytes31,860
source_files_sampled574
oversized_source_files0
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
20/20MCP 服务器
40/40可运行示例 — examples
所用输入
example_dirsexamples
has_mcp_signal
api_schema_files

关键数据

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

数据采集警告

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

更多细节

Star 与 Fork 历史 0 ★ / 18 ⇿
0Star
18Fork
9发布

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

0481216201832026-062026-072026-07
主版本 2次版本 4修订 3
OpenSSF Scorecard 3.4 / 10
3.4综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
不适用CI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
10Contributorsproject has 4 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
9Licenselicense file detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
10Security-Policysecurity policy file detected
不适用Signed-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities24 existing vulnerabilities detected
直接依赖 31
注册表软件包版本约束清单文件
npmcors^2.8.5apps/api/package.json
npmexpress^4.21.2apps/api/package.json
npm@reticlehq/browserworkspace:*apps/bench-app/package.json
npm@reticlehq/reactworkspace:*apps/bench-app/package.json
npmreact^19.0.0apps/bench-app/package.json
npmreact-dom^19.0.0apps/bench-app/package.json
npmzustand^5.0.14apps/bench-app/package.json
npm@reticlehq/serverworkspace:*apps/e2e/package.json
npm@reticlehq/testworkspace:*apps/e2e/package.json
npmplaywright^1.48.0apps/e2e/package.json
npm@reticlehq/browserworkspace:*apps/large-dom-bench/package.json
npmnext^15.1.0apps/next-smoke/package.json
npmreact^19.0.0apps/next-smoke/package.json
npmreact-dom^19.0.0apps/next-smoke/package.json
npm@reticlehq/browserworkspace:*apps/vibe-builder-demo/package.json
npm@reticlehq/coreworkspace:*packages/browser/package.json
npm@testing-library/dom^10.4.1packages/browser/package.json
npmzod^3.24.1packages/core/package.json
npm@typescript-eslint/utils^8.20.0packages/eslint-plugin/package.json
npm@babel/core^7.26.0packages/next/package.json
npm@reticlehq/babel-pluginworkspace:*packages/next/package.json
npm@reticlehq/coreworkspace:*packages/protocol/package.json
npm@reticlehq/browserworkspace:*packages/react/package.json
npm@reticlehq/coreworkspace:*packages/react/package.json
npm@modelcontextprotocol/sdk^1.13.0packages/server/package.json
npm@reticlehq/coreworkspace:*packages/server/package.json
npmws^8.18.0packages/server/package.json
npmzod^3.24.1packages/server/package.json
npm@babel/core^7.26.0packages/vite-plugin/package.json
npm@reticlehq/babel-pluginworkspace:*packages/vite-plugin/package.json
npm@reticlehq/coreworkspace:*packages/vite-plugin/package.json
全部依赖 未采集

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

依赖安全公告 0

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

没有已知公告影响已评估的依赖。

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "agent-testing",
        "ai-testing-tool",
        "automated-testing",
        "testing-tool",
        "agent-verification",
        "playwright-mcp",
        "proof-layer",
        "reticle-mcp"
      ],
      "is_fork": false,
      "size_kb": 120140,
      "has_wiki": true,
      "homepage": "https://www.reticle.sh",
      "languages": {
        "CSS": 29321,
        "HTML": 34276,
        "Astro": 909,
        "Shell": 11005,
        "JavaScript": 490999,
        "TypeScript": 2259091
      },
      "pushed_at": "2026-07-20T12:44:55Z",
      "created_at": "2026-06-11T07:53:01Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-23T16:53:12Z",
      "description": "AI agents can generate code, but they still struggle to understand what they build. Reticle gives them runtime perception of web applications.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": "NOASSERTION",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript",
        "JavaScript"
      ]
    },
    "owner": {
      "blog": "https://reticle.sh",
      "name": "Reticle",
      "type": "Organization",
      "login": "reticlehq",
      "company": null,
      "location": "United States of America",
      "followers": 2,
      "avatar_url": "https://avatars.githubusercontent.com/u/298235407?v=4",
      "created_at": "2026-06-30T10:34:23Z",
      "is_verified": null,
      "public_repos": 1,
      "account_age_days": 23
    },
    "license": {
      "state": "custom",
      "spdx_id": null,
      "raw_spdx": "NOASSERTION",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.1.0",
          "kind": "minor",
          "published_at": "2026-07-18T10:09:41Z"
        },
        {
          "tag": "v2.0.1",
          "kind": "patch",
          "published_at": "2026-07-17T16:18:55Z"
        },
        {
          "tag": "v2.0.0",
          "kind": "major",
          "published_at": "2026-07-11T11:46:14Z"
        },
        {
          "tag": "v1.3.1",
          "kind": "patch",
          "published_at": "2026-07-07T07:47:47Z"
        },
        {
          "tag": "v1.2.0",
          "kind": "minor",
          "published_at": "2026-06-27T09:12:59Z"
        },
        {
          "tag": "v1.0.0",
          "kind": "major",
          "published_at": "2026-06-22T07:09:31Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-06-20T09:22:04Z"
        },
        {
          "tag": "v0.6.10",
          "kind": "patch",
          "published_at": "2026-06-18T14:34:45Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-06-15T22:01:11Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "2e0a970c09623667e4310e3f812c3029168a50a7",
          "body": "example-remix's `typecheck` ran bare `tsc`, which needs React Router 7's generated route types\n(`./+types/*`). They existed locally (stale, from a prior dev run) so it passed, but CI's fresh\ncheckout has none — tsc failed with \"Cannot find module './+types/root'\". Run `react-router typegen`\nfirst, the framework's standard CI typecheck.\n\npre-commit.sh green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(example-remix): generate route types before typecheck (CI)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T10:02:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4f982c13ce74f34b302d446419b2539c3be4bae6",
          "body": "…React\n\nThe apps/ regroup added a `typecheck` script to example-next, but the app never declared @types/react\n— locally it resolved via workspace hoisting, so it passed; under CI's strict --frozen-lockfile layout\neach app sees only its own declared deps, so Next's generated .next/types (which refere\n[…]\n/react / @types/react-dom / typescript as\ndevDependencies, matching example-remix (which already passes CI).\n\npre-commit.sh green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(example-next): declare @types/react so the CI typecheck resolves …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T09:58:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4d92b45b0c12d3e37360595c9ebdb6ea543eb651",
          "body": "Bump all @reticlehq/* packages 2.0.1 → 2.1.0 and document the release.\n\nA minor, back-compatible release: the SDK gains network-tab, client-storage, and web-perf observation\n(with opt-in, redacted, capped body capture and SSE/WebSocket frames), credential redaction is hardened\nacross every new surfa\n[…]\nracles are fixed, and the event buffer moves to an O(1) head-index\nring. On-disk flow files remain version 1; no breaking changes.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: v2.1.0 — network/storage/perf observation + redaction hardening",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T07:19:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2b4d5581d854add2286060876d7a7befbd2e3b17",
          "body": "…ry + truncation\n\nClosing the remaining observer test gaps surfaced one more leak: for a body like\n`Authorization: Bearer <token>`, the key/value pass redacted Authorization's value as just \"Bearer\"\n(it stops at whitespace) and left the token behind, and the auth-scheme rule could no longer match.\nR\n[…]\nas untested), binary WS frame reported by byte size,\nand oversized-body truncation with the *Truncated flag.\n\npre-commit.sh green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): redact Bearer tokens before key/value; cover SSE + bina…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T07:11:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "adfea4d793ef53c7835e5f7bd7c2a707c38d1d82",
          "body": "…bserver coverage\n\nperf observer (was thin on semantics + tests):\n- CLS is now cumulative — a running sum of qualifying shifts — instead of emitting each isolated shift\n  value under a name ('cls') that implies cumulative. (naive sum; no session-windowing — noted inline.)\n- LCP no longer emits every\n[…]\nain + sensitive redaction + url-decode), single-area session/cookies scoping,\n  and the safeArea throw path.\n\npre-commit.sh green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): correct perf metric semantics + guard storage; extend o…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T07:08:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5e3fd839bea45f7ad3f1ed2d04cf19788a40af27",
          "body": "An adversarial audit of the network observer surfaced real defects, several in code from the prior\nredaction pass:\n\nRedaction (security):\n- redactText's auth-scheme rule over-redacted prose — \"Basic subscription includes…\" became\n  \"Basic [REDACTED] includes…\". Require credential shape (16+ chars AN\n[…]\ncted, JSON value-side JWT scrub, URLSearchParams/FormData bodies, and\nisSensitiveKey/scrubKnownSecrets units. pre-commit.sh green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): harden network redaction + fix XHR listener accumulation",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T07:02:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3fc7abacf08068b5ca940f51650b9b8437ab32e1",
          "body": "Verification flagged presenter.test.ts (849) as over the CLAUDE.md 600-line cap — the diff-scoped\npre-commit gate never caught it because the file wasn't restaged. Extract the shared fixtures\n(FAST_* timings, flush/wait/until, trackGlowFlips, dataOn/dataBusy selectors) into\npresenter-test-helpers.ts\n[…]\nlines over, a single feature's cohesive port-resolution\nbattery that gains nothing from an artificial seam.\n\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(browser): split the 849-line presenter test over the 600 cap",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T06:40:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "381f7c12c4ad359825e621330e31eb4a57ecbf0d",
          "body": "A verification pass over the network observer found that body redaction only covered PARSED JSON:\nsanitizeForTransport redacts keys inside an object, so with captureBodies enabled (dev-only, default\nOFF) a form-urlencoded `password=secret` post, a text/plain/xml body, a non-JSON SSE/WS frame, or a\n`\n[…]\n//user:pass@host` userinfo in\nredactUrl.\n\nTests: form-urlencoded password redaction + URL userinfo redaction. pre-commit.sh green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): redact credentials in non-JSON bodies + URL userinfo",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T06:34:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7f2699fef830ab8f57691400211426809c2f3c1d",
          "body": "…lements the same way\n\nThe in-session engine (replayProgram) and the on-disk engine (flow-replay) each re-parsed a QUERY\nCommandResult into live element refs with their own inline copy of the same map/filter. Hoist that into\na single queryRefs(result) in replay.ts; both engines now resolve anchors t\n[…]\nlay-engine dedup begun\nwith replayActionArgs / compileActStep / ambiguousTestidNote.\n\npre-commit.sh: green. 188 server tests pass.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(flows): one shared queryRefs — both replay engines extract e…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T04:10:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "12ee6c01eade81f7a52229ca4386503e127393fa",
          "body": "Regroup the flat apps/ tree by job — the four example apps move to apps/examples/{react,next,\nremix,astro} (package names unchanged). Update the pnpm-workspace glob (+apps/examples/*) and the\n.prettierignore pattern; workspace re-links and the full build/lint/typecheck/test gate stays green.\n\nThe fi\n[…]\npath coupling, so moving them would break the benchmark story just repaired —\nworking beats tidy for those.\n\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(apps): group the example apps under apps/examples/",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T04:04:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ea46475b1f63a50e0a79dde0d6d1f164be92d534",
          "body": "…ting\n\nCloses the two remaining hot-path costs the audit flagged:\n- Eviction advanced a HEAD index instead of shift()/splice() — O(1) per dropped event, vs O(n)\n  per shift (i.e. O(n) per push at the 2000-event steady state under DOM/animation floods). The\n  dead prefix is compacted out once it domi\n[…]\ncompaction path); caller-provided\nbyte size drives eviction. 202 buffer/session/predicate/bridge tests pass. pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(server): RingBuffer head-index ring + parse-boundary byte accoun…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T04:01:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "75d2b277da7e4a188b40103eb63b6f60ecc7ac38",
          "body": "… orphan race)\n\nTwo racing `reticle mcp`/`serve` on the same port both passed the pre-spawn probe (nothing\nlistening yet), both spawnDaemon, the second clobbered the pidfile with childB's pid, then\nchildB (EADDRINUSE) removePid-unlinked the pidfile owned by the LIVE childA — orphaning the\nrunning da\n[…]\non as the pure, tested shouldRemovePid().\n\nTDD: shouldRemovePid guard cases; 53 daemon/cli/index tests pass. pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(daemon): O_EXCL spawn-lock + pid-guarded removePid (eliminate the…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:57:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "82d09df2207d6c46534b21903ea7226a24824458",
          "body": "flow-tools.ts (565 lines) mixed the FLOW_HEAL ToolDef schema with the ~165-line heal state machine.\nMove healFlow + HEAL_MESSAGES + toChange into heal-run.ts (sibling of flow-replay-run.ts, per the\naudit), and hoist the shared sessionProjectId into the leaf flow-replay-run.ts so both flow-tools and\n\n[…]\ntools is now a thin ToolDef array (382 lines).\n\nBehavior identical (heal + flow tool suites pass, 31 tests). pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(flows): extract heal-run.ts from flow-tools (organisation)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:51:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c48245425d6fa78b7150242d263f9fff4243f947",
          "body": "…tDaemon() (DRY)\n\nThe drive-provider resolution (driveUrl launch+own → CDP attach → none, with storageState/\ninjectConnect plumbing) was ~30 lines duplicated VERBATIM between start() and startDaemon() —\nthe exact kind of divergence the bridge-security comment warns let daemon mode run with a\ndiffere\n[…]\nsplits (flow-tools,\nsession, constants) are preventive (under the 600 cap) and deferred to avoid churn/risk.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(server): extract shared resolveRealInput from start() + star…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:42:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "729398d021946e0137b2098bc2d23cc0ecdd5d5e",
          "body": "costHint set `bytes = json.length` (UTF-16 code units) but labeled it bytes and used it to gate the\nlarge-timeline recommendation — a multibyte-heavy payload was under-counted. Use Buffer.byteLength.\n\nDeliberately NOT adding width-capping to capDepth: width is sanitizeForTransport's responsibility\n(\n[…]\n perf optimization, noted.\n\nASCII payloads unaffected (byteLength == length); output-budget tests unchanged. pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): costHint reports real UTF-8 bytes, not UTF-16 code units",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:40:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c9ce896aafc61c6fd63c75743871ec31f512b03d",
          "body": "…ngines\n\nThe two replay engines (replayProgram over an in-session CompiledProgram, flow-replay over an\non-disk FlowFile) had the ambiguous-testid note (\"ambiguous testid 'x', used first match\") written\nverbatim in both — a rule-3 free string an agent reads to judge a brittle locator, and one that\nco\n[…]\neferred deliberately over a rushed change.\n\nBehavior identical (replay/heal/record-replay suites unchanged). pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(flows): share the ambiguous-testid replay note across both e…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:38:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9ba1c12355189bd82c5513974ae9e874232ee4bc",
          "body": "run.mjs ran only specs listed in ORDER (ORDER.filter(present)), so a spec on disk but not in\nORDER was silently un-run — exactly how new-features-test.mjs rotted with no signal. Keep ORDER\nfor sequencing, add an explicit SKIP set, and hard-error when a present spec is in neither, so\nevery new spec m\n[…]\nicitly skipped with a reason).\n\nVerified: all 15 present specs are classified; the guard doesn't false-trip. pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(e2e): fail loud on an unrouted spec instead of silently dropping it",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:35:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "51139fee705b6e71ef3b8ce3b27b8536dc5fd7bd",
          "body": "…doc refs\n\n- Add `typecheck: tsc --noEmit` to example-next and example-remix (both typecheck clean) so\n  `turbo typecheck` covers them — a type break no longer sails through until the heavy integration\n  suite boots a browser. (example-react/astro have no tsconfig — left as-is.)\n- bench/README.md bo\n[…]\nhe two SVGs it embeds so the flagship doc renders on a fresh clone\n  instead of showing broken image links.\n\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs/ci: typecheck example apps; fix stale bench fixture + benchmark …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:33:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "18eb193e8de788fb20369560cd3c50513a12bfdc",
          "body": "… counts\n\nBoth counted console errors via eventsSince(0), but the ring buffer evicts — so on a chatty page\nthe count was silently capped with no signal (unlike network/console/observe, which surface a\nbufferEnvelope). Spread bufferEnvelope(session) into both results so a regression check can tell a\n\n[…]\nt\" reference the\ndiscovery tool doesn't hold; guessing the scope could break legitimate cross-tab discovery.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): buffer-honesty on reticle_diff / reticle_explore console…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:29:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d8a73056bb3f0d2aae46a87c6d382a8ac046f086",
          "body": "The MutationObserver/snapshot walked only light-DOM `.children`, so a web-component / design-system\napp (or a same-origin iframe editor) was invisible — reticle_snapshot showed nothing inside, a\nsystematic false negative on a whole category of modern apps. The walk now also descends into an\nelement'\n[…]\nine piercing shadow boundaries is a larger follow-up\n(testing-library does not cross shadow roots natively).\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(browser): snapshot pierces open shadow DOM + same-origin iframes",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:26:48Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "558bc8f9a93b6ebe57044faf19a7d4ed929006ef",
          "body": "…can't do)\n\nAdd observers/perf.installPerf — a PerformanceObserver for largest-contentful-paint, layout-shift\n(excluding input-driven shifts per the CLS spec), and long tasks, emitting EventType.PERF into the\nring buffer. Lets an agent assert \"no layout shift on load\" or \"LCP under 2.5s\" from real m\n[…]\nthe SDK bootstrap.\n\nTDD: LCP/CLS/longtask emitted, recent-input shift excluded; clean no-op without the API.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(perf): observe LCP / CLS / long tasks (verification screenshots …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:24:53Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a1f80a9a29a321b74aa018e5e0eed1033f5420c5",
          "body": "…verification)\n\nThe highest-value uncovered domain: auth/session verification had nowhere to live (only the\nmanual reticle.state() store registry). Add reticle_storage — read localStorage,\nsessionStorage, and readable cookies from inside the app to verify \"token persisted after\nlogin\", \"cart survive\n[…]\nind spot.\n\nTDD: browser readStorage (redaction + area scoping); server tool (snapshot / key-hit / key-miss).\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: storage/cookie observation + reticle_storage (auth-persistence …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:21:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "83fe9d6461539d0765a29268690af9fdd4b3cf9d",
          "body": "… message\n\nHelloMessageSchema pins protocolVersion, so an old browser SDK's HELLO failed the strict parse\nand was dropped as a generic invalid message — the agent then hit NO_SESSION_CONNECTED, which\ndiagnoses a PORT mismatch (the wrong cause). Detect the version-mismatched HELLO before the\ngeneric \n[…]\nbrowser\".\n\nTDD: a HELLO with a bumped protocolVersion closes 1008 with the distinct reason. 11 bridge tests.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(bridge): a protocol-version-mismatched HELLO gets a clear upgrade…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:14:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "12511ea5cdeabc2dd72fe957b133fd382107aa53",
          "body": "…r-event)\n\n#evict shift()ed one event at a time in a loop, re-indexing the whole array each time —\nO(k·n) for a k-event bulk age-eviction (the DOM/animation floods the codebase documents).\nCompute the head-drop count for cap/bytes/age first, then splice once (O(n)). Exact same\ndrop decisions and byt\n[…]\nsearch accessors).\n\nTDD: bulk age-eviction drops 50 expired events in one pass with correct counts. 5 tests.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(server): batch RingBuffer eviction into one splice (was shift-pe…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:09:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c2a4415ff67a288c929587da5b95c2bb43d58f3b",
          "body": "ContractFileSchema, RunEvidenceSchema, CapabilityFlowSchema, RiskZoneSchema (types.ts),\nVerificationEvidenceSchema, RunSignatureSchema (verification-run.ts), and RecordedFlowSchema\n(flow-types.ts) had no exported z.infer, so consumers re-inferred them by hand while their\nsiblings export theirs. Add the missing type aliases.\n\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): export inferred types for the remaining public schemas",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:06:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "517179980331e5f905d572a234ddd4ce6e6ebe24",
          "body": "skip() and layoutSignature() each called getComputedStyle on every walked node — two forced\nsynchronous style resolutions per node, the dominant snapshot cost on a large DOM. Split the\ncheap style-free skips into skipEarly(), resolve the computed style ONCE per surviving node,\nand thread it into both the display:none check and the layout signature.\n\nBehavior identical (47 dom tests unchanged). pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf(browser): resolve computed style once per node in the snapshot walk",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:03:53Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "94300c82911046d5a9ad43ef97c5da2ceb56bd31",
          "body": "…was ENOENT)\n\ninject.mjs hardcoded apps/demo/src/... paths, but those views moved to apps/bench-app/src/\nwhen demo was rebuilt into a minimal app — so every regression-detection bench (run-observation,\nagent-loop, ...) crashed with ENOENT on the first readFileSync, and the correctness half of the\nbe\n[…]\nots)\nand build the file table from it.\n\nVerified: all 8 regressions inject+revert cleanly against bench-app. pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(bench): repoint the regression injector at the real fixture app (…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T03:00:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "99553f1fde16f91d34d372e13f1b6db79282cebf",
          "body": "The cache evicted the oldest-INSERTED entry, so a hot (session,scope,mode) key that the agent\nkeeps re-snapshotting could be evicted while colder, more-recently-added keys survived — forcing\na spurious full snapshot (and the token blowup delta mode exists to avoid). recall() now touches\nthe key (del\n[…]\n) moves it to the most-recently-used end.\n\nTDD: a recalled hot key survives while the colder key is evicted. pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): SnapshotCache is now true LRU (was FIFO)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T02:58:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dc8cc14c4e2ab572701dedb97229a9677ac47ddd",
          "body": "…aths)\n\ntoon.ts (encoded on every MCP result) and selectPath/capDepth (every scoped state read) had\nno direct tests. Add them, pinning the tricky behaviors: TOON's \"\"-vs-unset value ambiguity,\nquote/backslash escaping, nested indentation; selectPath numeric-index + the dotted-key\nambiguity (v3.0 spl\n[…]\neys on a miss; capDepth negative-budget, maxDepth 0 size\nmarkers, and budget pruning.\n\n28 core tests -> +14. pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test(core): cover toon.ts and state-select (previously-untested hot p…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:44:32Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fa1379184cd8e73f59550883a9001db503485e17",
          "body": "Realtime UIs (chat, live dashboards, order status) went dark after the initial handshake —\nfetch/XHR capture can't see a long-lived stream. Subclass EventSource + WebSocket (gated\nbehind captureNetworkBodies, since a chatty stream is the high-volume case) and emit\nnet.stream events: connection open,\n[…]\n constructors.\n\nTDD: WS open/out/in frames captured with redacted payload; off by default. 15 network tests.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(network): capture SSE + WebSocket frames (Network 1f)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:42:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "46487f6bce85af78c5891f195af483521aaa74e5",
          "body": "…er reconnect)\n\n#sendRaw dropped the INCOMING message once the 500-deep offline queue was full, so after a\nreconnect the agent replayed 500 stale events and lost the most recent activity — exactly the\nwindow it cares about. Make it a ring: drop the oldest, push the newest. The overflow counter\nstill signals the gap.\n\nTDD: 503 offline events -> the 3 oldest drop, newest survives (500 kept). pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(transport): offline queue drops oldest, keeps newest (recency aft…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:37:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "03201f5ba019e6b459fcfa427124cdc1674a36ae",
          "body": "…as local\n\nA global install (npm i -g) lives under the npm global prefix, whose path ALSO contains\n/node_modules/, so the old check classified it as LOCAL — apply_update then npm-installed\ninto the user's OWN project, polluting their package.json. Extract a pure\nclassifyExecutionKind that checks the\n[…]\n. 8 update tests pass.\nNote: the pidfile-orphan spawn race (O_EXCL spawn-lock) remains as a separate change.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(update): detectExecutionKind no longer misreads a global install …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:34:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "131acfcae68cbeb37bd4d42431e4d251c9e039c1",
          "body": "…precise React noise filter\n\n- serialization MAX_TOTAL_CHARACTERS was MAX_MESSAGE_BYTES/8 (~1/8 of the 1MiB wire budget),\n  truncating legitimate state far below the real limit. UTF-8 is <=~3 bytes per UTF-16 unit, so\n  /4 never exceeds the byte budget and doubles usable state.\n- TOON header claimed\n[…]\non points at them.\n\nTDD: react keeps a user CheckoutProvider while still stripping Next internals (23 pass).\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: widen state char budget to a provably-safe /4; honest TOON doc; …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:32:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "658d0931dc10f8f92451a27e4758dfce62c0ab72",
          "body": "…f not label\n\n- resolveMaxContexts honored an explicit env value unbounded, so RETICLE_MAX_CONTEXTS=5000\n  would spawn 5000 browser contexts (memory/FD exhaustion — the fork bomb the comment warns\n  about). Add a generous hard ceiling (128): realistic operator overrides still win, abuse is\n  capped.\n[…]\n only when ref is empty.\n\nTDD: max-contexts hard-ceiling clamp; crawl same-label-distinct-refs both clicked.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): clamp explicit RETICLE_MAX_CONTEXTS; crawl dedupes by re…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:27:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a594049f78b26dafd01aee4b903b90b890d17a53",
          "body": "… 1b), opt-in\n\nThe core of the \"verify from inside\" gap: answer \"did the API return the RIGHT data?\".\nOpt-in via reticle.connect({ captureNetworkBodies: true }) — off by default (bodies cost\ntokens and can carry PII):\n- fetch reads a res.clone().text() so the app's stream is untouched; XHR reads res\n[…]\n in reticle_network.\n\nTDD: capture+redact both bodies; off-by-default; 1a meta all green (13 network tests).\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(network): capture request/response bodies + status meta (Network…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:24:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7f76e3410b2bcd01d9b5c9165ebb698140869532",
          "body": "…Network 1a)\n\nThe headline gap the maintainer named: net.request carried only the envelope\n(method/url/status/ok/durationMs). Add response metadata that needs no body capture,\nso an agent can tell an HTML error page served as 200 from real JSON and spot\nempty/oversized responses:\n- browser: netRespo\n[…]\na); bodies/headers (1b/1c) build on it next.\n\nTDD: network 1a test (fetch) + event-filters projection green.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(network): capture content-type, response size, and status text (…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:17:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a36d301ac1ea09c4cedb121c1d9d1385863e18be",
          "body": "check-boundaries.mjs only inspected package.json deps, so a node:* / Node-builtin import\nor a deep relative import across the boundary was invisible — the invariant was approximated,\nnot enforced. Add ESLint no-restricted-imports/no-restricted-globals:\n- browser + react source: no node:* or bare Nod\n[…]\nvigator/localStorage globals.\n\nVerified: injecting  into a browser file now fails lint; current tree clean.\n\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(lint): enforce the browser/server boundary at the import level",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:13:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "95e44e1330555b87530f811be3f12cb6271ba608",
          "body": "…flow\n\nheal-verify re-replayed the ENTIRE healed flow from the app's current state, but the\ndrift-detection replay had already executed the prefix. For a non-idempotent flow\n(create/submit/delete) the second full run double-executes those steps — a unique-constraint\nfailure or an already-in-end-stat\n[…]\nw's stable prefix now acts once across the whole heal (2 acts, not 3).\nAll 18 existing heal tests unchanged. pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(flows): heal-verify replays from the drifted step, not the whole …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:10:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "24f1950b4f4b4f0edddb1cb579081f1f8c3a10ea",
          "body": "actions-dom.hitTest and commands.isOccluded were two center-point hit-tests with subtly\nDIFFERENT semantics — commands' version missed the ancestor-contains case (a wrapping\nlabel read as an occluder). Extract one dom/occlusion.hitTestOccluder (the correct\nsuperset: 0-area guard + itself/ancestor/de\n[…]\ntest now joins it as shared DOM policy.\n\nTDD: occlusion.test.ts (5). Callers' click/command tests unchanged.\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(browser): one center-point occlusion hit-test (DRY)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:06:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9064f7e279973428aa2da7b650c8d14ae7ae6182",
          "body": "…nostic fields\n\nTwo related structuredContent-stripping bugs (safety-critical for the human-in-the-loop\ncontrol channel):\n\n- runTool skipped the pool-lease reminder + age cleanup nudge whenever a handler already\n  returned a session health block ('session' in result) — which a throttled/backgrounded\n[…]\nheir schemas.\n\nTDD: invoke-tool lease-when-session-present test; mcp withSessionEnvelope superset guard (3).\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: stop schema-strict clients from dropping spliced envelope + diag…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-18T01:02:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2ceda8862615e933105a3e8ddaf64bcb1c2f2992",
          "body": "…ectness)\n\nwaitForPredicate registered onEvent(() => check()) and check() ran evaluatePredicate,\nwhich for element/text/state issues a browser MATCH/STATE_READ round-trip. Every buffered\nevent during a wait fired a fresh, undebounced command — the only guard prevented double\nRESOLVE, not double DISP\n[…]\nhared choke point.\n\nTDD: a 50-event burst now triggers 1 trailing re-check, not 50 (was 51 commands, now 2).\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(perf): coalesce predicate re-checks (worst edge bottleneck + corr…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T21:11:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "28ece1a57eb04e7910e0f255c1e5687c1f41d1b3",
          "body": "…lse-positive\n\n- MCP_SSE_PATH/MCP_MESSAGE_PATH/STATUS_PATH lived in http-server.ts with a manual\n  'keep in sync with SKILL.md' note — the agent<->server wire contract split from the\n  rest of it. Move them next to RETICLE_WS_PATH in core so the daemon HTTP plane, the\n  stdio proxy, cli-launch, and \n[…]\n DNS-rebinding\n  comment) as an internal milestone label — strip IPv4 before the semver check (audit 05-8).\n\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(core): move MCP wire paths into core; fix pre-commit IPv4 fa…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T21:06:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f94f16422ad24bc969ba511304da4b4562a62b5c",
          "body": "…testable update-checker\n\n- init/mcp.ts hardcoded '@reticlehq/server' while update-checker/updater used the\n  package.json-derived RETICLE_NPM_PACKAGE — two sources, one able to drift. Point\n  init/mcp at RETICLE_NPM_PACKAGE so the npx registration, version check, and installer\n  all resolve from th\n[…]\ncuit,\n  registry-unreachable fallback, and the fetch/updateAvailable path.\n\nTDD: update-checker.test.ts (3). pre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(server): single source for the published-package identity + …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T21:01:26Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a7690a557e83d09c42f1fed51f6353bf450e6ed3",
          "body": "…(DDD)\n\nThe product's defining rule — signal/net/state = observable CONSEQUENCE (a wrong or\nhealed locator cannot fake it), element/text = weak PRESENCE — was implemented three\ntimes (flow-classify walks FlowExpect, assert-grade walks Predicate, flow-success\ncompiles). A contributor could strengthen\n[…]\n over the core helpers.\n\nTDD: consequence.test.ts (4). All existing grader tests green (behavior preserved).\npre-commit.sh: green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(core): hoist consequence-vs-presence classification to core …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:56:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "208d044847153c72960f464dcd23cbdc38511bba",
          "body": "redactUrl only masked query-string values and bailed early when there was no '?',\nso a single-use token in the URL PATH (/reset/<token>, /invite/<token>) was emitted\nverbatim into net.request events, flows, and run artifacts. Mask a token-length\nsegment (>=12 chars) that follows a known sensitive se\n[…]\nm) are left alone. Query redaction is unchanged.\n\nRED->GREEN: network.test.ts path-token cases. browser 368, typecheck/lint clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: redact path-embedded secrets (magic-link/reset/invite tokens)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:38:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f12d9fd2d2d4fdb72ed95ddf9ae44dbf5bcbe478",
          "body": "…ard; native pin timer\n\n- FLOW_SAVE_RECORDED handler returned { flowName } but the outputSchema (already\n  corrected) declares { name } — schema-strict clients got no flow name after a\n  recording save. Return the SaveSummary as-is. Tests updated to assert .\n- rollback() exited for the npx kind too,\n[…]\n  strand it on-screen. Use the SDK's nativeSetTimeout like every other SDK timer.\n\nbrowser 366, server 1019, typecheck/lint clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: FLOW_SAVE_RECORDED name field; npx rollback no longer rolls forw…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:36:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f058dbf29cbdda8af49f84d16a5c6b8177fafedf",
          "body": "…read)\n\nreadState called readStores() (which sanitizeForTransport-truncates: arrays capped\nat 200, depth 8) and THEN selectPath walked the truncated tree — so reticle_state\n{ path:'deployments.250.status' } on a 500-row store returned found:false, silently\nfailing the exact large-store feature it ad\n[…]\nb-tree first, sanitize only\nthe selection.\n\nRED->GREEN: commands.test.ts row-250-past-cap case. browser 366, typecheck/lint clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: scoped state read selects before the transport cap (large-store …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:32:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a22a5188f637c0330b5dbe62efdf2006e11f2111",
          "body": "postToSession resolved on any response and ignored statusCode, so a 401/404/500\nfrom the daemon was silently swallowed and the JSON-RPC call hung client-side with\nno diagnostic. Log non-2xx (the forward stays fire-and-forget).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: log non-2xx from the daemon MCP endpoint instead of swallowing it",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:29:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a7d46a8f2565d49f743184c32280d4eff1cf4e74",
          "body": "- route observer: lastHref was only updated on popstate/hashchange, never after\n  pushState, so a Back nav compared against a stale href, tripped the to===from\n  guard, and emitted no route.change. Update lastHref inside fire().\n- recorder: capture <select> changes as a SELECT step (was dropped enti\n[…]\n double onChange side effect no longer fires on replay).\n\nRED->GREEN: route.test.ts (+1), recorder.test.ts (+2). browser 365 pass.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: route back-nav drop + recorder select/double-record",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:29:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "09e89a5817347464488e70cdbb900bb5810bca89",
          "body": "Binding beyond localhost (RETICLE_HOST=0.0.0.0) with an empty allow-list left\n#originAllowed rejecting every non-loopback browser at the WS handshake: the bridge\ncame up but accepted nothing, surfacing only an origin_rejected log. Throw a clear\nstartup error naming RETICLE_ALLOWED_ORIGINS instead.\n\n\n[…]\ng token requirement — no change needed there.\n\nTest added next to the token-required case. server 1019 pass, typecheck/lint clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: bridge refuses to start on a remote bind with no allowedOrigins",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:23:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f647b0ffe08f957509c44a840ee66d31f65ba402",
          "body": "- ContractFileSchema/ProjectFileSchema version was z.number() (accepted any version),\n  so a v1 reader silently parsed a future v2 file and stripped its unknown fields.\n  Pin to z.literal(CONTRACT_FILE_VERSION)/z.literal(PROJECT_FILE_VERSION) like FlowFile.\n- decision.ts/flow-report.ts compared step\n[…]\nant (rule 3) so a rename can't desync them.\n\nRED->GREEN: types.version.test.ts. typecheck 18/18, lint 10/10, core 46, server 1018.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: pin on-disk file versions; name the success-step tool constant",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:20:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1704663bb6665413b8199a48400a5999e6074ee1",
          "body": "…hq/core\n\nThe reticle bin ships in @reticlehq/server; @reticlehq/core has no executable. updater\ninstalled @reticlehq/core@version (so apply_update could never update the running server)\nand update-checker polled core's registry URL (right version only by lockstep luck).\n\n- Add RETICLE_NPM_PACKAGE i\n[…]\na separate, harder heuristic fix; deferred. The package-name fix\nalready removes the destructive 'wrong package' half of that bug.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: self-update installs @reticlehq/server, not schema-only @reticle…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:16:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e6639bb423e6a91bdf2cbdcc5ea749e3f33745b0",
          "body": "… verifies nothing)\n\n- evalSettled: a NET_PENDING with no matching NET_REQUEST is a request still in flight;\n  the page is NOT settled even if the DOM has gone quiet. Prevents act_and_wait/assert\n  passing while a save is mid-flight — the exact false-green settled exists to catch.\n- evalConsole: con\n[…]\narn/error; fail loudly on any uncaptured level.\n\nRED->GREEN: predicate-eval.oracle.test.ts (4 tests). Full server suite 1018 pass.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: two false-green oracles (settled ignores in-flight; console info…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:16:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5477c6459108959eca71e33789a68be41171b54d",
          "body": "- Replace 3 local asString/asRecord/asNumber reimplementations (flows.ts,\n  replay.ts, event-filters.ts) with the shared tools-helpers exports\n- Consolidate 4 more local sessionIdShape copies onto the shared tool-kit shape\n  (project/visual/viewport/network-mock tools)\n- Delete dead RingBuffer.reset\n[…]\nndleVersion() now logs SERVER_VERSION instead of re-reading package.json\n\nVerified: typecheck 18/18, lint 10/10, server 1009/1009.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: dedup helpers + shared shapes, drop dead ring-buffer method",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:09:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f60c50814c9bff64f817c8262e053746cf77efe1",
          "body": "- Remove 7 unreferenced bench harness scripts (not invoked by bench-all/gate/\n  adapters/suite-rre; nothing in bench/docs/package.json references them)\n- Delete committed generated artifact apps/vibe-builder-demo/qa/last-bench.json\n\nAlso done in the working tree (untracked / gitignored, not in this \n[…]\nRemoved bench scratch (OpenAI-experiment sweep + debug files) and stale bench/logs;\n  current measured bench/raw results preserved\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: cleanup batch 2 — prune dead bench scripts + generated artifact",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T20:04:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ea61788bf7b181fc9016315630433b99f48c9666",
          "body": "- Remove Presenter.result() legacy no-op + its test (real path is LogHandle.result)\n- Dedup byte-identical isReticleUi into dom-ignore.ts; import in actions-dom + commands\n- Consolidate live-control sessionIdShape onto the shared tool-kit shape\n- Strip gitignored plan/ design-doc citations from 8 pu\n[…]\nes-test.mjs (never in run order; stale target)\n\nVerified: pnpm typecheck (18/18), lint (10/10), browser 362/362, server 1009/1009.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: cleanup batch 1 — dead code, dup helpers, rule-10 doc refs",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T19:44:34Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9589cce29d87e7632b135a9b93a49bf7505c7555",
          "body": "v2.0.1 — bug-fix release (flow verifier honesty, prune, zero-config discovery, HUD)",
          "is_bot": false,
          "headline": "Merge pull request #28 from reticlehq/fix/v2.0.1-bugfixes",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:56:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ab8fd6a9b5362e130e9c2e0bd5887945c4447892",
          "body": "Bump all @reticlehq/* packages 2.0.0 → 2.0.1 and document the release. Also runs\nprettier over pre-existing format drift (README/SKILL/upgrade.ts/flow-scope.ts,\nunformatted on main) so CI format:check passes.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "release: v2.0.1 — bug-fix release + changelog",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:44:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "91a3dad55e0aa93a736f34f188963537560c0368",
          "body": "… projectId (#24)\n\nPointing an app's SDK at the daemon meant hand-reconciling a port in two\ndisjoint places (the app's reticle({ port }) and the daemon's RETICLE_PORT),\nwhich broke the one-daemon-many-repos / many-agents-one-dir real usage.\n\n- Each live daemon now drops a daemon-<port>.json in ~/.re\n[…]\ncovery path (reuses the same registry) and a\nCLI-side project-aware discover — follow-ups; the daemon registry is the shared core.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: daemon discovery registry — auto-match the SDK to the daemon by…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:40:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c3707897058f3b7ba2bcea863e5de173a0ed1266",
          "body": "- Add bridgeWsUrl(port, host?) to core and route the four hand-built\n  ws://localhost:${port}/reticle strings (browser SDK connect, vite-plugin +\n  init snippet generators, CLI inject-connect) through it — the wire string can\n  no longer drift across call sites (rule: no free wire strings).\n- The 'n\n[…]\nad of the 'is the SDK enabled?' dead end.\n- apps/demo pins its port via RETICLE_PORT env with a fallback, not a committed literal.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(core): one bridgeWsUrl() builder; name the port-mismatch cause",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:33:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a23b687b1a30d4d8b1a48aa44ca15fb23f5d1fe1",
          "body": "…te (#25)\n\nThe flow store only grew; a renamed/obsolete flow lingered in the replay list\nforever. Add FlowStore.remove(name, projectId?) (resolves the same path load()\nwould, then deletes it; NOT_FOUND on an absent flow, never a silent no-op) and\nexpose it as the reticle_flow_delete tool, project-sc\n[…]\nce (needs a new browser→daemon delete command);\nthe agent-facing tool covers pruning. Add the button when a human-side need lands.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(flows): prune stale flows — FlowStore.remove + reticle_flow_dele…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:29:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "57bef22ffd5fbc0f449e5e56c3a5576df0593595",
          "body": "…le hint (#23)\n\nA flow whose journey begins on another page drifted on step 1 with a\nmystifying 'a step no longer matches', because replay runs steps against the\ncurrent page and the start page was never recorded.\n\n- FlowFileSchema gains optional startPath (stays FLOW_FILE_VERSION 1); the\n  recorder\n[…]\n so the agent\nnavigates between tool calls where the session re-resolves. Auto-navigation is\nleft for a reconnect-aware follow-up.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(flows): record startPath; surface wrong-start-page as an actionab…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:26:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e589a06becb686973165ed2f68cb31d425136a60",
          "body": "- VisualStore.baselinePath/diffPath now reject a traversal name like their\n  saveBaseline/readBaseline siblings, so a crafted name can never echo a path\n  outside .reticle/visual/ to a future caller that does IO on it.\n- When pairing-token auto-provisioning fails, the bridge still fails open (never\n\n[…]\nt now says so LOUDLY: a plain\n  SECURITY warning that it is trusting every localhost origin, not just a silent\n  structured event.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): harden visual path echo + make token-provision failure loud",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:18:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e3558989e985a6038575e5d5a06a52e371b075d9",
          "body": "The multi-line composer showed a default chunky OS scrollbar inside the dark\nglass pill (unstyled overflow), and content-box sizing made scrollHeight\ninclude the 10px padding the height excluded — a visible jump on the first\nkeystroke and dead space below the caret.\n\n- box-sizing:border-box + base h\n[…]\nder is not an accessible name)\n\nAuto-grow logic unchanged — it was already correct. Enter sends, Shift+Enter\nnewlines (unchanged).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): polish HUD composer — styled scrollbar, no padding jump",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:16:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b72533b88c4a857c88953d29c6af52cd0d2e3a2f",
          "body": "… (#27)\n\nThe event ring buffer evicts on a 60s age cap; bufferHealth() counted the\ndrops but had zero production callers, so 'did the forbidden POST fire?' after\na long session returned a clean, confident 'no' with no sign the evidence was\ndiscarded — a silent false negative, the worst failure mode \n[…]\nintact buffer, zero token cost). Covers the empty-window\ncase too. cost.droppedOldest still reports only output-budget truncation.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): surface ring-buffer evictions on observe/network/console…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:14:20Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b94647753ace8c63d6b43f4cbfde769d88056010",
          "body": "FlowStore.list() unioned the per-project subdirs but #resolveReadPath did\nnot, so a no-projectId caller (reticle_domain, cli-verify) listed a nested\nflow then silently dropped it on `if (loaded.ok)` — an app with full flow\ncoverage reported flowCount:0 and every declared signal/testid as a GAP.\n\nMir\n[…]\nt()'s subdir union on the read side. Regression test: save under a\nprojectId, then list()+load() with no projectId both return it.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): unscoped flow load resolves per-project flows (#26)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-17T15:08:28Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "31d965ab5c08251c92a35e493aa703f20a2b7251",
          "body": "The deprecated protocol alias was unpublished from npm, so remove every place\nthat presented it as installable/available and fix the stale core-vs-protocol\nnaming from the pre-2.0 era:\n\n- MIGRATION.md: it's no longer published (no alias fallback) — migrate imports\n  to @reticlehq/core directly.\n- RE\n[…]\nis on npm now — reframe this as the \"test\n  unpublished local changes\" guide; drop the \"not on npm yet\" + 1.2.0 + protocol\n  bits.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: scrub @reticlehq/protocol references after unpublishing it",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T12:43:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d250e5b05528f7adaa6a3e0f5eb7719c21b9e232",
          "body": "Users kept asking how to install because the install section (line ~68) sat\nbelow the hero + problem sections and the existing nav row didn't even link to\nit. Add a centered ToC directly under the hero badges — leading with a prominent\nInstall link, plus All install options, Manual setup (docs), and the key\nsections — and add Install to the secondary nav row too. All anchors verified.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): add a top table-of-contents led by Install",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T12:40:23Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7159f84b389632e2df9e0a267c1308463fca8916",
          "body": "Replaces the thin one-line fallback in Step 4 with a fastest-signal-first\ndiagnostic: read the browser console (the SDK's own onUnreachable line names the\nport + a dead daemon), then check port match (the #1 manual-setup bug), daemon\nstatus, SDK wiring + dev restart/reload, and link to full troubleshooting.\nConsole text + `status` command verified against source.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(skill): add an ordered 'no session appeared?' connection checklist",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T12:29:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d9632ccea05c3ad35c32f382eadc8027c900f280",
          "body": "Dogfooding a fresh production install from npm surfaced a real onboarding trap in\nthe MANUAL path (the automated `reticle init` was already correct — it bakes the\nport into both the Vite plugin and .reticle.json):\n\n- SKILL Step 4 showed `.reticle.json { \"port\": 5173 }` and said \"port from Q3\"\n  (the\n[…]\nresh Vite+React app, `npm i -D @reticlehq/react\n@reticlehq/vite-plugin` (2.0.0 from npm) → wire → connect → query/act/assert pass.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: fix the manual-setup port story (bridge port vs dev-server port)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T12:27:24Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "55c47c40c8d25893b2809869c2d7b083345fc2e9",
          "body": "…lishing\n\n@reticlehq/protocol is a one-line re-export of @reticlehq/core with no v1 history\n(2.0.0 was its only release), zero downloads, and nothing depending on it. Mark it\nprivate so `pnpm -r publish` never republishes it; the npm 2.0.0 copy is unpublished\nseparately (within npm's 72h window). Import the wire contract from @reticlehq/core.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(protocol): retire the deprecated alias — mark private, stop pub…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T12:08:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "964ce729cf58a4c698d5263d4f4cd50d59049c5d",
          "body": "…ity hardening\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(changelog): add v2.0.0 — package split, per-project flows, secur…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T11:43:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8c9decc54cf4e4174bc57a177de70ead09fd8027",
          "body": "- fix(server): scope HUD replay-flow list to the connecting project (#22)\n- feat(server): per-project flow storage — collision-safe on a shared daemon (#22)\n- fix(browser): reconnect the bridge on foreground (self-heal after outage)\n- feat(server): `reticle version` command; publish workflow comment refresh",
          "is_bot": false,
          "headline": "Merge #22 flow scoping + reconnect-on-focus + version command",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T11:38:06Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7815d2df71d9d00d2fb3a6b57137b0fe8169ce2d",
          "body": "The troubleshooting docs point users at `npx @reticlehq/server@latest version` to\nconfirm which npx-resolved build is running, but there was no `version` command —\nit hit the usage-error path and exited non-zero. Add it (reads this package's own\npackage.json), so the documented diagnostic works and \n[…]\nstale header comment: as of v2 every\n@reticlehq/* package is public (not just core), which is what `pnpm -r publish`\nalready does.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(server): add a `reticle version` command (+ -v/--version)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T11:37:58Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ab3f8c8313414373363cbfbe18cabe0b5715502d",
          "body": "…foreground\n\nBrowsers throttle or suspend timers in a backgrounded tab, so the transport's\n1s reconnect loop stalls while hidden. A bridge blip during that window (daemon\nrestart on a `reticle` upgrade, laptop sleep/wake, network hiccup) left the\npanel stuck on \"ENDED\" until the user manually reload\n[…]\nt (focus racing the scheduled retry), unsubscribes on\nclose, and the visibility source is injected so it's testable without a DOM.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): reconnect the bridge immediately when a tab returns to …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T09:35:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "87272bee7099afcf543a521f3c478f5d733bc8b3",
          "body": "…aemon (#22)\n\nThe HUD-scoping fix hid other apps' flows but the store was still flat: one\ndaemon serving many apps kept all flows in .reticle/flows/<name>.json, so two\napps saving \"login\" clobbered each other and the replay tools (list/load/\nreplay/heal) resolved by bare name across every project — \n[…]\nnd an agent\ndriving app A can no longer list/load/replay app B's flows. Legacy flat flows\nkeep loading (global) until re-recorded.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(server): per-project flow storage — collision-safe on a shared d…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T09:15:52Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "06aeb7d35530c8f287481f8d164c1962f3dfc62e",
          "body": "… (#22)\n\nOne daemon can serve many apps (they share the bridge port), but its flow\nstore is flat — so every app's HUD listed every other app's flows (surfaced\ndogfooding Reticle on the Cloud dashboard: 26 chips from the demo/bench/e2e).\n\n- core: FlowFileSchema gains an optional projectId (stays v1, \n[…]\nd ones.\n\nLegacy flows already on disk carry no projectId, so they remain global until\nre-recorded — scoping applies going forward.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): scope the HUD replay-flow list to the connecting project…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T08:39:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e5ebbab92c64c38e3c53ff1d7c5845b0d0a961cc",
          "body": "\"Logged in\" = both cloud env vars set (RETICLE_CLOUD_URL + RETICLE_CLOUD_KEY,\nwritten by `reticle login` later, settable by hand today). On flow save the server\nbest-effort POSTs the flow to the cloud's /v1/flows so the team's regression suite\nlives in the cloud — survives refactors, runs in CI, sco\n[…]\nno-op and everything stays local (the no-phone-home default).\nFire-and-forget: a sync failure never fails the local save. 5 tests.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(server): sync saved flows to Reticle Cloud when logged in",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T03:56:30Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1d802b8c09e886dcd0c6a706d6649475a67f93db",
          "body": null,
          "is_bot": false,
          "headline": "Merge branch 'fix/hud-flows-overflow'",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T03:51:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "508c8a790caaf72349cee8d1cf137d6a125b7b13",
          "body": "# Conflicts:\n#\t.gitignore",
          "is_bot": false,
          "headline": "Merge branch 'feat/upgrade-hint-contract'",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T03:51:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e3b34e078fd603380693fef37f636c199b441764",
          "body": "A big app accumulates many flows; showing all of them everywhere is noise, and\nclicking one that can't start from the current page just drifts. Now each flow is\npushed with a `start` hint (its first step's testid anchor) and the HUD shows only\nflows whose start element is present in the live DOM — r\n[…]\nt step, so existing flows benefit without re-recording.\n\nSurfaced by dogfooding: the cross-project flow list is now page-relevant.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(hud): scope replay-flow chips to the current page",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T03:43:01Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bb498d193290e5fab14ace998682eca58eeb7a8e",
          "body": "… + input\n\nThe .reticle-flows row sat between the flex:1 log and the flex:none composer with\nno height cap and no overflow, inside the panel's overflow:hidden frame. With many\nsaved flows it grew, squeezed the log to zero, and pushed the message input below\nthe clip line — the panel became unusable.\n[…]\na flow chips scroll inside the row; the log and input stay\nvisible. Surfaced by dogfooding Reticle on the Reticle Cloud dashboard.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): bound the HUD replay-flow list so it can't hide the log…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T03:14:35Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "59cf31636a90d6fa1eb88ae33c55140e9896cbc6",
          "body": "The paid app was moved out of this repo to ReticleHQ/app/ (its own git). Keep the\napp/ ignore as a safety net against an accidental stray dir; fix the stale comment.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: clarify app/ gitignore — cloud app now lives in a sibling repo",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-11T02:55:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "01f5e637d9fb8d2749c5a78c249bb155e2b463c8",
          "body": "…S repo\n\napp/ holds the paid control plane (tenant/billing + the closed-intelligence moat),\ndeveloped locally with its own git per service and extracted to a private repo\nbefore real tenant data. Ignoring it on main prevents accidental commits.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: gitignore app/ — the cloud control plane never ships in the OS…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-10T22:29:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1a5c423c4db9c4bf881721371f044bae7d202912",
          "body": "…rompts\n\nA structured, honest hint the local server emits ONLY when a task is blocked by a\nfree-tier boundary (share proof, run history, team review, corpus heal, CI gate).\nCarries {capability, reason, unlockedBy, learnMoreUrl} so the agent de-dupes and\nsurfaces it in context — never a nag, never an\n[…]\nomise: the hint is advisory only.\n\nAlso gitignore app/ (the cloud control plane developed locally, never shipped in\nthe OSS repo).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(core): add the upgrade-hint contract for value-triggered cloud p…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-10T22:26:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8aa6d07fa7d33a62e7ce04d3d2eb089d398e26fe",
          "body": "* chore(ci): unbreak the format gate\n\nformat:check was red on main: README had unformatted lines and the\npw-vs-reticle head-to-head harness outputs (measured result JSON +\ngenerated scorecards) were never prettier-ignored despite being the same\n\"generated data, not code\" category already excluded fo\n[…]\nhq/core (the contract now lives there; protocol\nre-exports it).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\n\n---------\n\nCo-authored-by: Claude Fable 5 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "v2: retire the core umbrella, fix the front door (RT-1..RT-6) (#21)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-10T21:32:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "483c21bc58011fe9d80f1df196120ae9e0f6c2cb",
          "body": "…klist (#20)\n\nAdds a maintainer/audit security-finding issue form mirroring the\nplan/SECURITY-AUDIT.md structure (severity, files, impact/exploit, fix) with a\ndisclosure guard that routes undisclosed vulnerabilities to SECURITY.md instead.\nAdds a security-affecting line to the PR checklist. Existing bug/feature/PR\ntemplates were already present and left as-is.\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(github): add security-finding issue template + PR security chec…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-08T09:59:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ca51a38c821ccc336649a215ca8c22593b372df2",
          "body": "…ed a secret (#19)\n\nFixes M2: the WS bridge trusted any http://localhost:<port> origin, letting a\nrogue localhost app register/drive sessions. The daemon now auto-provisions a\nper-user token at ~/.reticle/pairing-token (0600) — read-or-create, stable across\nrestarts — and the bridge requires it. A b\n[…]\ntion + Next/plain token wiring\n\nEnd-to-end verified: tokenless loopback HELLO → closed 1008; injected token → accepted.\n\nCloses #8\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(security): auto-provision a pairing token so loopback origins ne…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-08T09:33:08Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8bdd0d69e2901ec4c9e862faa64fe93998439217",
          "body": "…(#18)\n\nThe dev-only SDK relied entirely on the consumer gating its import behind\nimport.meta.env.DEV; a prod build reached via localhost (SSR healthcheck, prod\nbundle opened locally) would still activate. connect() now self-disables when the\nbuild reports NODE_ENV=production, with an allowInProduct\n[…]\ndepth — DCE via import.meta.env.DEV remains the primary guard (docs\nunchanged on that point, now noting the backstop).\n\nCloses #11\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): add a production runtime backstop to the SDK connect() …",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-08T07:26:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c6cce04aa3343eb8974fcdcaccdd1014df57a2dd",
          "body": "… gate (#17)\n\nEnforcement was on only if RETICLE_LICENSE_PUBLIC_KEY happened to be in the\nenvironment, so any self-hosted operator got enterprise features free by never\nsetting it. Add a compiled-in BAKED_ISSUER_PUBLIC_KEY_PEM (empty in-repo, filled\nby the release pipeline) that takes precedence ove\n[…]\nrise/.env.local still use the stale IRIS_ prefix (H3), so the\nrepo runs in eval mode until the release bakes a real key. Closes #5\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): bake the issuer public key and fail closed on enterprise…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-08T07:23:22Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cd3432dc524d330ec9f60d73240c39cca688d1e3",
          "body": "… set (#16)\n\n#originAllowed returned true for a handshake with no Origin, so any non-browser\nlocal process (another app, a malicious npm postinstall, an extension native\nhost) could open the bridge and, tokenless, drive a session. A real browser SDK\nalways sends Origin; a missing one is now rejected\n[…]\nLO token check is the real gate). Test WS\nclients now send a loopback Origin to simulate the browser they stand in for.\n\nCloses #7\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): treat a missing WS Origin as untrusted unless a token is…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-08T07:19:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b3cff230a919182db9ce00039d8b0f8593b5f91a",
          "body": "…#15)\n\n`cmd /c start ... <url>` let cmd.exe re-parse the URL, so `&`/`^`/`|` in a\n(partially tab-influenced) URL could chain commands. Percent-encode those\nmetacharacters before they reach `start`; `%` is left alone so existing\npercent-encoding isn't double-encoded and the browser decodes back to the real URL.\n\nCloses #10\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): neutralize cmd.exe injection in Windows browser launch (…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-08T07:13:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1349eb9879cceabca778b55f1411cb4751f7888c",
          "body": "…ver (#14)\n\nThe observer recorded request URLs verbatim, so ?access_token=…, signed-URL\nkeys, and magic-link tokens leaked into the agent transcript and flow/run\nartifacts. Add redactUrl(), applied to both fetch and XHR capture, rewriting\nonly sensitive query params (shared isSensitiveKey regex) and only when matched,\npreserving path and hash otherwise.\n\nCloses #9\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): redact credential-bearing query params in network obser…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-08T07:11:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "afb22fabf3921fb1929c5abed3eb8b26badc706f",
          "body": "The recorder persisted raw fill values into .reticle/flows/<name>.json, so a\ndemoed login wrote the password/OTP/API key into a git-checked file. Extract the\nsensitive-field predicate already used by live-snapshot redaction into\nisSensitiveField() and apply it on the recorder's fill-flush path — password,\nsensitive-autocomplete, and sensitive-keyed fields now record REDACTED_VALUE.\n\nCloses #4\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(browser): redact typed secrets from recorded flow files (#13)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-08T07:09:10Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4719f16e3b8babd3a715c81fd3c542708ded5858",
          "body": "Loopback-peer trust alone let a DNS-rebound webpage (evil.com -> 127.0.0.1)\nauthorize against /mcp/* and /status and drive the agent's browser / read app\nstate. Require a loopback Host header and a loopback-or-absent Origin/Referer\nbefore granting loopback trust, mirroring the WS bridge's #originAll\n[…]\nlls through to the token check it cannot satisfy;\nlegitimate RETICLE_HOST clients present the token and are unaffected.\n\nCloses #3\n\nCo-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(server): block DNS-rebinding on the MCP/HTTP control plane (#12)",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-08T07:07:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bd78eaf35dd084fa8a855049147dc40993a30dfe",
          "body": "- Lead with the wordmark lockup (replaces icon + redundant H1)\n- Add a pain hook under the logo: \"Feature complete\" then the three\n  things you actually find, as a left-aligned ✗ checklist\n- Center only the \"proof layer\" tagline; left-align the body copy\n- Replace all 31 em-dashes with context-appropriate punctuation\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): restructure hero, add pain hook, drop em-dashes",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-07T17:57:08Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0d34c367f856763dc2813e3761626738f636d6ad",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "style: apply prettier to bench harness, bug injector, and SKILL.md",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-07T07:42:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "267b54ffd14c2e48f7f850b4582fc56e96dd2f4e",
          "body": null,
          "is_bot": false,
          "headline": "docs(readme): lead the hero with the Reticle value prop",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-06T13:04:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7a0f5ac0c70de6f8f8f9e216abf3538085b6246a",
          "body": "…D occluder/label fixes (non-breaking)",
          "is_bot": false,
          "headline": "chore(release): prep 1.3.1 — reticle_sessions schema declaration + HU…",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-06T13:04:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3cf4f409c162e49c3e83cfee91157eef6d785e6e",
          "body": null,
          "is_bot": false,
          "headline": "Update contact email and company name in README",
          "author_name": "Divyanshu Shekhar",
          "author_login": "divshekhar",
          "committed_at": "2026-07-06T12:48:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 9,
      "commits_last_year": 527,
      "latest_release_at": "2026-07-18T10:09:41Z",
      "latest_release_tag": "v2.1.0",
      "releases_from_tags": false,
      "days_since_last_push": 3,
      "active_weeks_last_year": 6,
      "days_since_latest_release": 5,
      "mean_days_between_releases": 4.1
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 100,
      "has_issue_template": false,
      "has_code_of_conduct": true,
      "has_pull_request_template": true
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@reticlehq/core",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "mcp",
            "ai-agents",
            "testing",
            "protocol",
            "reticle"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@reticlehq/core",
          "is_deprecated": false,
          "latest_version": "2.1.0",
          "repository_url": "https://github.com/reticlehq/reticle",
          "versions_count": 5,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 6243,
          "first_published_at": "2026-06-30T12:23:12.585000Z",
          "latest_published_at": "2026-07-18T10:10:44.461000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@reticlehq/next",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "reticle",
            "next",
            "nextjs",
            "source",
            "devtools"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@reticlehq/next",
          "is_deprecated": false,
          "latest_version": "2.1.0",
          "repository_url": "https://github.com/reticlehq/reticle",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 701,
          "first_published_at": "2026-07-11T11:55:48.054000Z",
          "latest_published_at": "2026-07-18T10:10:53.064000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@reticlehq/react",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "mcp",
            "ai-agents",
            "react",
            "testing"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@reticlehq/react",
          "is_deprecated": false,
          "latest_version": "2.1.0",
          "repository_url": "https://github.com/reticlehq/reticle",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 1609,
          "first_published_at": "2026-07-11T11:56:04.646000Z",
          "latest_published_at": "2026-07-18T10:11:02.540000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@reticlehq/server",
          "exists": true,
          "license": "SEE LICENSE IN LICENSE",
          "keywords": [
            "mcp",
            "ai-agents",
            "testing",
            "cli"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@reticlehq/server",
          "is_deprecated": false,
          "latest_version": "2.1.0",
          "repository_url": "https://github.com/reticlehq/reticle",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 787,
          "first_published_at": "2026-07-11T11:55:57.126000Z",
          "latest_published_at": "2026-07-18T10:10:56.980000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@reticlehq/browser",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "mcp",
            "ai-agents",
            "testing",
            "instrumentation",
            "observability"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@reticlehq/browser",
          "is_deprecated": false,
          "latest_version": "2.1.0",
          "repository_url": "https://github.com/reticlehq/reticle",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 1628,
          "first_published_at": "2026-07-11T11:55:44.760000Z",
          "latest_published_at": "2026-07-18T10:10:50.474000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@reticlehq/vite-plugin",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "vite-plugin",
            "reticle",
            "react",
            "devtools"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@reticlehq/vite-plugin",
          "is_deprecated": false,
          "latest_version": "2.1.0",
          "repository_url": "https://github.com/reticlehq/reticle",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 1333,
          "first_published_at": "2026-07-11T11:56:00.865000Z",
          "latest_published_at": "2026-07-18T10:10:59.775000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@reticlehq/babel-plugin",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "babel-plugin",
            "reticle",
            "react",
            "source",
            "devtools"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@reticlehq/babel-plugin",
          "is_deprecated": false,
          "latest_version": "2.1.0",
          "repository_url": "https://github.com/reticlehq/reticle",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 1573,
          "first_published_at": "2026-07-11T11:55:31.087000Z",
          "latest_published_at": "2026-07-18T10:10:41.560000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        },
        {
          "name": "@reticlehq/eslint-plugin",
          "exists": true,
          "license": "Apache-2.0",
          "keywords": [
            "mcp",
            "ai-agents",
            "eslint",
            "eslint-plugin",
            "testing"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@reticlehq/eslint-plugin",
          "is_deprecated": false,
          "latest_version": "2.1.0",
          "repository_url": "https://github.com/reticlehq/reticle",
          "versions_count": 3,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 456,
          "first_published_at": "2026-07-11T11:55:40.873000Z",
          "latest_published_at": "2026-07-18T10:10:46.888000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        }
      ]
    },
    "popularity": {
      "forks": 18,
      "stars": 191,
      "watchers": 5,
      "fork_history": {
        "days": [
          {
            "date": "2026-06-12",
            "count": 1
          },
          {
            "date": "2026-06-13",
            "count": 1
          },
          {
            "date": "2026-06-18",
            "count": 1
          },
          {
            "date": "2026-06-24",
            "count": 1
          },
          {
            "date": "2026-07-08",
            "count": 2
          },
          {
            "date": "2026-07-11",
            "count": 1
          },
          {
            "date": "2026-07-12",
            "count": 1
          },
          {
            "date": "2026-07-14",
            "count": 1
          },
          {
            "date": "2026-07-15",
            "count": 2
          },
          {
            "date": "2026-07-17",
            "count": 1
          },
          {
            "date": "2026-07-18",
            "count": 1
          },
          {
            "date": "2026-07-20",
            "count": 3
          },
          {
            "date": "2026-07-21",
            "count": 1
          },
          {
            "date": "2026-07-22",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 18,
        "total_forks": 18
      },
      "star_history": null,
      "open_issues_and_prs": 1
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": true,
      "has_dockerfile": false,
      "has_mcp_signal": true,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "apps/bench-app/tsconfig.json",
        "apps/demo/tsconfig.json",
        "apps/examples/next/tsconfig.json",
        "apps/examples/remix/tsconfig.json",
        "apps/next-smoke/tsconfig.json",
        "packages/babel-plugin/tsconfig.json",
        "packages/browser/tsconfig.json",
        "packages/core/tsconfig.json",
        "packages/eslint-plugin/tsconfig.json",
        "packages/protocol/tsconfig.json",
        "packages/react/tsconfig.json",
        "packages/server/tsconfig.json",
        "packages/test/tsconfig.json",
        "packages/vite-plugin/tsconfig.json",
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 31860,
      "source_files_sampled": 574,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 5224
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 1,
        "malicious_count": 0,
        "assessed_package": "npm:@reticlehq/core@2.1.0",
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "cors",
          "manifest": "apps/api/package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.8.5"
        },
        {
          "name": "express",
          "manifest": "apps/api/package.json",
          "ecosystem": "npm",
          "version_constraint": "^4.21.2"
        },
        {
          "name": "@reticlehq/browser",
          "manifest": "apps/bench-app/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@reticlehq/react",
          "manifest": "apps/bench-app/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "react",
          "manifest": "apps/bench-app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.0.0"
        },
        {
          "name": "react-dom",
          "manifest": "apps/bench-app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.0.0"
        },
        {
          "name": "zustand",
          "manifest": "apps/bench-app/package.json",
          "ecosystem": "npm",
          "version_constraint": "^5.0.14"
        },
        {
          "name": "@reticlehq/server",
          "manifest": "apps/e2e/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@reticlehq/test",
          "manifest": "apps/e2e/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "playwright",
          "manifest": "apps/e2e/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.48.0"
        },
        {
          "name": "@reticlehq/browser",
          "manifest": "apps/large-dom-bench/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "next",
          "manifest": "apps/next-smoke/package.json",
          "ecosystem": "npm",
          "version_constraint": "^15.1.0"
        },
        {
          "name": "react",
          "manifest": "apps/next-smoke/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.0.0"
        },
        {
          "name": "react-dom",
          "manifest": "apps/next-smoke/package.json",
          "ecosystem": "npm",
          "version_constraint": "^19.0.0"
        },
        {
          "name": "@reticlehq/browser",
          "manifest": "apps/vibe-builder-demo/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@reticlehq/core",
          "manifest": "packages/browser/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@testing-library/dom",
          "manifest": "packages/browser/package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.4.1"
        },
        {
          "name": "zod",
          "manifest": "packages/core/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.24.1"
        },
        {
          "name": "@typescript-eslint/utils",
          "manifest": "packages/eslint-plugin/package.json",
          "ecosystem": "npm",
          "version_constraint": "^8.20.0"
        },
        {
          "name": "@babel/core",
          "manifest": "packages/next/package.json",
          "ecosystem": "npm",
          "version_constraint": "^7.26.0"
        },
        {
          "name": "@reticlehq/babel-plugin",
          "manifest": "packages/next/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@reticlehq/core",
          "manifest": "packages/protocol/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@reticlehq/browser",
          "manifest": "packages/react/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@reticlehq/core",
          "manifest": "packages/react/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@modelcontextprotocol/sdk",
          "manifest": "packages/server/package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.13.0"
        },
        {
          "name": "@reticlehq/core",
          "manifest": "packages/server/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "ws",
          "manifest": "packages/server/package.json",
          "ecosystem": "npm",
          "version_constraint": "^8.18.0"
        },
        {
          "name": "zod",
          "manifest": "packages/server/package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.24.1"
        },
        {
          "name": "@babel/core",
          "manifest": "packages/vite-plugin/package.json",
          "ecosystem": "npm",
          "version_constraint": "^7.26.0"
        },
        {
          "name": "@reticlehq/babel-plugin",
          "manifest": "packages/vite-plugin/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        },
        {
          "name": "@reticlehq/core",
          "manifest": "packages/vite-plugin/package.json",
          "ecosystem": "npm",
          "version_constraint": "workspace:*"
        }
      ],
      "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": 1,
        "merged_prs": 13,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 15,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "divshekhar",
          "commits": 526,
          "avatar_url": "https://avatars.githubusercontent.com/u/61140213?v=4"
        },
        {
          "type": "User",
          "login": "karthiknagpuri",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/74970022?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.998
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "publish.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        "eslint.config.mjs"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "pnpm-lock.yaml"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 4 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": 9,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 10,
            "reason": "security policy file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 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": "24 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "2e0a970c09623667e4310e3f812c3029168a50a7",
        "ran_at": "2026-07-23T17:31:53Z",
        "aggregate_score": 3.4,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": true,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-18T10:11:09Z",
      "oldest_open_prs": [
        {
          "number": 29,
          "created_at": "2026-07-20T12:45:11Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ],
      "last_merged_pr_at": "2026-07-17T15:56:47Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/reticlehq/reticle",
    "host": "github.com",
    "name": "reticle",
    "owner": "reticlehq"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 68,
      "inputs": {
        "security": 47,
        "vitality": 75,
        "community": 68,
        "governance": 57,
        "engineering": 88
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 75,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 58,
            "inputs": {
              "commits_last_year": 527,
              "human_commit_share": 1,
              "days_since_last_push": 3,
              "active_weeks_last_year": 6
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 3 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 3
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "6/52 weeks with commits",
                "points": 4.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "527 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 527
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 9,
              "latest_release_tag": "v2.1.0",
              "releases_from_tags": false,
              "days_since_latest_release": 5,
              "mean_days_between_releases": 4.1
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "9 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 9
                    }
                  }
                ],
                "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 ~4.1 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 4.1
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "moderate",
        "name": "Community & Adoption",
        "value": 68,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "moderate",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 51,
            "inputs": {
              "forks": 18,
              "stars": 191,
              "watchers": 5,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "191 stars",
                "points": 37,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 191
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "18 forks",
                "points": 10.3,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 18
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "5 watchers",
                "points": 3.3,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "excellent",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 86,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": true,
              "has_pull_request_template": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file present, not a recognized license",
                "points": 16.9,
                "status": "partial",
                "details": [
                  {
                    "code": "license_custom",
                    "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": 13.5,
                "status": "met",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 6.3,
                "status": "met",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 69,
            "inputs": {
              "packages": [
                "@reticlehq/core",
                "@reticlehq/next",
                "@reticlehq/react",
                "@reticlehq/server",
                "@reticlehq/browser",
                "@reticlehq/vite-plugin",
                "@reticlehq/babel-plugin",
                "@reticlehq/eslint-plugin"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 14330
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "14,330 downloads/month across npm",
                "points": 55.4,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 14330,
                      "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": 57,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 22,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.998
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "2 contributors",
                "points": 2.7,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 4 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "merged_prs": 13,
              "open_issues": 0,
              "closed_issues": 15,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "13/13 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 13,
                      "decided": 13
                    }
                  }
                ],
                "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": 36,
            "inputs": {
              "followers": 2,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "reticlehq",
              "public_repos": 1,
              "account_age_days": 23
            },
            "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 reticlehq",
                "points": 3.4,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 2,
                      "login": "reticlehq"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "1 public repos, account ~0 yr old",
                "points": 2.3,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 1
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 0
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@reticlehq/core",
                "@reticlehq/next",
                "@reticlehq/react",
                "@reticlehq/server",
                "@reticlehq/browser",
                "@reticlehq/vite-plugin",
                "@reticlehq/babel-plugin",
                "@reticlehq/eslint-plugin"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 5
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "8 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 8,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 5 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "5 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "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": "excellent",
        "name": "Engineering Quality",
        "value": 88,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 80,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "2 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": "eslint.config.mjs",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.mjs"
                    }
                  }
                ],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "topics": [
                "agent-testing",
                "ai-testing-tool",
                "automated-testing",
                "testing-tool",
                "agent-verification",
                "playwright-mcp",
                "proof-layer",
                "reticle-mcp"
              ],
              "has_wiki": true,
              "homepage": "https://www.reticle.sh",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://www.reticle.sh",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "8 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 8
                    }
                  }
                ],
                "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": 47,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 34,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 3.4
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 4 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 detected",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "24 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Excluded from scoring (no data or not applicable): No advisories left outstanding. Remaining weights renormalized. Matched the npm:@reticlehq/core@2.1.0 runtime dependency closure — what installing the published package pulls in — 1 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "no_advisories_left_outstanding"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              },
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:@reticlehq/core@2.1.0",
                  "assessed": 1
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "source": "osv",
              "advisories": 0,
              "affected_packages": 0,
              "assessed_packages": 1,
              "unassessed_packages": 0,
              "affected_by_severity": "none",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "no indirect dependency carries a known advisory",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "no_indirect_advisories",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory carries a publication date",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "advisories_no_publication_date",
                    "params": {}
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 1,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 5
            },
            "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": 80,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "has_llms_txt": true,
              "legible_history_share": 0.97,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 5224
            },
            "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": "llms.txt present",
                "points": 15,
                "status": "met",
                "details": [
                  {
                    "code": "llms_txt_present",
                    "params": {}
                  }
                ],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "97 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 97,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 64,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "pnpm-lock.yaml"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [
                "apps/bench-app/tsconfig.json",
                "apps/demo/tsconfig.json",
                "apps/examples/next/tsconfig.json",
                "apps/examples/remix/tsconfig.json",
                "apps/next-smoke/tsconfig.json",
                "packages/babel-plugin/tsconfig.json",
                "packages/browser/tsconfig.json",
                "packages/core/tsconfig.json",
                "packages/eslint-plugin/tsconfig.json",
                "packages/protocol/tsconfig.json",
                "packages/react/tsconfig.json",
                "packages/server/tsconfig.json",
                "packages/test/tsconfig.json",
                "packages/vite-plugin/tsconfig.json",
                "tsconfig.json"
              ],
              "agent_commit_share": 0.93,
              "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.mjs",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "eslint.config.mjs"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "apps/bench-app/tsconfig.json, apps/demo/tsconfig.json, apps/examples/next/tsconfig.json, apps/examples/remix/tsconfig.json, apps/next-smoke/tsconfig.json, packages/babel-plugin/tsconfig.json, packages/browser/tsconfig.json, packages/core/tsconfig.json, packages/eslint-plugin/tsconfig.json, packages/protocol/tsconfig.json, packages/react/tsconfig.json, packages/server/tsconfig.json, packages/test/tsconfig.json, packages/vite-plugin/tsconfig.json, tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "apps/bench-app/tsconfig.json, apps/demo/tsconfig.json, apps/examples/next/tsconfig.json, apps/examples/remix/tsconfig.json, apps/next-smoke/tsconfig.json, packages/babel-plugin/tsconfig.json, packages/browser/tsconfig.json, packages/core/tsconfig.json, packages/eslint-plugin/tsconfig.json, packages/protocol/tsconfig.json, packages/react/tsconfig.json, packages/server/tsconfig.json, packages/test/tsconfig.json, packages/vite-plugin/tsconfig.json, 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": "93 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 93,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 31860,
              "source_files_sampled": 574,
              "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/574 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 574,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "moderate",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 60,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": true,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-23T17:32:02.653471Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/r/reticlehq/reticle.svg",
  "full_name": "reticlehq/reticle",
  "license_state": "custom",
  "license_spdx": null
}

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

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

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