Public record
Software health reportschema 0.27.0 · metrics 2.3.1 · 2026-08-01 13:44 UTC

personalrobotics / ssik

Analytical inverse kinematics for 6R and 7R revolute arms. Returns every IK branch at machine-precision FK closure. Ships per-arm build artifacts; covers non-Pieper 6R and non-SRS 7R geometries.

PythonBSD-3-Clause★ 176 stars⑂ 16 forkssince Apr 2026View on GitHub ↗

personalrobotics/ssik holds a health index of 71 out of 100, placing it in the Good band. It scores highest on Vitality (84/100) and lowest on Security (44/100). It was last updated today. A single contributor accounts for most of its recent work.

71
overall / 100
Good

Software health index

Metrics are grouped into weighted categories on one standardized 1–100 scale. Overall starts as their weighted mean, calibrated against the distribution of the public record so bands carry percentile meaning; when public evidence triggers the High-Risk Jurisdiction Policy, the rating is adjusted and receives an At Risk ceiling of 34.

71
Exceptional93-100The record's top tier (≈ top 5%); essentially all checked criteria met
Excellent80-92Strong across the board; minor gaps
Good65-79Healthy; gaps are limited and manageable
Moderate50-64Acceptable with notable gaps; review recommended
Weak35-49Material weaknesses across several areas
At Risk20-34Significant weaknesses; adoption warrants caution
Critical1-19Severe 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.

The weighted overall 63 is calibrated to 71 on the published index scale (record calibration 2026-08-02).

Ownership

97 followers242 public repossince Jun 2013

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

Package ecosystems

RegistryPackageVersionDownloads / moVersionsLast publishTags
PyPIssik4.1.05,251220 days agoik-geoinverse-kinematicskinematicsrobotics

Metrics by category

Vitality

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

84Excellent · 21% of overall
How it's scored
36/36Push recency — last push 0 days ago
9.7/36Commit cadence — 14/52 weeks with commits
18/18Commit volume — 283 commits in the last year
10/10OpenSSF Scorecard: Maintained — 30 commit(s) and 29 issue activity found in the last 90 days -- score normalized to 10
Inputs used
commits_last_year283
human_commit_share1
days_since_last_push0
active_weeks_last_year14

Release discipline

100Exceptional
How it's scored
27/27Ships releases — 20 releases published
36/36Release recency — latest release 0 days ago
27/27Release cadence — a release every ~5.6 days
0/10OpenSSF Scorecard: Signed-Releases — no data
Inputs used
releases_count20
latest_release_tagv4.1.0
releases_from_tagsno
days_since_latest_release0
mean_days_between_releases5.6
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?

59Moderate · 17% of overall
How it's scored
36.4/60Stars — 176 stars
9.8/25Forks — 16 forks
1.7/15Watchers — 3 watchers
Inputs used
forks16
stars176
watchers3
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
How it's scored
22.5/22.5README
22.5/22.5License — recognized license (BSD-3-Clause)
18/18CONTRIBUTING guide
0/13.5Code of conduct
0/7.2Issue template
0/6.3PR template
Inputs used
has_readmeyes
has_licenseyes
readme_badges
has_contributingyes
has_issue_templateno
has_code_of_conductno
readme_badge_services
has_pull_request_templateno
How it's scored
49.6/80Monthly downloads — 5,251 downloads/month across pypi
0/20Registry dependents — not reported by this ecosystem
Inputs used
packagesssik
dependents
ecosystemspypi
total_downloads
monthly_downloads5,251
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?

61Moderate · 23% of overall
How it's scored
9/54Bus factor — 1 contributor(s) cover half of all commits
0.3/22.5Commit distribution — top contributor authored 99% of commits
2.7/13.5Contributor breadth — 2 contributors
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Inputs used
bus_factor1
contributors_sampled2
top_contributor_share0.986
How it's scored
39.4/42Issue resolution — 94% of issues closed
28.2/30PR acceptance — 254/270 decided PRs merged
0/13Newcomer PR acceptance — no first-time contributor's PR decided in 30d
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Inputs used
merged_prs254
open_issues13
closed_issues196
prs_merged_7d
prs_decided_7d
prs_merged_30d
prs_decided_30d
issue_closed_ratio0.938
closed_unmerged_prs16
first_time_authors_30d
first_time_prs_merged_30d
first_time_prs_decided_30d
Excluded from scoring (no data or not applicable): newcomer_pr_acceptance. Remaining weights renormalized.
How it's scored
30/30Ownership backing — organization-owned
0/20Verified domain
14.3/25Owner reach — 97 followers of personalrobotics
25/25Track record — 242 public repos, account ~13 yr old
Inputs used
followers97
owner_typeOrganization
is_verified
owner_loginpersonalrobotics
public_repos242
account_age_days4,794

Package maintenance

100Exceptional
How it's scored
25/25Published & resolvable — 1 package(s) on pypi
35/35Publish recency — latest publish 0 days ago
20/20Version history — 22 published versions
20/20Not deprecated — active, not deprecated or yanked
Inputs used
packagesssik
ecosystemspypi
any_deprecatedno
min_days_since_publish0

Engineering Quality

Are baseline engineering and documentation practices in place?

66Good · 19% of overall
How it's scored
24/24CI workflows — 3 workflow(s)
24/24Tests present
0/16Linter config
0/9.6Pre-commit hooks
0/6.4.editorconfig
18/20OpenSSF Scorecard: CI-Tests — 29 out of 30 merged PRs checked by a CI test -- score normalized to 9
Inputs used
has_ciyes
has_testsyes
has_editorconfigno
has_linter_configno
has_precommit_configno
How it's scored
30/30README
25/25Documentation directory
0/15Documentation / homepage site
10/10Repository description
0/10Topics
0/10Wiki
Inputs used
topics
has_wikino
homepage
has_readmeyes
has_docs_diryes
has_descriptionyes

Security

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

44Weak · 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
2.2/2.5CI-Tests — 29 out of 30 merged PRs checked by a CI test -- score normalized to 9
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5License — license file detected
7.5/7.5Maintained — 30 commit(s) and 29 issue activity found in the last 90 days -- score normalized to 10
5/5Packaging — packaging workflow detected
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — no data
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
0/7.5Vulnerabilities — 29 existing vulnerabilities detected
Inputs used
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate4.4
Excluded from scoring (no data or not applicable): signed_releases. Remaining weights renormalized.

AI Readiness

How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight (4%): agent tooling is a real maintenance signal, but a repository with none can still reach 100/100.

50Moderate · 4% of overall
How it's scored
0/45Agent instructions — no CLAUDE.md / AGENTS.md / editor rules
0/15Machine-readable docs (llms.txt)
40/40Legible commit history — 100 of 100 human commits state their intent (structured subject or explanatory body)
Inputs used
has_llms_txtno
legible_history_share1
agent_instruction_files
agent_instruction_max_bytes
How it's scored
0/18One-command bootstrap
22/22Automated tests
0/11Lint / format config
11/11Static type checking — src/ssik/py.typed
10/10Reproducible environment — lockfile
8/10Demonstrated agent practice — 4 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
lockfilesuv.lock
has_dockerfileno
typed_languageno
bootstrap_files
has_devcontainerno
has_linter_configno
typecheck_configssrc/ssik/py.typed
agent_commit_share0.04
toolchain_manifests
dependency_bot_commit_share0
How it's scored
27/45Type-checkable code — Python with type-check config (src/ssik/py.typed)
52/55Manageable file sizes — 21/380 source files over 60KB
Inputs used
primary_languagePython
largest_source_bytes1,081,439
source_files_sampled380
oversized_source_files21
How it's scored
0/40API schema (OpenAPI/GraphQL/proto)
0/20MCP server
40/40Runnable examples — examples
Inputs used
example_dirsexamples
has_mcp_signalno
api_schema_files

Key facts

176GitHub stars
2contributors
283commits, last 12 months
0days since last push
20releases
1bus factor
13open issues
PyPIpackage 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
  • deps.dev does not index pypi:ssik@4.1.0; advisories assessed against the repository dependency graph instead

More detail

Star and fork history 0 ★ / 16 ⇿
0Stars
16Forks
12Releases

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.

468101214161672026-062026-062026-07
Major 2Minor 6Patch 4
OpenSSF Scorecard 4.4 / 10
4.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-08-01 13:44 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
9CI-Tests29 out of 30 merged PRs checked by a CI test -- score normalized to 9
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 29 issue activity found in the last 90 days -- score normalized to 10
10Packagingpackaging workflow detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
n/aSigned-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
0Vulnerabilities29 existing vulnerabilities detected
Direct dependencies 5
RegistryPackageVersion constraintManifest
PyPInumpy>=1.26pyproject.toml
PyPItomli>=1.1.0pyproject.toml
PyPIscipy>=1.13pyproject.toml
PyPIsympy>=1.10pyproject.toml
PyPIcython>=3.1pyproject.toml
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

