Public record
Software health reportschema 0.27.0 · metrics 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 · JavaScriptCustom license★ 191 stars⑂ 18 forkssince Jun 2026View on GitHub ↗

reticlehq/reticle holds a health index of 68 out of 100, placing it in the Moderate band. It scores highest on Engineering Quality (88/100) and lowest on Security (47/100). It was last updated 3 days ago. A single contributor accounts for most of its recent work.

68
overall / 100
Moderate

Software health index

Metrics are grouped into weighted categories on one standardized 1–100 scale. Overall starts as their weighted mean; when public evidence triggers the High-Risk Jurisdiction Policy, the rating is adjusted and receives an At risk ceiling of 49. AI Readiness sits outside the overall score.

68
Excellent85-100Exemplary; meets essentially all checked criteria
Good70-84Healthy; minor gaps
Moderate50-69Acceptable with notable gaps; review recommended
At risk30-49Significant weaknesses; adoption warrants caution
Critical1-29Severe problems (abandoned, single-maintainer, no hygiene)
VitalityCommunity &AdoptionSustainability &GovernanceEngineeringQualitySecurityAI Readiness

Score profile

Each axis is a category. The shape matters more than the average — a healthy subject fills the whole shape, while a spike-and-crater profile means strength in one dimension is masking risk in another.

Ownership

ReticleOrganization
2 followers1 public reposince Jun 2026

This repository is backed by an organization — shared, accountable stewardship that can outlive any single maintainer.

Package ecosystems

Metrics by category

Vitality

Is the project alive — is code being written and are releases shipping?

75Good · 22% of overall
How it's scored
36/36Push recency — last push 3 days ago
4.2/36Commit cadence — 6/52 weeks with commits
18/18Commit volume — 527 commits in the last year
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Inputs used
commits_last_year527
human_commit_share1
days_since_last_push3
active_weeks_last_year6

Release discipline

100Excellent
How it's scored
27/27Ships releases — 9 releases published
36/36Release recency — latest release 5 days ago
27/27Release cadence — a release every ~4.1 days
0/10OpenSSF Scorecard: Signed-Releases — no data
Inputs used
releases_count9
latest_release_tagv2.1.0
releases_from_tagsno
days_since_latest_release5
mean_days_between_releases4.1
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.

Community & Adoption

Does the project have users, downloads, attention, and a welcoming setup for contributors?

68Moderate · 18% of overall
How it's scored
37/60Stars — 191 stars
10.3/25Forks — 18 forks
3.3/15Watchers — 5 watchers
Inputs used
forks18
stars191
watchers5
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

Community health

86Excellent
How it's scored
22.5/22.5README
16.9/22.5License — license file present, not a recognized license
18/18CONTRIBUTING guide
13.5/13.5Code of conduct
0/7.2Issue template
6.3/6.3PR template
Inputs used
has_readmeyes
has_licenseyes
has_contributingyes
has_issue_templateno
has_code_of_conductyes
has_pull_request_templateyes
How it's scored
55.4/80Monthly downloads — 14,330 downloads/month across npm
0/20Registry dependents — not reported by this ecosystem
Inputs used
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
Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.

Sustainability & Governance

Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?

57Moderate · 24% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
0/22.5Commit distribution — top contributor authored 100% of commits
2.7/13.5Contributor breadth — 2 contributors
10/10OpenSSF Scorecard: Contributors — project has 4 contributing companies or organizations
Inputs used
bus_factor1
contributors_sampled2
top_contributor_share0.998
How it's scored
46.8/46.8Issue resolution — 100% of issues closed
38.2/38.3PR acceptance — 13/13 decided PRs merged
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Inputs used
merged_prs13
open_issues0
closed_issues15
issue_closed_ratio1
closed_unmerged_prs0
How it's scored
30/30Ownership backing — organization-owned
0/20Verified domain
3.4/25Owner reach — 2 followers of reticlehq
2.3/25Track record — 1 public repos, account ~0 yr old
Inputs used
followers2
owner_typeOrganization
is_verified
owner_loginreticlehq
public_repos1
account_age_days23
How it's scored
25/25Published & resolvable — 8 package(s) on npm
35/35Publish recency — latest publish 5 days ago
20/20Version history — 5 published versions
20/20Not deprecated — active, not deprecated or yanked
Inputs used
packages@reticlehq/core, @reticlehq/next, @reticlehq/react, @reticlehq/server, @reticlehq/browser, @reticlehq/vite-plugin, @reticlehq/babel-plugin, @reticlehq/eslint-plugin
ecosystemsnpm
any_deprecatedno
min_days_since_publish5

Engineering Quality

Are baseline engineering and documentation practices in place?