Raw JSON report machine-readable
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 15405,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Shell": 4610,
        "Python": 7792103
      },
      "pushed_at": "2026-08-01T13:31:29Z",
      "created_at": "2026-04-19T13:48:08Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-31T20:31:26Z",
      "description": "Analytical inverse kinematics for 6R and 7R revolute arms. Returns every IK branch at machine-precision FK closure. Ships per-arm build artifacts; covers non-Pieper 6R and non-SRS 7R geometries.",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "BSD-3-Clause",
      "default_branch": "main",
      "license_spdx_raw": "BSD-3-Clause",
      "primary_language": "Python",
      "significant_languages": [
        "Python"
      ]
    },
    "owner": {
      "blog": "https://personalrobotics.cs.washington.edu/",
      "name": "Personal Robotics Laboratory",
      "type": "Organization",
      "login": "personalrobotics",
      "company": null,
      "location": "University of Washington",
      "followers": 97,
      "avatar_url": "https://avatars.githubusercontent.com/u/4705918?v=4",
      "created_at": "2013-06-15T16:24:49Z",
      "is_verified": null,
      "public_repos": 242,
      "account_age_days": 4794
    },
    "license": {
      "state": "standard",
      "spdx_id": "BSD-3-Clause",
      "raw_spdx": "BSD-3-Clause",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v4.1.0",
          "kind": "minor",
          "published_at": "2026-08-01T13:42:44Z"
        },
        {
          "tag": "v4.0.0",
          "kind": "major",
          "published_at": "2026-07-31T13:34:58Z"
        },
        {
          "tag": "v3.3.0",
          "kind": "minor",
          "published_at": "2026-07-23T20:13:56Z"
        },
        {
          "tag": "v3.2.0",
          "kind": "minor",
          "published_at": "2026-07-20T13:02:44Z"
        },
        {
          "tag": "v3.1.0",
          "kind": "minor",
          "published_at": "2026-07-13T18:45:15Z"
        },
        {
          "tag": "v3.0.0",
          "kind": "major",
          "published_at": "2026-07-07T18:16:49Z"
        },
        {
          "tag": "v2.3.0",
          "kind": "minor",
          "published_at": "2026-06-19T15:03:39Z"
        },
        {
          "tag": "v2.2.0",
          "kind": "minor",
          "published_at": "2026-06-15T16:22:04Z"
        },
        {
          "tag": "v2.1.0",
          "kind": "minor",
          "published_at": "2026-06-12T21:54:04Z"
        },
        {
          "tag": "v2.0.0",
          "kind": "major",
          "published_at": "2026-06-11T18:34:09Z"
        },
        {
          "tag": "v1.3.0",
          "kind": "minor",
          "published_at": "2026-06-05T17:46:56Z"
        },
        {
          "tag": "v1.2.4",
          "kind": "patch",
          "published_at": "2026-06-04T18:04:40Z"
        },
        {
          "tag": "v1.2.3",
          "kind": "patch",
          "published_at": "2026-06-03T20:22:20Z"
        },
        {
          "tag": "v1.2.2",
          "kind": "patch",
          "published_at": "2026-06-03T17:59:29Z"
        },
        {
          "tag": "v1.2.1",
          "kind": "patch",
          "published_at": "2026-06-02T15:05:40Z"
        },
        {
          "tag": "v1.2.0",
          "kind": "minor",
          "published_at": "2026-05-21T03:54:48Z"
        },
        {
          "tag": "v1.1.1",
          "kind": "patch",
          "published_at": "2026-05-19T00:06:35Z"
        },
        {
          "tag": "v1.1.0",
          "kind": "minor",
          "published_at": "2026-05-18T00:06:43Z"
        },
        {
          "tag": "v1.0.1",
          "kind": "patch",
          "published_at": "2026-05-14T16:53:42Z"
        },
        {
          "tag": "v1.0.0",
          "kind": "major",
          "published_at": "2026-05-14T01:09:04Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "889c6f239f9793e11abd9a7e1286cf1b92b2c374",
          "body": "… (#478)\n\n3.10 was half-supported (requires-python >=3.10 + tomli/ruff accommodations) but\nshipped no cp310 wheel, listed no 3.10 classifier, ran no 3.10 CI, and warned at\nimport that it was \"best-effort, untested\". ROS2 Humble (Ubuntu 22.04, Python\n3.10, EOL May 2027) needs it, so make it real:\n\n- \n[…]\nImport\nis warning-free on 3.10. ruff + mypy clean. mypy stays python_version=3.11 (the\n3.10 target only adds spurious numpy .copy() no-any-return noise; ruff py310 +\nthe 3.10 CI run gate real compat).",
          "is_bot": false,
          "headline": "Make Python 3.10 a first-class supported version (ROS2 Humble) (#477)…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-31T20:31:16Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "68275b40738ac8cd16663c48c49ea678b7c6b25e",
          "body": "arm_coverage.md linked ../tests/test_prebuilt_fixture_parity.py (a source file\noutside the docs tree), which mkdocs --strict rejects as an unresolved doc link\n-- silently red on main since #422 (the Docs workflow is push-triggered, not a\nPR gate). Point at the GitHub blob URL instead; strict build passes.",
          "is_bot": false,
          "headline": "docs: fix broken source-file link that fails mkdocs --strict (#476)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-31T13:24:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c955cd535cf038b2aed000693403843119fe9e05",
          "body": "WidowX 250s: 6-DOF spherical-second-two-parallel -> ikgeo.spherical_two_parallel\n(tier 0), 100% coverage, worst FK 6.8e-13, ssik 0.53 ms / 8 sols. EAIK-comparable\nvia the DH path (supported, 6R-SPHERICAL_SECOND_TWO_PARALLEL). Kinematics-only\nMJCF fixture reconstructed by `ssik add-arm`. Source: robot_descriptions /\nwidow_mj_description (MuJoCo Menagerie trossen_wx250s, BSD-3-Clause). Second arm\nunder the trossen vendor.",
          "is_bot": false,
          "headline": "Onboard Trossen WidowX 250s (MJCF-sourced prebuilt) (#475)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-31T13:13:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9010f46b8e585163e6a3dc16e95adb7d3210d12f",
          "body": "* Onboard Trossen ViperX 300s as the first MJCF-sourced prebuilt\n\nFirst arm shipped from a MuJoCo MJCF source (via #470/#471). ViperX 300s is a\n6-DOF spherical-second-two-parallel arm -> ikgeo.spherical_two_parallel (tier 0),\n100% coverage, worst FK 3.7e-14, ssik 0.31 ms / 8 sols. Fixture is the\nkin\n[…]\nm -> a real comparison (ViperX:\n  supported, 6R-SPHERICAL_SECOND_TWO_PARALLEL, 8 sols, FK 8.5e-16) instead of a\n  spurious \"No module named\" refusal.\n\n* Add viperx300s_ik perf baseline ratio (ref=ur5)",
          "is_bot": false,
          "headline": "Onboard Trossen ViperX 300s (first MJCF-sourced prebuilt) (#473)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-31T05:22:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e4b4ad9b89f96d7fb03e98894a5892810fff2337",
          "body": "…0 follow-up) (#472)\n\n`suggest_base_ee` (URDF + MJCF) backs the end-effector off trailing gripper/tool\nbodies by name. But a body *named* like a gripper can carry a real arm joint:\nTrossen ViperX/WidowX put the 6th DOF (wrist-rotate) in `gripper_link`, so the\nname-only trim returned a 5-DOF chain th\n[…]\n (iiwa14, panda, ur5, gen3) are unchanged.\n\nTests: synthetic 6-DOF-arm-with-gripper-named-6th (URDF) + real ViperX/WidowX\n(MJCF) keep the 6th DOF; the existing 3-DOF-toy trim still lands on the wrist.",
          "is_bot": false,
          "headline": "add-arm auto-detect: don't trim a gripper-named body below 6 DOF (#47…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-31T04:31:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "640caedb97b1d7068556423cbef3957aee613c6a",
          "body": "…stry (#470) (#471)\n\n`ssik add-arm` (plus `ssik build`/`dispatch`, `regen_artifacts`, and the MANIFEST\nschema) was URDF-specific. This makes source-format ingestion pluggable so an\nMJCF-only arm onboards as a shipped prebuilt, and a future format (USD/SDF, #83)\nis one adapter module -- no edits to t\n[…]\ndispatch to seven_r.srs,\nbuild + coverage-gate at 100% coverage / worst FK 1.9e-12. URDF path is\nbehavior-preserving: artifact snapshots byte-identical, full URDF/manifest/CLI\nsuite (319 tests) green.",
          "is_bot": false,
          "headline": "add-arm: onboard MuJoCo MJCF arms via a pluggable format-adapter regi…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-31T04:07:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c00c95733b599a978963498084a2b97a16fbf006",
          "body": "… (#469)\n\nThe MJCF->KinBody loader landed in #343/#344 but was only reachable via the\ninternal load_mjcf_kinbody_normalized(path, base, ee). This wires it into the\npublic API so an MJCF-only arm is one call from IK, mirroring from_urdf:\n\n- suggest_base_ee_mjcf(path): auto-detect (base, ee) for the l\n[…]\nwa14 -> seven_r.srs 94 sols @ 1.9e-15; gen3 ->\nsrs_polished 73 sols @ 2.6e-16).\n\nadd-arm MJCF support (vendoring a prebuilt artifact from an MJCF, incl.\n<include>/mesh assets) is a separate follow-up.",
          "is_bot": false,
          "headline": "Add Manipulator.from_mjcf public entry point + MJCF auto-detect (#83)…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-31T02:53:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6e3ee568fe99b83f49db2e035155274f2afd2002",
          "body": "…7) (#468)\n\nsrs_polished, spherical_shoulder_polished, and the approximate-SRS in-limits\nresolver each hand-rolled the same tail: build the _fk/_jac closures, batch-\nNewton-polish every seed, keep rows that FK-close (and, for two of them, land\nin-limits), then dedup_by_wrap_close. ~20 lines x 3, and\n[…]\n (j2s7 0, yumi_left 8, yumi_right 3, gen3 0 per 1000).\n\njointlock.seven_r is deliberately out of scope (exact HP per locked-joint\nsample, no polish; its #459 gap is sampling density, a different fix).",
          "is_bot": false,
          "headline": "Unify the polished-7R solver tail into _polish.polish_candidates (#46…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-30T19:15:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2fd4952d13a27fe00d68a78e6cf8dd5be55f74e6",
          "body": "…(#465)\n\nThe approximate-SRS in-limits fallback (#370, srs_polished arms) dropped\n~0.5-2% of reachable in-limits poses on the default respect_limits=True\npath. Root cause: seeds came from feasible_in_limits_solutions, which\nfilters swivels by the joint limits evaluated on the *approximate* q(psi)\n*b\n[…]\nndom-restart finds it, which is not a\nprincipled closed-form path, so it stays tracked in #462 and xfailed.\n\nPerf gate unaffected: it benchmarks respect_limits=False, which never enters\nthis fallback.",
          "is_bot": false,
          "headline": "Close approximate-SRS in-limits gap via unfiltered seed union (#462) …",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-30T17:18:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b77d8c494bffe4ee6678fd5279c1ac276b1efc76",
          "body": "…(#464)\n\nAnswers 'if someone adds an arm with this issue, do we warn them?' -- previously\nno: add-arm FAILED gross gaps (<90%) but printed a clean VALIDATED for the ~1%\nclass, and sampled only 64 poses (too few to see 1%).\n\nNow the onboarding coverage gate has three bands (_coverage_band):\n- < 90%  \n[…]\ntly clean (its gap is <1%). Band thresholds unit-tested.\n\nComplements the #359 slow guard + the #463 non-slow CI coverage floor: the CI\ngates catch regressions, this warns the contributor at add time.",
          "is_bot": false,
          "headline": "add-arm: warn when a new arm has a >1% in-limits coverage gap (#462) …",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-29T23:30:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a7b64a5d6f639a5e405680b8359e737442c7e52f",
          "body": "…s_polished gaps (#462) (#463)\n\nAuditing the shipped roster for the coverage worry surfaced two things:\n\n1. yumi_left_ik + j2s7s300_ik (both srs_polished) fail the #359 in-limits\n   coverage guard -- ~0.5-1% of reachable in-limits poses return [] on the\n   default respect_limits=True path. Root caus\n[…]\nthe\n   default suite (~15s). Generous enough for the ~1% known sliver, tight enough\n   to catch a Star1-class gap at PR time.\n\nSlow suite: 17 passed, 2 xfailed. Fast smoke: 19 passed. ruff/mypy clean.",
          "is_bot": false,
          "headline": "Harden the default-path in-limits coverage guard; document 2 known sr…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-29T18:42:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e4d3eda7438e6deb6b6c31eab0722299192efc8e",
          "body": "…ling fixes (#292) (#461)\n\nTwo Apache-2.0 Rokae collaborative arms (RokaeRobot/rokae_ros2), non-Pieper\ngeneral_6r (offset wrist) that EAIK can't decompose ('6R-Unknown Kinematic\nClass') -- EAIK-gap showcase like Doosan/HC10. 100% coverage, ~1 ms. Roster\n68 -> 70.\n- rokae.xmatecr7_ik  (xMate CR7)\n- r\n[…]\nr-solver floor); other\n   machine-precision solvers keep their tight smoke-derived value.\n\nGate green (sanity 70/70, uniform_fuzz, manifest/snapshot/perf/scaffolds +\nbaseline + docs); ruff/mypy clean.",
          "is_bot": false,
          "headline": "Rokae xMate CR7 + SR3 cobots (EAIK-gap general_6r) + 2 general_6r cei…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-29T17:49:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5a4ad8055b86a24e0eaf74ee30172008ca014816",
          "body": "Standalone Apache-2.0 7R arm (RokaeRobot/rokae_ros2). Unlike RM75 (~1um vendor-URDF\ndrift -> srs_polished), xMate Pro7's URDF hits STRICT seven_r.srs: 100% coverage,\nFK 5.3e-14 (machine precision, no LM polish), 128 sols, 6.7 ms. A rare vendor URDF\nthat is exactly SRS-concurrent. EAIK refuses (7R). Roster 67 -> 68.\n\nGate green (manifest/uniform_fuzz/sanity/snapshot/perf/scaffold + baseline + docs);\nruff/mypy (244 files) clean.",
          "is_bot": false,
          "headline": "Onboard Rokae xMate Pro7 (7R, strict SRS) (#292) (#458)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-29T05:27:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ec37d708f9cc0cceabe57dfbbfd419333c15b19d",
          "body": "* Onboard 8 cobot/industrial 6R arms across 6 vendors (#292)\n\nWave 2/4 breadth, all validated 100% via the automated add-arm. Roster 59 -> 67.\n\nPieper spherical-wrist 6R (ikgeo.spherical_two_parallel), EAIK-supported:\n- mitsubishi.rv4fr_ik   (Mitsubishi RV-4FR, Apache-2.0)\n- hyundai.hh020_ik      (H\n[…]\n correctly (1e-4); only\nthe scaffold was wrong. Derive the scaffold ceiling by solver class\n(_scaffold_fk_ceiling): general_6r -> 1e-4, everything else -> 1e-6. Regenerated\nthe 3 general_6r scaffolds.",
          "is_bot": false,
          "headline": "Onboard 8 cobot/industrial 6R arms across 6 vendors (#292) (#457)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-29T05:02:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "24eec3dc25acd36d6249a534e89ddbaaaa64a6f4",
          "body": "Two Apache-2.0 Realman 7R arms, top 2024-2025 research popularity (Chinese\nhumanoids / RealSource dataset). Roster 57 -> 59.\n\n- realman.rm75_ik  (RM75-B): approximate-SRS 7R (~1um URDF drift), seven_r.srs_polished,\n  10 ms, FK 1e-12, 128 sols, 100% coverage.\n- realman.gen72_ik (GEN72): spherical-sho\n[…]\nectively for spec-authored fixtures (iiwa14).\n\nGate green (manifest/uniform_fuzz/sanity/parity/snapshot + rescue/dispatch/perf\ngates + regenerated baseline); ruff/mypy (235 files) clean; docs in sync.",
          "is_bot": false,
          "headline": "Onboard Realman RM75 + GEN72 (7R research arms) (#292) (#456)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-29T03:36:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "61339860888a79af8b3b1842cc272a6f7a92098a",
          "body": "…00iD + R-2000iC, Staubli RX160 (#292) (#455)\n\nFive more industrial spherical-wrist Pieper 6R flagships across five vendors, all\nvia the automated add-arm (#454): class metadata + sample_q auto-derived, only\nfixture_source + display strings hand-filled. Roster 52 -> 57. All dispatch to\nikgeo.spheric\n[…]\nnifest/uniform_fuzz/sanity/parity/snapshot/namespace/scaffolds +\nrescue/dispatch/perf gates + regenerated perf baseline); ruff/format/mypy (233\nfiles) clean; regen_docs --check in sync. Advances #292.",
          "is_bot": false,
          "headline": "Onboard Wave 2 batch 2: Yaskawa GP8, Kawasaki RS007N, FANUC LR Mate 2…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-29T03:03:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2e2db1a2010b84cde1eb295e9b43f900985fc33a",
          "body": "…ifest TODOs) (#425) (#454)\n\nOnboarding the ABB/KUKA Wave 2 batch, I hand-filled kinematic_class /\nshort_class / class_tags for all 5 by copying a same-class neighbour -- pure\nmechanical work that's a function of the dispatched solver (class_tags is one\ndistinct set per solver across the whole roste\n[…]\nprovenance) and the marketing display strings. Reduces ~6 TODOs to ~2.\n\nTest: add-arm on UR5 emits the derived three-parallel class + a non-placeholder\nsample_q + a display_name. CONTRIBUTING updated.",
          "is_bot": false,
          "headline": "add-arm: derive class metadata, sample_q, and display_name (fewer man…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-29T00:42:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8c07e54b44d1ed43b0ffde1efe9d47125fd3e203",
          "body": "… (#292) (#453)\n\nFive industrial spherical-wrist Pieper 6R arms, the first Wave 2 flagships\n(install-base breadth). All dispatch to ikgeo.spherical_two_parallel, validate at\n100% coverage, and EAIK-agree (all supported, ~3us). Roster 47 -> 52.\n\n- abb.irb120_ik / irb1600_ik / irb6700_ik   (ros-indust\n[…]\nind sibling)).\n28-file gate green (manifest, uniform_fuzz, sanity, parity, snapshots, namespace,\nscaffolds, rescue/dispatch/perf gates); ruff/format/mypy (228 files) clean;\nregen_docs --check in sync.",
          "is_bot": false,
          "headline": "Onboard Wave 2 batch 1: ABB IRB 120/1600/6700 + KUKA KR6 R900 / KR210…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-29T00:34:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "571d45add91a90c27999f2e25bba34bf2f2b2276",
          "body": "…#425) (#452)\n\nIndustrial vendor descriptions (ABB, KUKA, FANUC via ros-industrial) split a\nrobot across sibling ROS packages: irb120_3_58.xacro in abb_irb120_support does\n<xacro:include filename=\"$(find abb_resources)/...\"/> for shared materials.\nxacrodoc couldn't resolve $(find abb_resources) unle\n[…]\nhrough full add-arm: VALIDATED 100%, worst FK 1.2e-13).\n\nSelf-contained two-package test fixture (robot_support includes\n$(find shared_resources)); 3 tests green. Advances #425 (one-click onboarding).",
          "is_bot": false,
          "headline": "Resolve multi-package ROS xacros in ingestion ($(find sibling_pkg)) (…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T22:37:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8f63a47960c0889c1e1ea1d492470c0c034ed16c",
          "body": "…lently (#445) (#451)\n\n--no-validate skips the minutes-long artifact build + coverage gate for\nslow-build (cached-RR 7R) arms -- but it used to skip onboarding validation\nENTIRELY, so the riskiest arms (0 IK / [0,0]-locked limits / wrong ee) could\nscaffold green with no verdict. The onboarding gate \n[…]\nefore shipping. A 0-coverage smoke prints a LIKELY BROKEN diagnosis.\n\nTested: --no-validate now prints the live-smoke verdict + UNVALIDATED reminder\n(new test); full add-arm suite green.\n\nCloses #445.",
          "is_bot": false,
          "headline": "add-arm --no-validate: run a live-solver smoke instead of skipping si…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T21:49:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d66790b2d6441e2da1d013700a58413bd3ce4107",
          "body": "…ine (#436) (#450)\n\nscripts/regen_bench.py measures per-arm solve time and the manifest stores it,\nbut nothing fails CI if a solver change regresses speed. Absolute-ms assertions\ncan't work: the manifest ms_mean was measured on a dev machine and would\nfalse-fail on a Linux runner.\n\nGate on RELATIVE \n[…]\nA coverage-floor test (test_baseline_covers_benched_arms)\nforces a baseline refresh when an arm is onboarded; CONTRIBUTING documents the\nregen step. 50 passed (47 arms + 3 meta) in ~13s.\n\nCloses #436.",
          "is_bot": false,
          "headline": "Add perf-regression gate via machine-independent relative-ratio basel…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T21:46:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "da88d26149d46bddb527f24ecb5ee663a9c54abc",
          "body": "…ource prose (#444) (#449)\n\nThe upstream FK-parity test parsed the robot_descriptions module name out of the\nhuman fixture_source prose. Two failure modes hit during the iiwa7/j2s7\nonboarding (#443): a paren-annotated source ('robot_descriptions /\ndifferentiable-robot-model (kuka_iiwa/iiwa7)') parse\n[…]\nken migration or bulk field\nremoval can't quietly gut parity while leaving one arm green.\n\n29 passed; regen_docs --check in sync; test_manifest green; ruff/format/mypy\n(221 files) clean.\n\nCloses #444.",
          "is_bot": false,
          "headline": "Structured upstream_description field: decouple parity from fixture_s…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T21:13:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "97f98c88088e8a3d9a8e4cd6f0ce825d294ee3d2",
          "body": "…(#435) (#448)\n\nThe #433 composer canonicalization fix touched all three spherical-wrist\ncomposers (spherical_two_parallel, spherical_two_intersecting, generic\nspherical), but the never-again parity guard only covered spherical_two_parallel.\nGeneralize it: parametrize over all three topologies x (ca\n[…]\n composer/live divergence remains.\n\n6 passed (3 composers x 2 gauges). Closes #435 (items 1-2; item 3, a single\nmerged gauge-fuzz test, is unnecessary -- axis-sign and flange-offset are each\nguarded).",
          "is_bot": false,
          "headline": "Extend flange-offset parity guard to all 3 spherical-wrist composers …",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T21:06:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6dd0bc7f5ef29cf0a3a8e1ba23fb123912fc8cf3",
          "body": "Several tier-0 7R solvers are picked by predicates that can match the same arm\n(the two approximate predicates overlap; strict-SRS is a subset of\napproximate-SRS). Which one wins is pure dispatch order, and nothing validated\nthat the chosen solver maximizes coverage.\n\nj2s7s300 (#440) exposed this: i\n[…]\n_gap_is_real) that measures the\nreal j2s7 gap (srs_polished >> spherical_shoulder_polished) and asserts dispatch\npicks srs_polished -- fails on a #440 revert. 8 passed, 9 skipped in ~9s.\n\nCloses #442.",
          "is_bot": false,
          "headline": "Add dispatch coverage-optimality gate (#442) (#447)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T20:50:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8f0bb431092bb6447fa6b04bf99b44222c8fbaa8",
          "body": "…#441) (#446)\n\nEvery prebuilt solve() has a T-perturbation rescue that backfills when the\nanalytical solver returns nothing. It is legitimate for singular/borderline\nposes but can mask a broken analytical solver: an arm can read 100% coverage on\nthe default path while its native closed-form solver r\n[…]\nss regression (native 0.0) fails.\n\nThe threshold is a pure, unit-tested function (test_gate_has_teeth) so the band\nlogic is verified without needing a live broken arm. 46 passed in ~27s.\n\nCloses #441.",
          "is_bot": false,
          "headline": "Add rescue-dependence gate: no arm may lean on the numerical rescue (…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T20:45:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "35feace97c2083d0f7f948bdad6402316ef40d4a",
          "body": "Both arms were the last two blocked on #424, now fixed at the solver/dispatch\nlevel (#439 iiwa7 offset-wrist SRS, #440 j2s7 dispatch precedence). Ship them:\n\n- iiwa7_ik (seven_r.srs, kuka): 5.8ms, 128 sols, worst FK 5.1e-14. Offset-wrist\n  SRS -> general Davenport path. Fixture reused from #439 (kuk\n[…]\n7 matches upstream; j2s7 non-robot_descriptions\nsource so parity-skipped), test_artifact_snapshots, test_prebuilt_namespace all\ngreen for both arms; regen_docs --check in sync; ruff/format/mypy clean.",
          "is_bot": false,
          "headline": "Onboard KUKA iiwa7 + Kinova j2s7s300 as prebuilts (closes #424) (#443)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T20:30:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b4cb4558f5f0947e1231f5df5b2d3f38ade9b54d",
          "body": "…lder (j2s7, #424) (#440)\n\nKinova j2s7s300 has an exact spherical wrist and a near-spherical shoulder\n(1.6mm drift). It matches BOTH is_approximately_spherical_shoulder_7r and\nis_approximately_srs_7r, and the dispatcher checked the spherical-shoulder\npredicate first -- routing j2s7 to seven_r.spheri\n[…]\nolver, correctly retained; Gen3/YuMi\n-> srs_polished; Franka/FR3 -> exact spherical_shoulder). j2s7 now 38% -> 100%.\n\nAdds tests/fixtures/j2s7s300.urdf + routing and 50-pose coverage regression\ntests.",
          "is_bot": false,
          "headline": "Route spherical-wrist near-SRS 7R to srs_polished, not spherical_shou…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T18:37:47Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "23d3630c25faa499a602eb6c73bf43ba9309427d",
          "body": "…439)\n\n* Fix seven_r.srs returning 0 solutions on offset-wrist SRS arms (iiwa7, #424)\n\nThe native SRS solver has two extraction paths: a fast vectorized canonical\nZYZ path (iiwa-class) and a general Davenport path (#354). The canonical path\nuses joint 5's frame origin as the wrist-pivot reference fo\n[…]\n, poisoning downstream arg types),\nimport _classify_srs_7r_geometric from its home module ssik.kinematics.predicates\n(srs re-imports but doesn't re-export it), and narrow the SrsClassification | None.",
          "is_bot": false,
          "headline": "Fix seven_r.srs 0-solutions on offset-wrist SRS arms (iiwa7, #424) (#…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T17:45:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "658a77b1881452f63175a9f54a70828669553e5f",
          "body": "…y (#425) (#438)\n\nadd-arm printed a ready-to-paste MANIFEST.toml stanza but you still had to\nhand-copy it into the file. --write-manifest appends the derived stanza to\n<repo-root>/src/ssik/prebuilt/MANIFEST.toml directly. It refuses to clobber an\nexisting [arms.<name>] entry unless --force (which re\n[…]\nk add-arm' and a shipped\nprebuilt (#425 friction log).\n\nTested: append writes valid TOML preserving existing entries; --force replaces\nwithout duplicating; a second add without --force errors cleanly.",
          "is_bot": false,
          "headline": "Add 'ssik add-arm --write-manifest' to append the stanza automaticall…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T16:25:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "19d7e21fff2a7cb529ce0dee1e6d3a71413893f4",
          "body": "The onboarding-robustness work (#425/#428/#430) went into the CLI only.\nfrom_urdf, the public library entry point, still loaded the URDF directly:\npackage:// meshes under an xmlns:xacro namespace failed with\nPackageNotFoundError (xacrodoc resolves them during expansion), and base/ee\nwere required.\n\n\n[…]\nads FK-identically to the clean fixture,\nthe non-stripping loader still raises PackageNotFoundError on it (teeth), and\nbase/ee auto-detection yields a solvable arm (FK->IK->FK round-trip).\n\nFixes #434",
          "is_bot": false,
          "headline": "Make Manipulator.from_urdf as robust as ssik add-arm (#434) (#437)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T16:14:44Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0970de6e22eed17485e4ee2392bcfdb3aaa48a74",
          "body": "…nova j2s6s300 (#424) (#433)\n\nRoot cause of the #424 \"fanuc gauge\" / \"j2s6 [0,0]\" bugs (both were the SAME\nbug, not gauge/limits): the ikgeo spherical-wrist COMPOSERS did not call\n`canonicalize_spherical_wrist(kb)` before baking constants, while their LIVE\nsolvers do (spherical_two_parallel.solve li\n[…]\nund via the new add-arm coverage gate (#427/#432), which flagged the\n0-coverage artifacts at onboarding. Closes the fanuc + j2s6 items in #424.\n\nRefs #424, #292. Unblocks the Wave 2 industrial roster.",
          "is_bot": false,
          "headline": "Fix codegen composer canonicalization gap; onboard FANUC M-710iC + Ki…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T13:16:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "77ed1a37aa397e397b4bc7878049c85e0e5faacd",
          "body": "…ete stanza (#425) (#432)\n\nOnboarding's verdict was a CI round-trip away: add-arm scaffolded, and you\nonly learned an arm was broken (0 solutions) after building + pushing. Now\nadd-arm closes the loop locally.\n\n- add-arm builds the emitted artifact in a temp dir and runs the coverage\n  gate (`ssik._\n[…]\n100% coverage, FK 6.7e-13), and emits\nfk_ceiling_fuzz=1e-09 / platform_drift=false. test_cli_add_arm covers both\npaths (fast arms validate; rizon4 uses --no-validate).\n\nRefs #425 (one-click friction).",
          "is_bot": false,
          "headline": "add-arm: build + coverage-validate the artifact locally; emit a compl…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T00:57:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b9355ce7933aa038bc19e55fa5c951f406792a60",
          "body": "…) (#431)\n\nThe bulletproof coverage gate lived only in generated scaffold code, so\nnothing verified it actually rejects a broken arm -- \"bulletproof\" was\nasserted, not tested. Extract it into `ssik._validation.assert_solve_coverage`\n(one tested implementation) and have the `add-arm` scaffold call it\n[…]\ncatches the FANUC/j2s6 (#424) failure mode.\n- The generated scaffold's coverage test now calls the shared helper instead\n  of an inline loop -- one implementation, tested.\n\nRefs #423 (gate hardening).",
          "is_bot": false,
          "headline": "Extract + test the coverage gate: prove it rejects a broken arm (#423…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-28T00:28:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2c117db4d2c4bd5daf207f91665da072bd588025",
          "body": "Onboarding required hand-tracing every URDF's link tree to find the base\nand end-effector links. `suggest_base_ee()` now derives them: base = parent\nof the first actuated joint (leading `world->base` fixed joints fold in),\nee = the actuated flange of the longest chain, backing off gripper fingers\nby\n[…]\n + coverage), so this is convenience, not a\ncorrectness risk. Verified: UR5, iiwa14, FANUC, YuMi (dual-arm -> yumi_body\n/ yumi_link_7_r) resolve to the correct flange.\n\nRefs #425 (one-click friction).",
          "is_bot": false,
          "headline": "add-arm: auto-detect --base/--ee from the URDF (#425) (#430)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-27T22:59:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9187b5d62d5407a325211c5b07254a4aa9bfe723",
          "body": "Re-onboards YuMi, which was deferred in #424 on a phantom failure: the\n0.1 m FK \"corruption\" was the fixture-parity base-frame bug (fixed in\n#428), not a bad fixture. With the package:// ingestion fix (#428),\n`ssik add-arm <raw-yumi.urdf>` vendors it cleanly with no hand-strip.\n\n- ABB YuMi left + ri\n[…]\neam to 1e-9 (the\ntest that falsely failed before), uniform fuzz coverage + FK, the new\ncoverage-gated scaffold, snapshots, respect_limits invariant, manifest.\n\nRefs #292. Closes the YuMi item in #424.",
          "is_bot": false,
          "headline": "Onboard ABB YuMi (IRB 14000) left + right (#292) (#429)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-27T22:34:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6bcb602cbdca6c67dae2ae8b0bdf34fec216292c",
          "body": "…ame bug (#425, #423) (#428)\n\nTwo onboarding-robustness fixes surfaced by Wave 1 (#292):\n\n1. package:// mesh ingestion. Vendor URDFs (ABB YuMi, FANUC) declare\n   xmlns:xacro but reference meshes by ROS `package://`, so `_is_xacro`\n   matched and routed them through the xacro processor, which failed \n[…]\nm(ee, base)`); a no-op for root-based shipped arms.\n\nTogether these unblock YuMi (fixture verified correct to 1.6e-16).\n\nRefs #425 (one-click friction), #423 (gate correctness). Unblocks part of #424.",
          "is_bot": false,
          "headline": "add-arm: load vendor URDFs with package:// meshes; fix parity base-fr…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-27T22:04:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fd36f16ac51e189269dfc2181fe1f0263c061dd7",
          "body": "* Onboard 7 Wave 1 prebuilts: YuMi L/R, Gen3 Lite, UR7e/12e/15/18 (#292)\n\nAdds the zero-friction Wave 1 arms that pass full validation (500-pose\nuniform fuzz: coverage + FK-closure under each arm's ceiling), all sourced\nfrom robot_descriptions:\n\n- ABB YuMi (IRB 14000) left + right (seven_r.srs_polis\n[…]\nt from a hand mesh-strip workaround for its\npackage:// meshes). The onboarding surfaced build-gate holes (#423) and\none-click friction (#425).\n\nRefs #292. Deferred #424. Hardening #423. Friction #425.",
          "is_bot": false,
          "headline": "Onboard 5 Wave 1 prebuilts: Gen3 Lite + UR7e/12e/15/18 (#292) (#426)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-27T22:02:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2cdefea7ce070882ceed8bc6a094255575cb3af4",
          "body": "…e-arm regen (#423, #425) (#427)\n\nThe Wave 1 onboarding (#292) showed a broken arm (0 solutions) could pass\nthe whole default gate, because the scaffold test asserted \"FK <= tol on\nevery retained IK\" -- vacuously true at zero coverage -- against the raw\nsolver in a tiny [-0.8, 0.8] box, all marked @\n[…]\ny pose the default path covers (guards the iiwa7 #424 bug).\n- CONTRIBUTING updated for the single-arm build + coverage gate.\n\nRefs #423 (gate hardening), #425 (one-click friction). Deferred arms #424.",
          "is_bot": false,
          "headline": "Bulletproof + speed up arm onboarding: coverage-gated scaffold, singl…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-27T22:01:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5109a670e041b842439cb74f501bacbb01f95883",
          "body": "* Organize prebuilt artifacts into vendor subpackages (#421)\n\nMove all 36 prebuilt-arm artifacts from the flat `ssik.prebuilt.<arm>_ik`\nlayout into vendor subpackages `ssik.prebuilt.<vendor>.<model>_ik`\n(e.g. `ssik.prebuilt.universal_robots.ur5_ik`,\n`ssik.prebuilt.fanuc.crx10ia_ik`). The redundant v\n[…]\n-table summaries (now a colon), per user preference. Replacements\nare contextual (colon/comma/parens/sentence-split), not a blanket sub; en\ndashes in numeric ranges and compound names are left intact.",
          "is_bot": false,
          "headline": "Organize prebuilt artifacts into vendor subpackages (#421) (#422)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-26T18:00:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42075738c5fac79b2d9a1c97f95ac44e6656fee1",
          "body": "Onboards CRX-3iA / 5iA / 10iA / 10iA/LP / 20iA/L / 30iA as prebuilt tier-2\nRaghavan-Roth artifacts, rendered from the FANUC-CORPORATION/fanuc_description\nxacro macros (Apache-2.0). All six are the same non-Pieper 6R class as the\nalready-shipped CRX-10iA/L, with the skew wrist (joint 6 ⟂ flange) that\n[…]\nhe\nhonest non-Pieper RR guarantee; the 1e-10 scaffold default stalls on rare\nhard poses at ~1.5e-10 -- a valid machine-precision-adjacent solution, the\n#82 algebraic-seed-precision gap).\n\nCloses #301.",
          "is_bot": false,
          "headline": "Add the 6 FANUC CRX sibling prebuilts (#301) (#420)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-25T21:41:28Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7552b6be5823b3ed6ce7dfce5ea75fab8eaecf0b",
          "body": "The tier-2 Raghavan-Roth path produced FK-wrong candidates (algebraic FK\n~2.0, artifact solve() returning 0 IKs) for 6R arms whose last joint axis\nis not parallel to the flange z -- e.g. the FANUC CRX non-/L siblings\n(joint 6 ⟂ flange). Root cause is NOT the codegen composer (it faithfully\nbakes poe\n[…]\nplus a real-arm regression parametrization over every RR\nfixture, including the concrete CRX-10iA geometry (skew wrist + on-axis\nflange, the projection degeneracy the synthetic sweep can't reproduce).",
          "is_bot": false,
          "headline": "Fix poe_to_dh terminal frame for skew wrists (#418) (#419)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-25T20:39:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cbd333fbed8f519e5acdca2612a14f9b897133d1",
          "body": "The SRS general-Davenport vectorization (#415) sped up the four exact\nnon-canonical concurrent-axis SRS arms; their published bench numbers\npredated it. Re-measured via scripts/regen_bench (compiled extensions,\nmedian-of-5), normalized to the reference machine by the median factor of\nthree unchanged\n[…]\n unchanged (the bench uses respect_limits=False and #415 is\nbehavior-neutral: 0 parity diffs), so only the timing fields moved.\n\nMANIFEST + regen_docs (README) + the srs.py docstring (~13 -> ~4-5 ms).",
          "is_bot": false,
          "headline": "Refresh bench numbers for the general-path SRS arms after #415 (#417)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-24T17:23:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "69ea82e242164317f2f1fadf704e109093a2b41b",
          "body": "…f py310\n\n#367 lowered the floor to 3.10 but ssik.prebuilt._manifest hard-imports\ntomllib (3.11+ stdlib), so every prebuilt-arm import crashed on 3.10 with\nModuleNotFoundError -- advertising support that was guaranteed broken.\n\n- _manifest.py: fall back to the tomli backport on Python < 3.11.\n- pypr\n[…]\n (E402).\n\nVerified end-to-end on CPython 3.10.17 + numpy 1.26.4: ssik imports, the\nbest-effort warning fires once, and iiwa14_ik.solve returns 84 IKs at\n2.4e-15 FK (the tomllib->tomli path exercised).",
          "is_bot": false,
          "headline": "Make Python 3.10 support actually work: tomllib->tomli fallback + ruf…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-24T17:05:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7261dc0b53897a847d9570a5a06298731a6c9a1d",
          "body": "Emit a one-time UserWarning when ssik is imported under Python < 3.11,\nthe tested minimum and Scientific Python SPEC 0 support floor. Makes the\nbest-effort, untested status of 3.10 explicit to users. See #366.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Warn on best-effort (untested) Python versions",
          "author_name": "Griffin Norris",
          "author_login": "griffin-norris",
          "committed_at": "2026-07-24T17:05:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cf62f35ec25c20e8b5f4049cfd39bcfd66ddaf38",
          "body": "Lower requires-python to >=3.10 and relax the numpy dependency floor\nfrom >=2.0 to >=1.26 to broaden install compatibility.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Support Python 3.10 and numpy 1.26",
          "author_name": "Griffin Norris",
          "author_login": "griffin-norris",
          "committed_at": "2026-07-24T17:05:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "18ff1e7bd2605ae0ad896aed3addf7c61d2ab8cf",
          "body": "Restore the scalar _sp4_branches alongside _sp4_branches_batch: the exact\nin-limits swivel resolver (_swivel_limits, #369) imports the scalar form\nand it landed on main after this branch forked. Behavior-identical to main\nacross all SRS arms (parity-verified, 0 diffs).",
          "is_bot": false,
          "headline": "Reconcile vectorized general path with #369 swivel-limits resolver",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-24T16:29:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "66fbb6f0d62342abc5d6658a0344137236910bd5",
          "body": "The general-path (non-canonical SRS) sweep was a scalar `for i in range(N)`\nloop over the 16 swivels, running the Davenport shoulder/wrist extraction one\nswivel at a time. Restructure it like the canonical ZYZ path: enumerate the\ndiscrete branches (2 elbow x 2 shoulder x 2 wrist) on the outside and \n[…]\nle poses. FK residual unchanged at 2.09e-14.\n\nR1 Pro left: 9.75 -> 5.63 ms/solve; 15.45 -> 5.63 (-64%) vs the pre-series\nbaseline.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Vectorize the general Davenport SRS sweep over the swivel batch",
          "author_name": "Griffin Norris",
          "author_login": "griffin-norris",
          "committed_at": "2026-07-24T16:29:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5b6dc85029c8f8bad3a82c6c0e9bdc3d1accdb16",
          "body": "The general Davenport path in seven_r.srs (used by non-canonical SRS\narms like the Galaxea R1 Pro) is a per-swivel scalar loop that called\nnp.cross / np.linalg.norm / np.eye on length-3 vectors hundreds of\ntimes per solve. On 3-vectors those generic entry points are dominated\nby dispatch overhead (a\n[…]\nath.\nMath is identical; FK residual is unchanged at 2.09e-14.\n\nR1 Pro left arm: 15.45 -> 9.75 ms/solve (-37%) at full enumeration.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Speed up general-SRS 7R solve: scalar 3-vector ops on the hot path",
          "author_name": "Griffin Norris",
          "author_login": "griffin-norris",
          "committed_at": "2026-07-24T16:29:57Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7dbcfbd7c3c5ca89507f9bc972311268872e8a3e",
          "body": "test_oracle3/4 asserted HP must match Raghavan-Roth solution counts on\nJACO 2 -- the premise #409 explicitly rejected. #409 established HP and RR\nare complementary, not competing, universal-6R solvers: RR is the tier-2\ngeneral-6R path; HP is the locked-7R backstop. HP returning fewer branches\nthan R\n[…]\nnearest_wrap) and updates the module docstring + oracle2 comment to\nreflect the retirement.\n\nOracle suite after: 5 passed, oracle6 xfail (legit, #183), oracle5 slow;\nno stray XPASS. ruff + mypy clean.",
          "is_bot": false,
          "headline": "Retire stale HP-vs-RR parity oracles (oracle3/4) on JACO 2 (#414)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-24T13:41:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "ed53ae3b793db29cd74aeb2a258607417fd2e182",
          "body": "…ntract (#413)\n\ntest_gen3_random_pose_fk_closure (slow) called jointlock.seven_r.solve\ndirectly and asserted a non-empty result on every random reachable pose.\nRaw jointlock+HP legitimately returns nothing at measure-zero near-singular\nridges (near-straight elbow, q_3 ~ 0), so seed 173 failed: q_3 =\n[…]\nn-singular, so it validates the raw path on well-conditioned\ninput. Verified: all 10 fuzz seeds pass (was failing at seed 173); full\nGen3 + srs_polished suites 29 passed incl. slow; ruff + mypy clean.",
          "is_bot": false,
          "headline": "Fix stale Gen3 jointlock slow test: assert the production coverage co…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-24T12:54:40Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c4a84bc439a05829e65501ea8cbd73b95565b138",
          "body": "…ne) (#412)\n\nAdds two Mermaid flowcharts to the \"Under the hood\" section:\n\n1. Dispatch tree -- how `dispatch()` classifies a POE-normalized chain by\n   topology and picks the fastest matching solver. 7R closed-form is\n   grouped by family (concurrent shoulder -> wrist concurrent = SRS class,\n   or o\n[…]\ny, and manipulator.solve. Mermaid renders natively on GitHub and\nvia the mkdocs superfences already configured, so no binary asset. Both\ndiagrams validated by rendering with mermaid-cli.\n\nCloses #411.",
          "is_bot": false,
          "headline": "README: add solver-selection decision-tree figure (dispatch + lm_refi…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-24T04:20:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "be8c4b8ef0626400620be912a6cea0f4c39659c2",
          "body": "…ad of crashing (#410)\n\nHP's interpolation-based elimination hits a singular Cramer/pencil matrix\non a large fraction of poses for general (non-locked) 6R geometries such\nas the FANUC CRX-10iA/L. Two code paths could then raise an unhandled\n`numpy.linalg.LinAlgError` out of `solve()`:\n\n- `eliminate_\n[…]\n Verification showed HP is\nload-bearing for symmetric-DH locked-7R sub-chains (live RR misses q_truth\non 9/20 and is 20-75s), so HP stays; this is the one real robustness bug\nthat evaluation surfaced.",
          "is_bot": false,
          "headline": "Harden Husty-Pfurner: degrade to empty on singular-matrix poses inste…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-24T02:54:43Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5ad09c1a8550095a71d5dd8fa7de26c2d42fee67",
          "body": "Lever A (#405) replaced the per-candidate tight-then-loose lm_refine rescue with\na single lm_refine_batch call -- but lm_refine_batch defaults to a TIGHT\ndivergence tolerance (2.0 / 2, tuned for srs_polished in #203), whereas the\nper-candidate lm_refine it replaced used the loose default (5.0 / 4). \n[…]\nv3.2.0\ncount comparison shows ZERO differences across the whole roster.\n\nRegression guard: test_batched_rescue_recovers_full_set_piper_ridge pins the\nexact pose + the >=6 distinct FK-closing recovery.",
          "is_bot": false,
          "headline": "Fix rescue completeness regression from the batched refine (#405) (#408)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-23T18:24:29Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5a222641d139047ba044f0e1722ccaa814904ca9",
          "body": "Gen3 srs_polished dropped from 40.75 to ~13ms with the batched FK+Jacobian\n(#406). Update the number everywhere it appears:\n\n- MANIFEST bench + README EAIK-comparison table: gen3 40.75 -> 12.87 ms.\n- docs/architecture.md: the srs_polished tier row said \"~40 ms full sweep\".\n\nOnly gen3 is updated. A f\n[…]\ne via the median factor of the control arms\n(the ones lever A/C don't touch): 14.79 / 1.15 = 12.87 ms, which matches the\ndirect median measurement. Every other arm keeps its committed reference value.",
          "is_bot": false,
          "headline": "Refresh docs with post-lever-C Gen3 number (~13ms) (#407)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-23T13:21:23Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "94e383bfc708992658ca5190b478d9f890e65556",
          "body": "lm_refine_batch already batches the linalg but called fk_fn / jacobian_fn\nper-candidate -- and those (poe_forward_kinematics + kinbody_jacobian) are\n~50-60% of a Gen3 srs_polished solve. Add kinbody_fk_jacobian_batch: a single\nvectorised chain walk that returns FK (N,4,4) + spatial Jacobian (N,6,dof\n[…]\nsmatic, and test_lm_refine_batch_batched_equals_scalar (same seed\nset converges to the same roots). Full suite 1734 passed.\n\nBench numbers deferred to a roster refresh after the stacked gen3 PRs land.",
          "is_bot": false,
          "headline": "perf: batched FK + Jacobian for the LM-refine inner loop (#406)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-23T12:47:33Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3296ad0264f8ea743231bb00f818e9652ee33091",
          "body": "* perf: batch the T-perturbation rescue's candidate refinement\n\nThe #319 rescue re-solves at each of 16 perturbed poses and Newton-polished\nEVERY returned candidate back to T_target via a per-candidate tight-then-loose\nlm_refine (2 passes x 20 iters). Most perturbed candidates are swivel solutions\nt\n[…]\nored by 16x the base solve cost -- addressed separately\nby batching the FK+Jacobian in the solve/refine inner loop (lever C).\n\n* Annotate polished as Iterable to satisfy mypy (batched/scalar branches)",
          "is_bot": false,
          "headline": "perf: batch the T-perturbation rescue's candidate refinement (#405)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-23T12:46:52Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "574bc5b22efec8ad979c86f933558f3d488ae834",
          "body": "… numbers (#404)\n\n* Guard against benchmarking uncompiled perf extensions; correct the numbers\n\nRoot cause of the inflated bench numbers: this repo cythonizes both poe_fk and\nrefinement (hatch_build.CYTHON_TARGETS, #248), but a dev checkout that built\nonly poe_fk.so ran the refinement layer in pure \n[…]\nment-heavy arms move (gen3/piper/xarm7 ~-20%);\nnon-refining arms are within measurement noise, confirming the machine is\ncomparable.\n\n* Fix mypy import-not-found for regen_bench in perf-extension test",
          "is_bot": false,
          "headline": "Guard against benchmarking uncompiled Cython extensions + correct the…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-23T04:16:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0564d8b12c8ba581abdddf317ba3000fba96d0c7",
          "body": "The committed bench numbers were a patchwork measured at different points in the\ncodebase's history, so the README no longer reflected reality. Re-benched the\nwhole roster on one quiet machine (per-arm minimum of two runs to drop\ncontention spikes; control arms -- solvers unaffected by recent change\n[…]\n, so neither the Jacobian nor the stagnation change touches it).\n- Everything else within measurement noise of its prior value.\n\nTiming only; EAIK comparison numbers (external, unaffected) left as-is.",
          "is_bot": false,
          "headline": "Refresh stale bench numbers across the prebuilt roster (#403)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-22T20:28:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c66294c531ba8926199777de7ead125e804eb79e",
          "body": "…cobian (#402)\n\n* perf: scalarize the emitted _spatial_jacobian cross product\n\nThe codegen-emitted _spatial_jacobian used np.cross(p_i, z_i) for the linear\nJacobian columns. For 3-vectors np.cross is dominated by moveaxis /\nnormalize_axis_tuple overhead -- ~11x slower than the scalar triple. It runs\n[…]\nue the ungated refiner finds, the guard also\nfinds). SB bench numbers refreshed (thor 8.4->2.6, core 8.4->2.6, spark 7.3->2.5ms).\n\n* Update refinement module docstring for the convergence-abort guards",
          "is_bot": false,
          "headline": "perf: gate wasted LM refinement by convergence + scalarize emitted Ja…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-22T20:18:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "04bddae94a0b4992476c1aee2ed3e6b1163332ff",
          "body": "…trio-flip (#399)\n\n* Fix three_parallel codegen trio-flip; dedup sign convention; guard parity\n\nPR #398 fixed the axis-sign gauge bug in the *live* three_parallel solver but\nnot in the codegen composer, which re-implements the candidate construction as\nemitted source. So the baked artifacts users im\n[…]\nand records a correctness verdict instead. thor/spark\nnow render as EAIK 'refuses (returns FK-incorrect solutions)', which is the\nhonest comparison: ssik solves them at machine precision, EAIK cannot.",
          "is_bot": false,
          "headline": "Onboard Standard Bots (thor/core/spark) + fix three_parallel codegen …",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-22T20:05:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5b8e6dc532173c4191ffefa24454f0deffa79780",
          "body": "…ign + length) (#398)\n\n* Fix three_parallel axis-sign gauge bug on anti-parallel trio joints\n\nthree_parallel collapses the parallel trio (joints 1,2,3) onto the single\ndirection axes[1] and uses the signed total theta14 = q1+q2+q3+q4, solving\neach trio angle *about axes[1]*. When a URDF authors a tr\n[…]\nady guarded by each solver re-asserting its predicate on entry.\n\ntest_manipulator_constructors.py: a scaled-axis arm is FK-identical to the\nunit version and self-round-trips; a degenerate axis raises.",
          "is_bot": false,
          "headline": "Bulletproof solver construction against axis representation gauges (s…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-22T05:14:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "43b1c3ce0690126ccc4082e7976722333b0c2356",
          "body": "…s #8, #9) (#397)\n\n* Add Manipulator.from_dh / from_axes / from_transforms constructors (closes #8, #9)\n\nThree non-URDF constructors matching EAIK's DhRobot / HPRobot / HomogeneousRobot,\nso callers with DH tables, ik-geo H/P parameters, or per-joint zero-pose\ntransforms can build a Manipulator witho\n[…]\nes to\nikgeo.spherical_two_parallel and solve(fk(q)) roundtrips at 4e-15 (the #8\nbenchmark); shape/length validation + limits pass-through covered. Full suite\n1684 passed.\n\n* ruff format manipulator.py",
          "is_bot": false,
          "headline": "Manipulator.from_dh / from_axes / from_transforms constructors (close…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-22T03:45:42Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d70d8ddd4057fbf29fb0857d27d68ceffe8523fc",
          "body": "…389) (#396)\n\nTwo per-call hot-path wins from the audit, both behaviour-preserving:\n\n- E2: rotate() (Rodrigues) built the result via ~5 numpy temporaries -- a\n  _cross3 array plus four element-wise product/sum arrays -- every call. It is\n  one of the hottest calls in the SP5/SP6 refine loops. Scalar\n[…]\natched solver accepts. The solver is fixed at\n  __init__, so cache its parameter set there (frozenset) and do a set lookup\n  per call instead of reflecting.\n\nFull suite 1675 passed; ruff + mypy clean.",
          "is_bot": false,
          "headline": "Efficiency: scalarize rotate() + cache the solver signature (E2/E6, #…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-21T21:34:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "718e47e6e55f7747d05ef4bbe69950e345851307",
          "body": "…s #388) (#395)\n\n* Factor the axis-intersection geometry + make it scale-relative (U5, closes #388, #389)\n\nThe \"lstsq the first two axis lines, verify the rest by perpendicular drift\"\nkernel was copy-pasted three times (three_consecutive_intersecting,\naxes_meet_at_common_point, _max_axis_drift) -- o\n[…]\ned on a ~1 m arm and accepted on a ~100 m\narm; a real 1 cm offset is rejected at any scale. Full suite 1675 passed.\n\n* Mark test_ik_overhead_under_300us @perf (was flaking under -n auto parallel load)",
          "is_bot": false,
          "headline": "Factor axis-intersection geometry + make it scale-relative (U5, close…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-21T20:44:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "63f693cb112e8cfa47639110378473441080428c",
          "body": "…389) (#394)\n\nlm_refine converged and reported on ||se3_log_residual|| while Solution.fk_residual,\nthe exact/algebraic path, lm_refine_batch, and every emitted solve() use the\nFrobenius error ||fk(q) - T||_F. For a rotation-dominated error the two differ by\nup to ~3x, so a candidate accepted at the \n[…]\npins residual == Frobenius and accepted-implies-under-gate.\nFull suite 1672 passed -- the stricter gate costs no coverage (quadratic\nconvergence clears the ~1.4-3x candidates in 1-2 extra iterations).",
          "is_bot": false,
          "headline": "Gate lm_refine on the Frobenius FK residual, not the SE(3) log (D2, #…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-21T19:44:57Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2ee85aca873e7e4c2aec0b6bb2c774dbc7297304",
          "body": "…2b) (#393)\n\n* Factor the shared post-processing pipeline into finalize_solutions (U2b, #389)\n\nThe limits -> seed -> truncate tail was hand-duplicated in four places that had\nalready drifted: Manipulator.solve and three codegen templates (thin-wrapper,\nspecialised-6R, jointlock-7R, the last with two\n[…]\nms the emitted finalize\n  behaves identically to the live path.\n\nFull suite 1665 passed; parity + snapshot green; ruff + mypy clean.\n\n* Fix mypy: guard Optional __file__ in postprocess structural test",
          "is_bot": false,
          "headline": "Factor the shared post-processing pipeline into finalize_solutions (U…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-21T17:21:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8403b7f369782c620740dab6b2e7859ff0bddeb2",
          "body": "* Add artifact<->live solver parity test (U2 part 1, #389)\n\nThe codegen emitters re-express solver behaviour as generated source (the\nspecialised composers inline the SP1/SP3/SP4 algebra; every emitter re-derives\nthe verify/dedup/postprocess tail). That is behavioural duplication across two\nrepresen\n[…]\ninned\n  by the uniform-fuzz suite.\n\n24 passed, 3 skipped.\n\n* Fix mypy: type the parity helpers + explicit live.solve kwargs\n\n* Use per-arm fk_ceiling_fuzz for parity FK bound (LAPACK-backend variance)",
          "is_bot": false,
          "headline": "Artifact↔live solver parity test (U2 part 1) (#392)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-21T13:07:14Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b5597b533b5c4cac7ca63ed426a6edbdfbfd4929",
          "body": "…(U1, #389) (#391)\n\nPer-solver metadata lived in six hand-synced name->X tables — dispatcher\nestimates, codegen import paths, manipulator module paths, codegen composers,\nand the fk-atol/force-refine overrides — two of them byte-identical and fully\nderivable (`f\"ssik.solvers.{name}\"`), none keyset-g\n[…]\nnt; every prebuilt's\nSOLVER_NAME is registered. A half-wired solver now turns CI red instead of\nKeyError-ing in the field.\n\nArtifacts byte-identical (snapshot green, no regen). Full suite 1641 passed.",
          "is_bot": false,
          "headline": "Collapse the ~6 parallel solver registries into one SolverSpec table …",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-20T23:48:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2ff2706406f14cd1003219b1adf55e95c7d68ffd",
          "body": "…s (D1, #389) (#390)\n\nThe thin-wrapper codegen hard-coded `from ...seven_r._swivel_limits import\nresolve_in_limits` for every arm. That's the SRS resolver; on a spherical-shoulder\narm (Franka/FR3/xArm7) it classifies as non-SRS and returns [] — a silent no-op.\nSo the respect_limits empty-fallback re\n[…]\nka/FR3/xArm7 recover in-limits solutions (was 0).\n\nRegenerated franka/fr3/xarm7 artifacts (one import line each). hoisted\n`import_module` to a module-level import (was duplicated in two local scopes).",
          "is_bot": false,
          "headline": "Wire the solver-matched in-limits resolver into thin-wrapper artifact…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-20T21:52:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f2f44c3bc9ded18eff32b338d75a839c33a67d74",
          "body": "A spherical-wrist 6R whose last wrist joint's URDF frame sits a fixed distance\nalong its own rotation axis from the wrist-center intersection -- the flange\noffset, standard on industrial arms (ABB IRB 6700 and others) -- was dispatched\nto the ~100x-slower ikgeo.general_6r. The strict three_consecuti\n[…]\nh reporters' actual URDFs (IRB 6700 + a second\nspherical-wrist 6R): both now dispatch spherical_two_parallel and solve 300/300\nrandom poses at ~5e-15. New tests use a self-contained synthetic fixture.",
          "is_bot": false,
          "headline": "Route + solve spherical-wrist 6R arms with a flange offset (#377) (#387)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-19T23:16:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "dd5d47d21a5228b6b60502980580e9306008e771",
          "body": "…w-up) (#386)\n\nThe perf gates timed sub-millisecond calls with median/mean and tripped on\nshared CI runners where scheduling noise is additive: iiwa14 max_solutions=1\n(0.23 ms compute) had its median of 20 dragged to 1.00 ms under load, failing a\n< 1 ms gate on an unrelated PR's CI.\n\nAdd one shared \n[…]\n \"best-case cost must stay under X\" -- exactly a\nregression gate's intent. Best-of-N spread on the formerly-flaky gate is\n0.40-0.41 ms across 30 trials (vs the 1.00 ms median spike). Full suite green.",
          "is_bot": false,
          "headline": "Make perf gates noise-robust with shared best-of-N timing (#383 follo…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-17T23:53:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "bbfb2cf3849c59a7ac74f65f33bcc2af88cb9aef",
          "body": "…#383)\n\nThe trajectory-tracking idiom `solve(T, q_seed=q, max_solutions=1)` on the\nredundant thin-wrapper 7R arms (spherical-shoulder franka/fr3, polished\nspherical-shoulder xarm7, SRS iiwa14/gen3/openarm/r1pro) resolved the whole\n1-parameter self-motion each call -- several ms -- to then keep one s\n[…]\nn vs\n  L-infinity-ranking gap over the continuous swivel, benign and non-accumulating.\n- Falls through cleanly on far seeds / out-of-limits continuations, verified by\n  spying on the full solver call.",
          "is_bot": false,
          "headline": "Seeded numerical-tracking fast path for thin-wrapper 7R arms (#380) (…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-17T21:17:39Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3ef3c59b5d0f2759dc99ec5ffe337b211cfd0b01",
          "body": "`rescue_via_T_perturbation` used a single `fk_atol=1e-8` both as lm_refine's\nconvergence target and as the acceptability gate. When a rescue lands off-ridge\n(well-conditioned -- the common case) the polish dipped under 1e-8 on the first\nNewton step and stopped there, returning solutions at ~6e-9 eve\n[…]\nrecovery is unchanged.\n\n- gen3 at the falsifying q*: worst FK 5.79e-9 -> 5.24e-13.\n- Deterministic regression test on that pose.\n- #319 rescue suite + full uniform fuzz: green. Full suite 1589 passed.",
          "is_bot": false,
          "headline": "Polish well-conditioned rescues to machine precision (#384) (#385)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-17T20:37:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "80077e6280d9ab7966c704a3362c81a52de8513a",
          "body": "The srs_polished *analytical* path once returned 0 sols at q*=[0.512, 0.512,\n1.020, 0.625, -0.648, -2.75, 0.875] (recovered only by the #358 LM rescue at\n~1e-8, below the strict 1e-9 analytical fuzz bar). The general-Davenport SRS\ngeneralization (#354/#356) -- which srs_polished runs on the best-fit\n[…]\nots --\nclosed it: the pose now returns 13 sols at ~2e-16.\n\nRemove the gen3 known_gaps xfail (the uniform fuzz passes across seeds) and add\nthe q* to the srs_polished hand-picked FK-closure regression.",
          "is_bot": false,
          "headline": "Close #299: gen3 srs_polished analytical coverage gap is fixed (#382)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-17T04:47:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "871abc893b0ac1f2aea7e31ab849d2f670345a97",
          "body": "…s) + #288 (z1 genuine) (#381)\n\n* Drop spurious near-singular branch in three_parallel (#362)\n\nAt a near-singular UR pose (e.g. q0=q5=0), an SP3/SP4 argument clipped to\nthe reachability boundary yields a branch that FK-closes to only ~7e-6 --\na least-squares near-miss with no exact IK nearby (damped\n[…]\n(jointlock) keep their machine-precision-or-drop\ncontract. The 1e-7 gate alone still drops the UR spurious near-miss on the\nlive path. jointlock bulletproof + three_parallel + z1/ur16e fuzz all green.",
          "is_bot": false,
          "headline": "Refine near-singular near-misses in three_parallel: fix #362 (spuriou…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-17T04:12:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d153492fc99395996233b87bb9b2b4325c1ace52",
          "body": "…, closes #159) (#379)\n\nxArm7 is nearly the exact spherical-shoulder class -- the closed-form q_i(q6)\nrecipe gives excellent seeds (~1e-8 residual, which was the #159 precision\nfloor) but the exact 1e-10 gate rejects them. New seven_r.spherical_shoulder_\npolished: closed-form seeds over the reachabl\n[…]\now_build 1184 s, platform-drifting) -> 12.7 KB\nthin-wrapper (fast, deterministic); manifest + docs. 22.8 -> ~7 ms, FK 1.5e-6\n-> ~1e-11 (closes #159), 0/150 in-limits coverage misses. Bulletproof test.",
          "is_bot": false,
          "headline": "Approximately-spherical-shoulder polished solver: onboard xArm7 (#373…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-15T22:27:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1d7193ab395990f2a0dadf530f4b9a99c2786c62",
          "body": "…#378)\n\n* Add bounded-domain feasible-interval core for locked-joint redundancy (#373)\n\nThe periodic feasible_arcs (extracted in #372) handles the SRS swivel on\nthe circle [-pi, pi). The spherical-shoulder specialist's redundancy is a\nlocked joint (q6) on its own limits [a, b] with no wrap-around. A\n[…]\nturned sample -- the\n  old 'within one sweep-step on all joints' bound was jointlock-specific).\nPlus the fr3 docstring. Full suite: 1583 passed, 7 xfailed (pre-existing).\n\n* Wrap long line (ruff E501)",
          "is_bot": false,
          "headline": "Spherical-shoulder 7R specialist + auto-routing (Franka/FR3) (#373) (…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-15T21:32:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "99f0e5c319ac8a3009876ce38d443eba030ed93c",
          "body": "…4) (#375)\n\n* Fix _lock_joint dropping the locked transform when locking the last joint (#374)\n\nWhen lock_idx == last_idx, the propagation loop skips the locked joint\n(the i == lock_idx continue) and never reaches the last-joint absorption\nbranch, so the locked joint's fixed transform T_left @ Rot(a\n[…]\nil known gap referencing #376 (same\nconvention as the existing _SINGULAR_CONFIGS). No production impact: no\narm dispatches HP on a last-joint lock.\n\n* Type-annotate _locked_config_params return (mypy)",
          "is_bot": false,
          "headline": "Fix _lock_joint dropping the locked transform on last-joint lock (#37…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-14T20:56:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2c72735ae95ca32b5b778d9d95c0327b32d41fb6",
          "body": "* Extract parameter-agnostic feasible-interval core (#148 step 1)\n\nThe feasible-swivel resolver (#359/#369) computes exact in-limits arcs for\nthe SRS elbow swivel by treating each joint as a smooth 1-parameter family\nq_i(psi) and finding the sign-zeros of phi_i(psi) = cos(q_i - c_i) - cos(h_i).\nThat\n[…]\non. The shared\ncore stays dependency-free (scipy-free) to preserve iiwa's lean import chain.\nBacked by the existing SRS feasible-swivel tests and the 7R prebuilt fuzz.\n\n* Format _feasible_param (ruff)",
          "is_bot": false,
          "headline": "Extract parameter-agnostic feasible-interval core (#148 step 1) (#372)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-14T16:43:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b0965d3eb5f03db5f0967c581f3e772dd0e21347",
          "body": "…70) (#371)\n\n#369 closed #359 for exactly-concurrent SRS arms. Kinova Gen3 is only\napproximately SRS (~12 mm axis drift), so the exact resolver no-ops on it and\ngen3 still dropped reachable in-limits poses on the default respect_limits=True\npath.\n\nAdd an approximate path to resolve_in_limits (mirror\n[…]\n #299, is separate and stays\nxfailed -- respect_limits=False; the LM rescue closes it only to ~1e-8.)\n\nFull non-slow suite 1567 passed; new gen3 case in tests/test_swivel_limits.py;\nruff + mypy clean.",
          "is_bot": false,
          "headline": "Extend feasible-swivel limit resolution to approximate-SRS / gen3 (#3…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-13T17:57:27Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "895c0e4123a73e7c3f5c80bdb9123eb39a13d263",
          "body": "…(#369)\n\nThe elbow swivel is the SRS redundancy; the solver sampled it blindly (16\nuniform samples) and then filtered by joint limits, so a reachable in-limits\npose whose in-limits swivel arc was narrower than the sampling returned [].\nDenser sampling doesn't fix it (the arc can be arbitrarily narro\n[…]\nstays gated: the exact resolver needs\nexact concurrency; extending it to relaxed-pivot + LM polish is a follow-up.\n\nFull non-slow suite 1566 passed; new tests/test_swivel_limits.py; ruff + mypy clean.",
          "is_bot": false,
          "headline": "Exact feasible-swivel joint-limit resolution for SRS-class 7R (#359) …",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-12T05:34:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "78eff3c491f1c9184535b3facae0297cd7410060",
          "body": "…ath fuzz (#365)\n\n* Release: refuse to publish if built version != tag (#364)\n\nTwo v* tags on one commit (v3.0.0rc1 + v3.0.0) let hatch-vcs resolve the rc,\nso the v3.0.0 run built + published ssik-3.0.0rc1 to real PyPI. Add a guard\nstep to both publish jobs: assert every dist artifact carries the ta\n[…]\nty guarantee; the 5 SRS-family tight-limit arms (gen3, openarm L/R,\nr1pro L/R) are xfailed for #359. Immediately caught gen3 as a gap arm the\nby-hand probing missed (52 sols returned, none in-limits).",
          "is_bot": false,
          "headline": "Harden gaps revealed by the v3.0.0 release: version guard + default-p…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-08T22:53:26Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "1793c4e10808dfe7aeb2805c465f869c13e9a337",
          "body": "…(#363)\n\nThe R1 Pro's y-x-z shoulder / z-y-x wrist (non-Z*Z, tilted/offset elbow) was\nthe motivating arm for the SRS generalization (#356); it now solves natively at\nmachine precision. Vendor both 7-DOF arms as tier-0 seven_r.srs prebuilts:\n\n- Fixtures + test scaffolds via `ssik add-arm` (mesh-strip\n[…]\n_r.srs; worst FK 3e-15 over the bench\nsweep, 0 empty / 300 random poses; 14 per-arm tests + uniform fuzz (500\nexamples each) + snapshot byte-compare + manifest consistency all pass.\nruff + mypy clean.",
          "is_bot": false,
          "headline": "Onboard Galaxea R1 Pro (left + right 7-DOF arms) as prebuilts (#357) …",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-07T17:10:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "eb3becf8177c76469ca59fb1e1681e08bf799a89",
          "body": "…358) (#361)\n\nThe #319 bulletproof rescue -- auto-recovers a reachable-but-degenerate pose\nthe analytical path returns [] for -- was wired into the specialised\norchestrators (RR / jointlock / tier-0 ikgeo) but NOT the thin-wrapper\ntemplate, so the SRS family had no safety net: iiwa14, OpenArm L/R\n(s\n[…]\nn-gap kept + reason updated: the\nstrict 1e-9 *analytical* ceiling still gates (LM rescue closes to ~1e-8; the\nsrs_polished gap itself remains #299). Full non-slow suite 1545 passed;\nruff + mypy clean.",
          "is_bot": false,
          "headline": "Wire the T-perturbation rescue into thin-wrapper (SRS-family) arms (#…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-06T01:07:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b0e26ae68083131124562d50dfebd4934222e15b",
          "body": "* Generalize native SRS solver to any concurrent-axis 7R (#354)\n\nThe native seven_r.srs solver was ZYZ-only: its shoulder/wrist angle\nextraction hardcoded z-y-z Euler triples, so the is_srs_7r predicate\ngated on a Z*Z (parallel first/third axis) structure (#307). Concurrent-\naxis arms whose triples \n[…]\nm_constants already computed; check the (unit)\naxes directly instead of normalizing all seven. Canonical iiwa path is back\nto ~0.41 ms median (macOS); correctness unchanged (iiwa 1e-14, R1 Pro 5e-16).",
          "is_bot": false,
          "headline": "Generalize native SRS solver to any concurrent-axis 7R (#354) (#356)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-07-05T23:24:07Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5d4181e9809ab43a9dee55212d6de0d3b931f420",
          "body": "…r generalized SRS (#354) (#355)\n\n* Add generalized 3-axis (Davenport) rotation decomposition (#354 foundation)\n\ndecompose_3axis(R, n1, n2, n3) solves R = Rot(n1,a) Rot(n2,b) Rot(n3,c) for\narbitrary unit axes (Shuster-Markley 2003) -- the building block for generalizing\nseven_r.srs past its ZYZ-only\n[…]\n-wide (my local check was source-only). Accept ArrayLike for\nthe axis args (the function np.asarrays internally) so list literals type-check,\nand replace *-unpacks in the tests with explicit indexing.",
          "is_bot": false,
          "headline": "Generalized 3-axis (Davenport) rotation decomposition — foundation fo…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-30T12:59:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cd849ffe44a05003e95b39441e5ed21a9c432c5c",
          "body": "…-driven) (#353)\n\n* Automate the EAIK comparison: manifest-driven, folded into regen_bench (#350)\n\nThe README EAIK table was hand-maintained in three places (a _PIEPER_EAIK dict\n+ hardcoded refusal strings in regen_docs, plus a duplicate FIXTURES list in\nexamples/04) and drifted from EAIK's real beh\n[…]\n count makes --check exit non-zero).\n\nRemaining hand-written: outreach/*.md (no live counts) and examples/04's FIXTURES\nlist (a standalone demo; the doc source of truth is now scripts/regen_bench.py).",
          "is_bot": false,
          "headline": "Automate the EAIK comparison + remaining doc counts/rosters (manifest…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-29T17:43:51Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fdb7b356cfb3049f425a03c56296f4c2726d4286",
          "body": "…48) (#349)\n\n* Speed up CI: cache robot_descriptions + parallelize pytest (closes #348)\n\nCI had crept to 43-68 min with high run-to-run variance. Measured: pytest is\n~100% of wall-clock and the dominant cost is uncached robot_descriptions clones\n(~16 repos, several with mesh files) -- the local suit\n[…]\nnvestigation captured in #350). Add a fast, deterministic regression test that\na sub-chain primed on one BLAS backend is still found under ~1e-12 DH jitter.\n\n* Format conftest after xarm7 hook removal",
          "is_bot": false,
          "headline": "Speed up CI: cache robot_descriptions + parallelize pytest (closes #3…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-29T14:41:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "37955798c55a1422697664a54167c8f72c49da8a",
          "body": "The cached-RR caches (_PRIMED_LINEARITY_MAP, _DERIVATION_CACHE) were keyed on\nexact DH float tuples. poe_to_dh produces values differing in the last ~1e-12\nbits across BLAS backends (OpenBLAS vs Accelerate), so the macOS-baked key never\nmatched the Linux-runtime key for 55/176 lock-sample sub-chains\n[…]\ndy matched).\n\nVerified on the Linux/OpenBLAS runner: 176/176 primed, 0 misses, 38 ms/solve.\nRegression test: a sub-chain primed on one BLAS backend stays found under\n~1e-12 DH jitter (fast, no sympy).",
          "is_bot": false,
          "headline": "Quantize cached-RR cache keys to fix ~140x Linux slowdown (#350) (#352)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-29T13:31:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "126090f38a9d7096451e83b3dc90454ee04f7eb8",
          "body": "…es #346) (#347)\n\n* Ship the current Universal Robots lineup: UR3e/5e/10e/16e/20/30 (closes #346)\n\nSix new prebuilt arms covering the entire current UR product line, all added\nvia the one-click flow that #327 (xacro) + #341 (add-arm/regen_bench) enabled:\n`ssik add-arm ur.urdf.xacro --xacro-arg ur_ty\n[…]\nfixture_source and load_robot_description(desc)'d it,\nfailing with ModuleNotFoundError. Point each at its per-arm module; yourdfpy\nprocesses the xacro with the right ur_type and FK matches to 3.5e-16.",
          "is_bot": false,
          "headline": "Ship the current Universal Robots lineup: UR3e/5e/10e/16e/20/30 (clos…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-24T14:06:24Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "52ec000f74db9d2abeb9187aa712a00a637d9bff",
          "body": "…327) (#345)\n\nThe Universal Robots family and many ROS descriptions ship as xacro (macros,\n<xacro:include>, substitution args), not flat URDF -- previously you had to\npre-expand by hand. Now every entry point accepts xacro directly:\nManipulator.from_urdf, `ssik build`, `ssik classify`, `ssik add-arm\n[…]\nnd overridden subargs, FK-correct load at both, and the add-arm\nvendoring path (expand -> strip -> plain FK-equivalent URDF).\n\nDocs: setting_up_your_robot.md gains a Xacro/MJCF format-support section.",
          "is_bot": false,
          "headline": "Xacro / modular-URDF support across all loader entry points (closes #…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-24T01:06:01Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "42362fb61e7e5e6b0f13d8925acb099abfd82e88",
          "body": "…#344)\n\nFirst format beyond URDF (#83): MuJoCo-native arms and Menagerie MJCF-only\nentries. Rather than hand-parse MJCF (rich format -- <default> classes,\n<compiler> angle/coordinate settings, <include>, keyframes), load via\nmujoco.MjModel.from_xml_path (which compiles all of that) and read the\nPOE-\n[…]\nommitted toy 3R fixture\n(varied axes + a non-trivial body quat + a limited joint), limit reading,\nmissing-body + ball-joint errors.\n\nFollow-ups: wiring MJCF into `ssik add-arm`; USD/SDF loaders (#83).",
          "is_bot": false,
          "headline": "MJCF loader: load_mjcf_kinbody_normalized via mujoco MjModel (#343) (…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-23T05:45:53Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a649db1f05fafcc8d59fe75e077f87bafa301beb",
          "body": "…) (#342)\n\nAdding a prebuilt arm was multi-step with manual benchmarking (this session's\nxArm7 flip needed hand-measured ms/FK/sols + a hand-edited [bench] block). This\nmakes it tooled and mostly one-click.\n\nscripts/regen_bench.py (new): measures each prebuilt's solve() (time / max FK /\nbranch count\n[…]\nFK + raises on broken joints;\nregen_bench's manifest rewrite is surgical; add-arm vendors a stripped,\nFK-identical URDF.\n\nBeyond-URDF ingestion (MJCF/USD/SDF) stays scoped to #83 -- a separate loader.",
          "is_bot": false,
          "headline": "Low-friction arm onboarding: one-click bench + complete add-arm (#341…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-22T18:10:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a03c813653a63b14f3fad5f7ec216ba3ab067b0f",
          "body": "…ify (#337) (#340)\n\nAt near-singular poses the SP5 quartic can develop a near-double root (gap\n~9e-10) whose sign-branch backsolve yields a spurious candidate: a non-zero\nleast-squares point (LM stalls at ~2.6e-6 with a well-conditioned cond(J)~960,\nso it is NOT a true solution), 3 rad from any genu\n[…]\ners below the gate).\n\nRegression: deterministic test that the repro pose yields only\nmachine-precision branches. No regression across sp5 / spherical /\ntwo_intersecting / puma cross-validation suites.",
          "is_bot": false,
          "headline": "sp5: reject spurious near-double-root candidates via tighter post-ver…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-20T17:54:02Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "3d62ebec1675784f80c879b159f1189a096d695c",
          "body": "…l (#312) (#339)\n\n* xarm7: build from manufacturer URDF (slow_build); add strip-urdf tool (#312)\n\n#312 was diagnosed as a codegen \"hang\"; it's actually a legitimately slow\nRR-bake, not an infinite loop. The xArm7 *URDF* geometry classifies its\njointlock lock-sweep inners as `reversed:two_intersectin\n[…]\npy-clean the two_intersecting SP5-overflow guard (#312)\n\nPatch the sp5 module directly (not two_intersecting.sp5, which mypy flags as\nnot an explicit export) and type the monkeypatch wrapper with Any.",
          "is_bot": false,
          "headline": "xarm7: build from manufacturer URDF (slow_build) + add strip-urdf too…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-19T14:57:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "93b884d5b10ca5a5777a172233d7f3dbe264b52c",
          "body": "…#338)\n\nfrom_urdf(...).solve(T) could return [] (or far fewer branches) for poses the\nbaked `ssik build` artifact solves, because the cached-RR fast path is only\nprimed at build time; the cold URDF path uses the universal Husty-Pfurner inner\nsolver, which has coverage gaps. A silent \"try before you \n[…]\nad of silent.\n\nRegression tests: from_urdf recovers the rizon4 ridge via rescue (all FK-close,\nrescue never reduces the analytical count); the cold-coverage warning fires\nexactly once per Manipulator.",
          "is_bot": false,
          "headline": "Manipulator: rescue + cold-coverage warning for from_urdf 7R (#328) (…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-18T01:46:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "5fee9373afc94297404cc9129745565004ac68c2",
          "body": "…#324) (#336)\n\nHypothesis found an SP5 input where solve() returned a triple that fails the\ndefining equation by ~0.5. Root cause is NOT degeneracy (the issue's\nnear-parallel k2 is incidental; the degeneracy guard correctly doesn't fire):\nthe input is genuinely infeasible -- |p0 + Rot(k1,t1)p1| = |p\n[…]\nnger protects any completeness: verified no regression across SP5 unit\ntests, Puma 500-pose cross-validation, and the full prebuilt fuzz.\n\nAdds a deterministic regression test for the infeasible case.",
          "is_bot": false,
          "headline": "sp5: return [] on infeasibility instead of a non-satisfying best-LS (…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-17T13:05:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "60c38cfc74af47566e3dc27454dc3033756dde16",
          "body": "* tests: replace stale HP-not-implemented xfails on oracle 2/5 (#325)\n\nThe HP solver landed (#184/#185) but two oracle tests still carried the\nstale `xfail(strict=True, raises=NotImplementedError, reason=\"#162\")` mark,\nso they XPASS-failed once HP worked (oracle2 locally where EAIK is present;\noracl\n[…]\nss-platform, so loosen the joint\nmatch to a branch-level 1e-2 (distinct UR5 branches differ by >>1e-2) and\nkeep exact count parity. Catches missing/spurious/wrong branches without\nflaking on numerics.",
          "is_bot": false,
          "headline": "tests: fix stale HP-not-implemented xfails on oracle 2/5 (#325) (#335)",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-16T16:00:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a24cf1ec43f6d281a7b31a158417a54ed1d7d2c0",
          "body": "…lter) (#333) (#334)\n\nAdds a hard tracking guarantee on top of q_seed: solve(T, q_seed=q,\nseed_tolerance=tau) returns only solutions whose every joint is within tau\n(per-joint wrap-to-pi L-infinity) of the seed, possibly empty. The empty\nresult is the useful signal that smooth continuation isn't pos\n[…]\ngenerated all 19 prebuilt artifacts (orchestrator template change).\nDocs: quickstart + README trajectory-tracking sections now cover seed_metric\nand seed_tolerance; api.md lists within_seed_tolerance.",
          "is_bot": false,
          "headline": "seed_tolerance: bound max joint deviation from q_seed (postprocess fi…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-15T16:06:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0a713a109eb94356c3a0c3ac1c921f8a4118bc08",
          "body": "…ath (#330, #331) (#332)\n\nStrengthen the q_seed contract so solve(T, q_seed=q, max_solutions=k)\nreturns the k solutions *genuinely* nearest the seed, branch-continuously\nand cheaply -- the trajectory-tracking idiom.\n\n#330 -- seed_metric kwarg on solve()/Manipulator.solve, threaded to the\nnearest-to-\n[…]\nt_seeded_nearest_tracking.py\ncovering metric plumbing, the divergent wrap_l2-vs-wrap_linf pick, the\nseeded-matches-exhaustive guarantee, the full-branch-set return, and the\nfewer-dispatches speed win.",
          "is_bot": false,
          "headline": "Seeded nearest-to-seed tracking: seed_metric + 7R lock-outward fast p…",
          "author_name": "Siddhartha Srinivasa",
          "author_login": "siddhss5",
          "committed_at": "2026-06-12T21:48:25Z",
          "body_truncated": true,
          "is_coding_agent": false
        }
      ],
      "releases_count": 20,
      "commits_last_year": 283,
      "latest_release_at": "2026-08-01T13:42:44Z",
      "latest_release_tag": "v4.1.0",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 14,
      "days_since_latest_release": 0,
      "mean_days_between_releases": 5.6
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 50,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "ssik",
          "exists": true,
          "license": "BSD-3-Clause",
          "keywords": [
            "ik-geo",
            "inverse-kinematics",
            "kinematics",
            "robotics",
            "Development Status :: 4 - Beta",
            "Intended Audience :: Science/Research",
            "Programming Language :: Python :: 3",
            "Programming Language :: Python :: 3.10",
            "Programming Language :: Python :: 3.11",
            "Programming Language :: Python :: 3.12",
            "Programming Language :: Python :: 3.13",
            "Topic :: Scientific/Engineering"
          ],
          "ecosystem": "pypi",
          "matches_repo": true,
          "registry_url": "https://pypi.org/project/ssik/",
          "is_deprecated": false,
          "latest_version": "4.1.0",
          "repository_url": "https://github.com/personalrobotics/ssik",
          "versions_count": 22,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 5251,
          "first_published_at": "2026-05-13T23:46:27.725165Z",
          "latest_published_at": "2026-08-01T13:42:29.497697Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 0
        }
      ]
    },
    "popularity": {
      "forks": 16,
      "stars": 176,
      "watchers": 3,
      "fork_history": {
        "days": [
          {
            "date": "2026-06-02",
            "count": 5
          },
          {
            "date": "2026-06-03",
            "count": 1
          },
          {
            "date": "2026-06-04",
            "count": 1
          },
          {
            "date": "2026-07-09",
            "count": 1
          },
          {
            "date": "2026-07-16",
            "count": 1
          },
          {
            "date": "2026-07-21",
            "count": 7
          }
        ],
        "complete": true,
        "collected": 16,
        "total_forks": 16
      },
      "star_history": null,
      "open_issues_and_prs": 13
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "src/ssik/py.typed"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 1081439,
      "source_files_sampled": 380,
      "oversized_source_files": 21,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "pyproject.toml"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "pypi"
      ],
      "dependencies": [
        {
          "name": "numpy",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.26"
        },
        {
          "name": "tomli",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.1.0"
        },
        {
          "name": "scipy",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.13"
        },
        {
          "name": "sympy",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=1.10"
        },
        {
          "name": "cython",
          "manifest": "pyproject.toml",
          "ecosystem": "pypi",
          "version_constraint": ">=3.1"
        }
      ],
      "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": 0,
        "merged_prs": 254,
        "open_issues": 13,
        "closed_ratio": 0.938,
        "closed_issues": 196,
        "closed_unmerged_prs": 16
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "siddhss5",
          "commits": 279,
          "avatar_url": "https://avatars.githubusercontent.com/u/7348473?v=4"
        },
        {
          "type": "User",
          "login": "griffin-norris",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/164929321?v=4"
        }
      ],
      "contributors_sampled": 2,
      "top_contributor_share": 0.986
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "docs.yml",
        "release.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "uv.lock"
      ],
      "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": 9,
            "reason": "29 out of 30 merged PRs checked by a CI test -- score normalized to 9",
            "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": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 10,
            "reason": "license file detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 29 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "29 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "889c6f239f9793e11abd9a7e1286cf1b92b2c374",
        "ran_at": "2026-08-01T13:44:21Z",
        "aggregate_score": 4.4,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-08-01T13:42:47Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-31T20:31:16Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": [
        {
          "number": 83,
          "created_at": "2026-04-27T04:11:39Z",
          "last_comment_at": "2026-07-25T21:52:26Z",
          "last_comment_author": "siddhss5"
        },
        {
          "number": 225,
          "created_at": "2026-05-09T22:31:28Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 292,
          "created_at": "2026-05-20T21:16:31Z",
          "last_comment_at": "2026-07-25T21:52:27Z",
          "last_comment_author": "siddhss5"
        },
        {
          "number": 329,
          "created_at": "2026-06-11T20:00:10Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 350,
          "created_at": "2026-06-26T00:29:55Z",
          "last_comment_at": "2026-07-25T21:52:28Z",
          "last_comment_author": "siddhss5"
        },
        {
          "number": 423,
          "created_at": "2026-07-27T13:35:51Z",
          "last_comment_at": "2026-07-28T21:49:43Z",
          "last_comment_author": "siddhss5"
        },
        {
          "number": 425,
          "created_at": "2026-07-27T19:02:01Z",
          "last_comment_at": "2026-07-28T20:20:50Z",
          "last_comment_author": "siddhss5"
        },
        {
          "number": 459,
          "created_at": "2026-07-29T04:53:54Z",
          "last_comment_at": "2026-07-30T04:15:57Z",
          "last_comment_author": "siddhss5"
        },
        {
          "number": 460,
          "created_at": "2026-07-29T04:53:56Z",
          "last_comment_at": "2026-07-30T23:44:27Z",
          "last_comment_author": "siddhss5"
        },
        {
          "number": 466,
          "created_at": "2026-07-30T13:21:34Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 467,
          "created_at": "2026-07-30T18:06:54Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 474,
          "created_at": "2026-07-31T04:53:42Z",
          "last_comment_at": null,
          "last_comment_author": null
        },
        {
          "number": 479,
          "created_at": "2026-07-31T17:56:59Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/personalrobotics/ssik",
    "host": "github.com",
    "name": "ssik",
    "owner": "personalrobotics"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "good",
      "name": "Overall health",
      "note": "The weighted overall 63 is calibrated to 71 on the published index scale (record calibration 2026-08-02).",
      "notes": [
        {
          "code": "overall_calibration",
          "params": {
            "raw": 63,
            "calibrated": 71,
            "calibration": "2026-08-02"
          }
        }
      ],
      "value": 71,
      "inputs": {
        "security": 44,
        "vitality": 84,
        "community": 59,
        "governance": 61,
        "calibration": "2026-08-02",
        "engineering": 66,
        "ai_readiness": 50,
        "weighted_overall_raw": 63
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 84,
        "weight": 0.21,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 74,
            "inputs": {
              "commits_last_year": 283,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 14
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "14/52 weeks with commits",
                "points": 9.7,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 14
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "283 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 283
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 29 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "exceptional",
            "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": 20,
              "latest_release_tag": "v4.1.0",
              "releases_from_tags": false,
              "days_since_latest_release": 0,
              "mean_days_between_releases": 5.6
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "20 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 20
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~5.6 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 5.6
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "exceptional",
            "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": 59,
        "weight": 0.17,
        "metrics": [
          {
            "key": "popularity",
            "band": "weak",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 48,
            "inputs": {
              "forks": 16,
              "stars": 176,
              "watchers": 3,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "176 stars",
                "points": 36.4,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 176
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "16 forks",
                "points": 9.8,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 16
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "3 watchers",
                "points": 1.7,
                "status": "partial",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "good",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "readme_badges": null,
              "has_contributing": true,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "readme_badge_services": [],
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (BSD-3-Clause)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "BSD-3-Clause"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          },
          {
            "key": "ecosystem_adoption",
            "band": "moderate",
            "name": "Ecosystem adoption (downloads)",
            "note": "Excluded from scoring (no data or not applicable): Registry dependents. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "registry_dependents"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 62,
            "inputs": {
              "packages": [
                "ssik"
              ],
              "dependents": null,
              "ecosystems": "pypi",
              "total_downloads": null,
              "monthly_downloads": 5251
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "5,251 downloads/month across pypi",
                "points": 49.6,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 5251,
                      "ecosystems": "pypi"
                    }
                  }
                ],
                "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": 61,
        "weight": 0.23,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 15,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 2,
              "top_contributor_share": 0.986
            },
            "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 99% of commits",
                "points": 0.3,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 99
                    }
                  }
                ],
                "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 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "good",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Newcomer PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "newcomer_pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 78,
            "inputs": {
              "merged_prs": 254,
              "open_issues": 13,
              "closed_issues": 196,
              "prs_merged_7d": null,
              "prs_decided_7d": null,
              "prs_merged_30d": null,
              "prs_decided_30d": null,
              "issue_closed_ratio": 0.938,
              "closed_unmerged_prs": 16,
              "first_time_authors_30d": null,
              "first_time_prs_merged_30d": null,
              "first_time_prs_decided_30d": null
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "94% of issues closed",
                "points": 39.4,
                "status": "partial",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 94
                    }
                  }
                ],
                "max_points": 42
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "254/270 decided PRs merged",
                "points": 28.2,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 254,
                      "decided": 270
                    }
                  }
                ],
                "max_points": 30
              },
              {
                "key": "newcomer_pr_acceptance",
                "name": "Newcomer PR acceptance",
                "detail": "no first-time contributor's PR decided in 30d",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_newcomer_prs",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 13
              },
              {
                "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": "good",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 69,
            "inputs": {
              "followers": 97,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "personalrobotics",
              "public_repos": 242,
              "account_age_days": 4794
            },
            "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": "97 followers of personalrobotics",
                "points": 14.3,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 97,
                      "login": "personalrobotics"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "242 public repos, account ~13 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 242
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 13
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "exceptional",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "ssik"
              ],
              "ecosystems": "pypi",
              "any_deprecated": false,
              "min_days_since_publish": 0
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on pypi",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "pypi"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 0 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "22 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 22
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 66,
        "weight": 0.19,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 66,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "3 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "29 out of 30 merged PRs checked by a CI test -- score normalized to 9",
                "points": 18,
                "status": "partial",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 65,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": null,
              "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": null,
                "points": 0,
                "status": "missed",
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "weak",
        "name": "Security",
        "value": 44,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "weak",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 44,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 4.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": "29 out of 30 merged PRs checked by a CI test -- score normalized to 9",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 29 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "29 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "exceptional",
            "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"
              ],
              "commit_weight_rule": {
                "min_commits": 50,
                "min_commit_share": 0.1
              },
              "review_only_matches": 0,
              "below_threshold_exposures": [],
              "assessed_self_published_locations": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 50,
        "weight": 0.04,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "weak",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 51,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "uv.lock"
              ],
              "has_dockerfile": false,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "src/ssik/py.typed"
              ],
              "agent_commit_share": 0.04,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "src/ssik/py.typed",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "src/ssik/py.typed"
                    }
                  }
                ],
                "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": "4 of the last 100 commits agent-authored or agent-credited",
                "points": 8,
                "status": "partial",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 4,
                      "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": "good",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 79,
            "inputs": {
              "primary_language": "Python",
              "largest_source_bytes": 1081439,
              "source_files_sampled": 380,
              "oversized_source_files": 21
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Python with type-check config (src/ssik/py.typed)",
                "points": 27,
                "status": "partial",
                "details": [
                  {
                    "code": "typecheck_config_language",
                    "params": {
                      "files": "src/ssik/py.typed",
                      "language": "Python"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "21/380 source files over 60KB",
                "points": 52,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 380,
                      "oversized": 21
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "weak",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "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": 0,
                "status": "missed",
                "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? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
      }
    ],
    "classification": {
      "labels": [
        "library"
      ],
      "scores": {
        "library": 6
      },
      "primary": "library",
      "evidence": [
        {
          "tier": "distribution",
          "label": "library",
          "source": "registry:pypi",
          "weight": 6
        }
      ],
      "artifacts": [],
      "confidence": "medium",
      "host_extension": false,
      "runs_as_process": false,
      "consumed_by_code": true
    },
    "metrics_version": "2.3.1"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
    "deps.dev does not index pypi:ssik@4.1.0; advisories assessed against the repository dependency graph instead"
  ],
  "report_type": "repository",
  "generated_at": "2026-08-01T13:44:38.520217Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/p/personalrobotics/ssik.svg",
  "full_name": "personalrobotics/ssik",
  "license_state": "standard",
  "license_spdx": "BSD-3-Clause"
}

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 v2.3.1, schema v0.27.0 — full methodology · metrics wiki.

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