88Excellent · 20% of overall
How it's scored
24/24CI workflows — 2 workflow(s)
24/24Tests present
16/16Linter config — eslint.config.mjs
0/9.6Pre-commit hooks
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — no data
Inputs used
has_ciyes
has_testsyes
has_editorconfigno
has_linter_configyes
has_precommit_configno
Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.

Documentation

100Excellent
How it's scored
30/30README
25/25Documentation directory
15/15Documentation / homepage site — https://www.reticle.sh
10/10Repository description
10/10Topics — 8 topics
10/10Wiki
Inputs used
topicsagent-testing, ai-testing-tool, automated-testing, testing-tool, agent-verification, playwright-mcp, proof-layer, reticle-mcp
has_wikiyes
homepagehttps://www.reticle.sh
has_readmeyes
has_docs_diryes
has_descriptionyes

Security

Are visible security and supply-chain practices strong, without unresolved high-risk jurisdiction exposure?

47At risk · 16% of overall
How it's scored
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 — no data
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.5License — 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 — no data
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
0/7.5Vulnerabilities — 24 existing vulnerabilities detected
Inputs used
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate3.4
Excluded from scoring (no data or not applicable): ci_tests, signed_releases. Remaining weights renormalized.
How it's scored
35/35Direct dependencies free of known advisories — no direct dependency carries a known advisory
25/25Indirect dependencies free of known advisories — no indirect dependency carries a known advisory
0/40No advisories left outstanding — no advisory carries a publication date
Inputs used
sourceosv
advisories0
affected_packages0
assessed_packages1
unassessed_packages0
affected_by_severitynone
direct_affected_packages0
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.

AI Readiness

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.

80Good · 0% of overall
How it's scored
45/45Agent instructions — CLAUDE.md
15/15Machine-readable docs (llms.txt) — llms.txt present
40/40Legible commit history — 97 of 100 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtyes
legible_history_share0.97
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes5,224
How it's scored
0/18One-command bootstrap
22/22Automated tests
11/11Lint / format config — eslint.config.mjs
11/11Static type checking — 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/10Reproducible environment — lockfile
10/10Demonstrated agent practice — 93 of the last 100 commits agent-authored or agent-credited
0/8Automated maintenance — no automated dependency updates observed
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Inputs used
has_nixno
has_testsyes
lockfilespnpm-lock.yaml
has_dockerfileno
typed_languageyes
bootstrap_files
has_devcontainerno
has_linter_configyes
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
How it's scored
45/45Type-checkable code — TypeScript (statically typed)
55/55Manageable file sizes — 0/574 source files over 60KB
Inputs used
primary_languageTypeScript
largest_source_bytes31,860
source_files_sampled574
oversized_source_files0
How it's scored
0/40API schema (OpenAPI/GraphQL/proto)
20/20MCP server
40/40Runnable examples — examples
Inputs used
example_dirsexamples
has_mcp_signalyes
api_schema_files

Key facts

191GitHub stars
2contributors
527commits, last 12 months
3days since last push
9releases
1bus factor
0open issues
npmpackage ecosystems

Data collection 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

More detail

Star and fork history 0 ★ / 18 ⇿
0Stars
18Forks
9Releases

When each star and fork was added, collected from GitHub and bucketed by day. Cumulative growth sits directly above the daily additions it is made of, so the two read against each other: steady organic accretion looks nothing like an abrupt, short-lived burst. Where that difference is measurable, it is reported as growth authenticity.

0481216201832026-062026-072026-07
Major 2Minor 4Patch 3
OpenSSF Scorecard 3.4 / 10
3.4aggregate

Independent, tool-agnostic security assessment from the open-source OpenSSF Scorecard. Each check rewards a security practice, not a specific vendor's tool. Checks Scorecard could not determine are marked n/a and excluded from the security score (never counted as zero).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
n/aCI-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
n/aSigned-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
0Vulnerabilities24 existing vulnerabilities detected
Direct dependencies 31
RegistryPackageVersion constraintManifest
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
All dependencies not collected

The resolved dependency set could not be collected for this report: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Dependency advisories 0

Installing npm:@reticlehq/core@2.1.0 pulls in 1 packages, direct and transitive: 0 carry known advisories, of which 0 are direct dependencies.

No known advisories affect the assessed dependencies.

An advisory means the version recorded in the dependency graph falls inside an advisory’s affected range. Reachability is not analysed, and the graph includes development and test pins — a finding may concern tooling rather than shipped software.

Raw JSON report machine-readable
{
  "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
}

Scores are signals, not warranties. They reflect publicly visible practices on GitHub — not a code audit, and not a security guarantee.

Missing data is excluded and weights renormalized, never scored as zero. Methodology is versioned and open: metrics v1.13.0, schema v0.27.0 — full methodology · metrics wiki.

How one result sits in the wider record: aggregate statisticsnpm.