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

JarvusInnovations / gws-axi

Google Workspace CLI for agents — designed with AXI (Agent eXperience Interface).

TypeScriptMIT★ 8 星标⑂ 1 复刻始于 2026年4月在 GitHub 上查看 ↗

JarvusInnovations/gws-axi 的健康指数为 100 分中的 62 分,处于「中等」区间。 其得分最高的类别是Vitality(82/100),最低的是Community & Adoption(37/100)。 最近一次更新在 6 天前。 近期的大部分工作由 1 位贡献者完成。

62
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

12 关注者225 个公开仓库始于 2011年2月

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布标签
npmgws-axi0.17.02,188286 天前googlegoogle-workspacegmailcalendardocsdriveslidescliagentaxitoon

按类别列示的指标

活力

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

82良好 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 6 天前
6.2/36提交节奏 — 52 周中有 9 周有提交
18/18提交量 — 最近一年 181 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year181
human_commit_share1
days_since_last_push6
active_weeks_last_year9

发布纪律

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

社区与采用

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

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

社区健康

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

可持续性与治理

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

63中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 5 contributing companies or organizations
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
46.8/46.8议题解决 — 100% 的议题已关闭
38.2/38.3PR 接受 — 已裁定的 PR 中 42/42 已合并
0/15OpenSSF Scorecard:Code-Review — Found 0/8 approved changesets -- score normalized to 0
所用输入
merged_prs42
open_issues0
closed_issues3
issue_closed_ratio1
closed_unmerged_prs0
评分方式
30/30所有权背书 — 组织持有
0/20已验证域名
8/25所有者影响力 — JarvusInnovations 有 12 位关注者
25/25既往记录 — 225 个公开仓库,账户约 15 年
所用输入
followers12
owner_typeOrganization
is_verified
owner_loginJarvusInnovations
public_repos225
account_age_days5,646
评分方式
25/25已发布且可解析 — npm 上有 1 个软件包
35/35发布时效 — 最近一次发布于 6 天前
20/20版本历史 — 28 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packagesgws-axi
ecosystemsnpm
any_deprecated
min_days_since_publish6

工程质量

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

67中等 · 占总体的 20%

工程实践

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

文档

65中等
评分方式
30/30README
25/25文档目录
0/15文档 / 主页站点
10/10仓库描述
0/10主题标签
0/10Wiki
所用输入
topics
has_wiki
homepage
has_readme
has_docs_dir
has_description

安全

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

54中等 · 占总体的 16%

安全态势

46存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
2.2/7.5Branch-Protection — branch protection is not maximal on development and all release branches
2.5/2.5CI-Tests — 8 out of 8 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/8 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 5 contributing companies or organizations
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
2.5/2.5许可证 — license file detected
7.5/7.5Maintained — 30 commit(s) and 3 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 — 无数据
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
5.2/7.5Vulnerabilities — 3 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated17
scorecard_versionv5.5.0
checks_inconclusive1
scorecard_aggregate4.6
已排除计分(无数据或不适用):signed_releases。 其余权重已重新归一化。
评分方式
35/35直接依赖不含已知公告 — 没有直接依赖携带已知公告
10/25间接依赖不含已知公告 — 1 个受影响:brace-expansion 2.1.2 (high 7.5)
40/40没有长期未处理的公告 — 没有公告公开超过 90 天
所用输入
sourceosv
advisories1
affected_packages1
assessed_packages93
unassessed_packages0
affected_by_severityhigh 1
direct_affected_packages0
比对的是 npm:gws-axi@0.17.0 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 93 个软件包。 未对可达性进行分析。

AI 就绪度

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

68中等 · 占总体的 0%
评分方式
45/45代理指令 — .claude/CLAUDE.md
0/15机器可读文档(llms.txt)
40/40可读的提交历史 — 100 次人类提交中有 100 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share1
agent_instruction_files.claude/CLAUDE.md
agent_instruction_max_bytes13,597
评分方式
0/18一条命令的引导启动
22/22自动化测试
0/11Lint / 格式化配置
11/11静态类型检查 — tsconfig.json
0/10可复现环境
10/10已体现的代理实践 — 最近 100 次提交中有 82 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
所用输入
has_nix
has_tests
lockfiles
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configstsconfig.json
agent_commit_share0.82
toolchain_manifests
dependency_bot_commit_share0
评分方式
45/45可类型检查的代码 — TypeScript(静态类型)
55/55可控的文件大小 — 采样的 97 个源文件中有 0 个超过 60KB
所用输入
primary_languageTypeScript
largest_source_bytes53,959
source_files_sampled97
oversized_source_files0

关键数据

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

数据采集警告

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

更多细节

OpenSSF Scorecard 4.6 / 10
4.6综合

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

10Binary-Artifactsno binaries found in the repo
3Branch-Protectionbranch protection is not maximal on development and all release branches
10CI-Tests8 out of 8 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/8 approved changesets -- score normalized to 0
10Contributorsproject has 5 contributing companies or organizations
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 3 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
不适用Signed-Releasesno releases found
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
7Vulnerabilities3 existing vulnerabilities detected
直接依赖 7
注册表软件包版本约束清单文件
npm@toon-format/toon^2.1.0package.json
npmaddressparser^1.0.1package.json
npmaxi-sdk-js^0.1.4package.json
npmdiff^9.0.0package.json
npmgoogle-auth-library^10.7.0package.json
npmgoogleapis^173.0.0package.json
npmturndown^7.2.4package.json
全部依赖 未采集

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

依赖安全公告 1

安装 npm:gws-axi@0.17.0 会引入 93 个包(直接与传递):其中 1 个存在已知公告,0 个为直接依赖。

软件包版本关系严重程度公告数修复版本
brace-expansion2.1.2间接15.0.8

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 637,
      "has_wiki": false,
      "homepage": null,
      "languages": {
        "Shell": 138,
        "JavaScript": 54026,
        "TypeScript": 628563
      },
      "pushed_at": "2026-07-20T22:08:31Z",
      "created_at": "2026-04-19T15:46:25Z",
      "owner_type": "Organization",
      "updated_at": "2026-07-20T22:07:09Z",
      "description": "Google Workspace CLI for agents — designed with AXI (Agent eXperience Interface).",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "develop",
      "license_spdx_raw": "MIT",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript"
      ]
    },
    "owner": {
      "blog": "http://jarv.us",
      "name": "Jarvus Innovations",
      "type": "Organization",
      "login": "JarvusInnovations",
      "company": null,
      "location": "Philadelphia, PA",
      "followers": 12,
      "avatar_url": "https://avatars.githubusercontent.com/u/609450?v=4",
      "created_at": "2011-02-09T19:43:15Z",
      "is_verified": null,
      "public_repos": 225,
      "account_age_days": 5646
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.17.0",
          "kind": "minor",
          "published_at": "2026-07-20T22:08:31Z"
        },
        {
          "tag": "v0.16.2",
          "kind": "patch",
          "published_at": "2026-07-02T18:40:08Z"
        },
        {
          "tag": "v0.16.1",
          "kind": "patch",
          "published_at": "2026-07-02T12:52:34Z"
        },
        {
          "tag": "v0.16.0",
          "kind": "minor",
          "published_at": "2026-07-02T04:56:26Z"
        },
        {
          "tag": "v0.15.0",
          "kind": "minor",
          "published_at": "2026-07-02T00:36:23Z"
        },
        {
          "tag": "v0.14.1",
          "kind": "patch",
          "published_at": "2026-06-24T17:30:36Z"
        },
        {
          "tag": "v0.14.0",
          "kind": "minor",
          "published_at": "2026-06-24T16:09:03Z"
        },
        {
          "tag": "v0.13.0",
          "kind": "minor",
          "published_at": "2026-06-23T19:38:13Z"
        },
        {
          "tag": "v0.12.0",
          "kind": "minor",
          "published_at": "2026-06-23T13:35:11Z"
        },
        {
          "tag": "v0.11.0",
          "kind": "minor",
          "published_at": "2026-06-23T13:07:02Z"
        },
        {
          "tag": "v0.10.2",
          "kind": "patch",
          "published_at": "2026-06-11T17:34:50Z"
        },
        {
          "tag": "v0.10.1",
          "kind": "patch",
          "published_at": "2026-06-11T16:37:42Z"
        },
        {
          "tag": "v0.10.0",
          "kind": "minor",
          "published_at": "2026-06-11T15:57:14Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2026-06-10T23:43:27Z"
        },
        {
          "tag": "v0.8.4",
          "kind": "patch",
          "published_at": "2026-06-09T02:29:41Z"
        },
        {
          "tag": "v0.8.3",
          "kind": "patch",
          "published_at": "2026-06-08T13:17:32Z"
        },
        {
          "tag": "v0.8.2",
          "kind": "patch",
          "published_at": "2026-05-22T16:30:29Z"
        },
        {
          "tag": "v0.8.1",
          "kind": "patch",
          "published_at": "2026-05-22T16:25:19Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-05-13T17:50:38Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-05-13T17:08:09Z"
        },
        {
          "tag": "v0.6.2",
          "kind": "patch",
          "published_at": "2026-05-13T15:33:29Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2026-05-01T22:30:05Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-04-28T14:31:10Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2026-04-24T22:38:22Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2026-04-22T02:38:39Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2026-04-20T00:36:33Z"
        },
        {
          "tag": "v0.2.0",
          "kind": "minor",
          "published_at": "2026-04-19T20:07:44Z"
        },
        {
          "tag": "v0.1.0",
          "kind": "minor",
          "published_at": "2026-04-19T19:28:20Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "8e0b492538df01efd83ce02d8336ebd4f6030e2c",
          "body": "…e-data\n\nfeat(calendar): provider-uniform join URLs (conferenceData + scrape fallback)",
          "is_bot": false,
          "headline": "Merge pull request #44 from JarvusInnovations/feat/calendar-conferenc…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-20T22:06:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ac3caf39ae50115892a9fa5c9a96885b553ba303",
          "body": "Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01X1L36Gc8WZ93aCfUHtrWbW",
          "is_bot": false,
          "headline": "chore(plans): mark calendar-conferencing done (PR #44)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-20T21:46:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e203b9c4a29b5e6e659b478edcfc62259bdcd7f4",
          "body": "README calendar-reads example + implementation-status entry in the\nproject CLAUDE.md.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01X1L36Gc8WZ93aCfUHtrWbW",
          "is_bot": false,
          "headline": "docs(calendar): note conferencing join-URL surface (#43)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-20T21:44:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cafdae37b9849d63cb5acf8740a050ff014c41aa",
          "body": "Surface a single tappable join link for any meeting, not just Google\nMeet. New shared resolver src/commands/calendar/conference.ts walks a\npriority chain: structured conferenceData video entryPoint -> hangoutLink\n-> provider-anchored URL scraped from description, then location.\n\nThe scrape is the on\n[…]\nAuth scope. 16 unit tests over real-shape Meet + Teams-synced fixtures.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01X1L36Gc8WZ93aCfUHtrWbW",
          "is_bot": false,
          "headline": "feat(calendar): resolve provider-uniform join URLs (#43)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-20T21:44:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "57be38d23401fe359d199b83f692bf9f78aae719",
          "body": "Spec the cross-command join-URL surface for `calendar events`/`get`:\na provider-uniform resolution chain (structured conferenceData video\nentryPoint -> hangoutLink -> provider-anchored description/location\nscrape) with source disclosure per surface-completeness-limits.\n\nMotivated by issue #43: a rea\n[…]\nhe\ndescription, so conferenceData alone leaves exactly that case blank.\n\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01X1L36Gc8WZ93aCfUHtrWbW",
          "is_bot": false,
          "headline": "docs(specs): add calendar conferencing spec + plan (#43)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-20T21:44:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fa2e25879f69190f308a863b1e20172ba8150c2d",
          "body": "fix(auth): never send joined teammates to the Cloud Console",
          "is_bot": false,
          "headline": "Merge pull request #41 from JarvusInnovations/fix/join-no-console",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T18:38:39Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eeb617b4d3fb876deeda28d2b991623327f2896d",
          "body": "A teammate who adopts a shared client via `auth join` has no IAM on the\nshared GCP project, but setup.html rendered the full per-step Cloud\nConsole deep-links (their setup is 6/7, not \"complete\", so links weren't\ncollapsed). Following one — e.g. \"Audience → Test users\" — dropped them on\na Console \"Y\n[…]\nvs\n  Internal consent-screen config, user cap, teammate steps).\n- Spec + status index updated; unit tests for the guidance helper.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(auth): never send joined teammates to the Cloud Console",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T17:07:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2d511e7a9e99aef9bc2bd87abbb4e769c025ac71",
          "body": "…hint\n\nfix(auth): name the target account on auth login (setup page + login_hint)",
          "is_bot": false,
          "headline": "Merge pull request #39 from JarvusInnovations/fix/auth-login-account-…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T12:51:00Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "37a22a20aaf3d4ce24bde7d718bb4f4f196fe10b",
          "body": "…n_hint)\n\nBare `auth login` (no --account) prepared an OAuth flow with no expected\naccount, so the setup.html panel showed a generic \"Waiting for\nauthentication\" and the Google URL carried no `login_hint` — the user\ncouldn't tell which account they were about to authenticate, or which\nbrowser profil\n[…]\nunt), so\nthis closes the gap without further UI changes. Documented in\narchitecture.md; unit-tested via the extracted pure helper.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(auth): name the target account on `auth login` (setup page + logi…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T05:39:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4419444086b218fcb28a5087b6d7f556b39c106f",
          "body": "feat(slides): inline-markdown links + comments",
          "is_bot": false,
          "headline": "Merge pull request #38 from JarvusInnovations/feat/slides-links-comments",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T04:54:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5da3a185951f2c87af082723cf3ea9aed7652356",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(plans): close out slides-links-comments done (PR #38)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T04:40:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e99b9b68af7390a00e532ad02f106ec2d98668fa",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: document slides links + comments in README and status index",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T04:39:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a0379723a18a88d3ffc6b8711a4078c8cb2a8eda",
          "body": "Slides text extraction dropped hyperlinks (read textRun.content, ignored\ntextRun.style.link). Now:\n- linkHref() maps external url → the url, internal pageObjectId →\n  slide:<id>; nav-only links (relativeLink/slideIndex) stay plain text.\n- runsToMarkdown() joins runs, wrapping linked spans as [text](\n[…]\nnts, no new scope. Unit tests cover linkHref, runsToMarkdown\n(coalescing, whitespace, distinct links, empty core), and extraction.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(slides): resolve embedded links inline as markdown + add comments",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T04:39:25Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4b85b1d50f07bdc77e42ddcf9c22f9f35edd247e",
          "body": "Backfill the previously-unspecced Slides read surface with a\ncontent-extraction contract (title/body/tables/notes, image counts,\ninline-markdown link resolution) and document the slides comments alias.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(specs): add slides read spec + links/comments plan",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T04:39:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2edf1a4b1bd3543095ae6b192f59ef916c4299f7",
          "body": "feat(sheets): add Sheets service — read (rich grid) + comments",
          "is_bot": false,
          "headline": "Merge pull request #36 from JarvusInnovations/feat/sheets-read",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T04:30:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6e7fc8fea1a3a192e5652e73991e5af8ee5f9a50",
          "body": "CI format:check (oxfmt) flagged the three new/edited files. Also add the\nSheets service to the README status table, intro, agent-instruction\nsnippet, usage examples, and roadmap.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "style(sheets): apply oxfmt formatting + document Sheets in README",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T03:47:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0066d8b109df52d7337bb1ea84f768dcde8f481c",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(plans): close out sheets-read done (PR #36)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T03:33:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5f93ab06461c75d860746334a794652ae85ca60c",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: record sheets service in project status index",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T03:31:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8968c7678a51152783d7733c5a2cb5dadadb46ab",
          "body": "New `sheets` service (BYO `spreadsheets` scope + sheets.googleapis.com;\nsheetsClient factory; doctor probe; cli registration).\n\n`sheets read <id>`:\n- Tab model like `docs read`: always lists sheets[N]{gid,title,index,rows,\n  cols}; single-tab auto-renders, multi-tab without --tab disambiguates.\n- Gr\n[…]\nts cover the pure helpers (column letters, A1 range origin,\ngrid build + header promotion, link/markdown extraction, header-mode).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(sheets): add sheets service — read (rich grid) + comments",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T03:31:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "41355d0a2e7d99a52db37db5437ff4081d64aa9a",
          "body": "Spec-first scaffold for a new Sheets service. `sheets read` mirrors the\n`docs read` tab model (a spreadsheet's sheets are its tabs), renders the\ngrid with A1-addressable column letters or auto/explicit header promotion,\nresolves embedded links inline as markdown, and surfaces cell notes. Also\nregisters sheets in architecture.md (commands, client factories, scopes).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(specs): add sheets read spec + plan",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T03:30:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c100ef8e5fd469a4ee3698d1afccb8a591d70bcf",
          "body": "feat(auth): add `auth join` for shared-client onboarding",
          "is_bot": false,
          "headline": "Merge pull request #35 from JarvusInnovations/feat/auth-join",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T00:34:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "caf80ec059f80704511ce20c36b5de17d1a9cb79",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(plan): close out auth-join (pr #35)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T00:27:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "72b6b3307ee00f9ff64564b251004b5eb7db5b70",
          "body": "Adds `gws-axi auth join <path> [--published]`: reads a shared Desktop\nOAuth client credentials.json from any path (e.g. ~/Downloads), copies\nit into the config dir, and marks setup steps 1-6 done (via: team-join),\nleaving step 7 (the teammate's own login) untouched. Lets a team reuse\none OAuth clien\n[…]\nJSON, shared by auth join, the\ncredentials_saved step, and the oauth_client auto-confirm.\n\nImplements specs/commands/auth-join.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(auth): add `auth join` for shared-client onboarding",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T00:26:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "00971768f0c507a5d26ecade6fc8cc50d416f2c6",
          "body": "Spec for a one-shot onboarding command onto an already-provisioned\n(shared) OAuth client: validate a Desktop credentials.json, install it,\nand mark setup steps 1-6 satisfied-by-the-shared-client so the from-\nscratch wizard doesn't misfire. Includes the local principle that\npublish status is asserted (--published), never inferred from the file.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(specs): add auth join spec + plan",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-07-02T00:26:56Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "28130d1b6b03c3b0aa52bed84b0dd4ab5215ad51",
          "body": "ci: add pre-merge lint/format/type-check gates",
          "is_bot": false,
          "headline": "Merge pull request #33 from JarvusInnovations/chore/ci-quality-gates",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-27T02:33:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6ec0a20e16e89c13a242855ded9b6951fb5eb415",
          "body": "Extend the existing build-and-test job with the standard pre-merge quality\ngates (oxlint, oxfmt --check, tsc --noEmit) ahead of build and test. Keeps\nthe repo's existing setup-node + setup-bun provisioning as-is; the gates are\ncredential-free and run on every push/PR to main and develop.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01QHVPQXzEiaPAupLgDa7D5n",
          "is_bot": false,
          "headline": "ci: add lint, format-check, and type-check gates to CI",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-27T02:17:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "028be6931887c3d45d4e8253d6e184f5f35c118f",
          "body": "One-time mechanical reformat of the TypeScript source tree with oxfmt\n(the new house formatter) so the format:check gate passes on its first\nCI run. No behavioral changes — formatting only.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01QHVPQXzEiaPAupLgDa7D5n",
          "is_bot": false,
          "headline": "style: apply oxfmt formatting across src",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-27T02:16:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2e8c974649ca2581e8114af65aeeeec0a63ef3bf",
          "body": "Clear the errors the new lint gate surfaces, all minimal:\n\n- Remove six unused imports/bindings (no-unused-vars): readPendingAuth\n  (auth.ts), readSetupState (steps.ts), getDefaultAccount (loopback.ts),\n  accountHeaderFields (service-stub.ts), gmail_v1 type (modify.ts), and the\n  dead runtimeFailing\n[…]\nintAt scan; same behavior, no control chars\n  in a RegExp.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01QHVPQXzEiaPAupLgDa7D5n",
          "is_bot": false,
          "headline": "fix: resolve oxlint correctness findings in existing code",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-27T02:15:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e5957e3aa88a113e853953b8bce2939a88623307",
          "body": "Add the Jarvus house TypeScript linter/formatter (oxlint + oxfmt) as dev\ndependencies and wire the standard four-script contract into package.json:\nlint / format / format:check / typecheck (scoped to src bin). Add the base\noxlint config (correctness-as-error) and recommend the oxc VS Code extension\nso local editing matches CI.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01QHVPQXzEiaPAupLgDa7D5n",
          "is_bot": false,
          "headline": "chore(ci): add oxlint + oxfmt tooling and quality-gate scripts",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-27T02:15:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5d6324ece893e4c8e595850992092882ebc7ba4e",
          "body": "…sync\n\ndocs(readme): sync command surface + status table",
          "is_bot": false,
          "headline": "Merge pull request #31 from JarvusInnovations/docs/readme-drive-docs-…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T16:35:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d66a96886cf6adbf42b61872d3972298c0dbe23d",
          "body": "… table\n\n- Status: replace the dense blockquote with a per-service Reads/Writes table\n  (✅ shipped / 🟡 partial / 🚧 planned / ✋ out of scope).\n- Docs: add `revisions` and `diff`; document `docs read`'s inline revisions;\n  fix the export flag (`--format` → `--as`) and add `--revision`.\n- Drive: split \n[…]\nin/--content, --convert, --convert+--update) + `mkdir`\n  writes.\n- Roadmap: correct the stale \"Drive writes not implemented\" line.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): sync command surface + replace status blockquote with a…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T16:34:51Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a0222a3add56d799a34dd1d4c1f3fbc78c43323e",
          "body": "…nt-sources\n\nfeat(drive): upload content sources (stdin/--content) + convert-on-update",
          "is_bot": false,
          "headline": "Merge pull request #30 from JarvusInnovations/feat/drive-upload-conte…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T16:07:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "32c87e4b34447f7bbabdd7123d2e836921b26bcc",
          "body": "…convert done (PR #30)\n\nCloseout for both upload follow-ups (shipped together in PR #30): status done,\nvalidation checked, Notes + Follow-ups populated. Updates CLAUDE.md status.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(plans): mark drive-upload-inline-content + drive-upload-update-…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T16:06:14Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6aae31f848bcb967ee1f1964c28b6816047db314",
          "body": "Lifts the blanket --convert + --update rejection. When the target file is\nalready the native type the source converts to (e.g. markdown -> existing\nDoc), the converted media is re-imported as a NEW revision — the write side\nof the read->edit->write-back loop with docs read/diff/revisions.\n\nA files.g\n[…]\n live: markdown convert+update bumped a Doc 1->2 revisions with\nreplaced content; csv-onto-Doc mismatch rejected. 131 tests green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(drive): allow --convert with --update for matching native targets",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T16:04:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d18d455fbd41ced39dc82303ae6a7792d5f93b76",
          "body": "drive upload now accepts content from three mutually-exclusive sources: a\nlocal file path (default), `-` for stdin, or --content <string>. For stdin\nand --content there's no filename to infer, so --name is required and the\ndefault --mime derives from the --name extension (reusing detectMimeType).\n\nL\n[…]\ne notes.md --convert`.\n\nVerified live: stdin and --content each create a native Doc via Google's\nconversion. 131 tests green (+5).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(drive): upload from stdin or --content (no temp file)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T16:01:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a2e7537fc8c8448ffde77f39392ad9fee0aeacbb",
          "body": "…date\n\nSpec-first groundwork for the two upload follow-ups:\n\n- Content sources: local path (default), stdin (`-`), or `--content <string>`;\n  exactly one required. --name required (and --mime derived from it) when\n  there's no filename to infer.\n- `--convert` + `--update`: lifted the blanket rejecti\n[…]\nvision (the write side of read->edit->write-back).\n\nMarks drive-upload-inline-content and drive-upload-update-convert in-progress.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(specs): extend drive upload with content sources + convert-on-up…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:58:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dcd3b766e1db5a47ef50bf64bd41df4700b9a19b",
          "body": "…overability\n\nfeat(docs): revision discoverability + diff command",
          "is_bot": false,
          "headline": "Merge pull request #28 from JarvusInnovations/feat/docs-revision-disc…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:34:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "74445418fbcf0798d2bb08a20870c1ec40e2ee1b",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(plans): mark docs-revision-discoverability done (PR #28)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:32:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "db5f4c1919239733c8e541db4e6d6fb03a6d114a",
          "body": "…lity\n\nCheck verified criteria and capture the work-in-progress record. Status\nstays in-progress; formal closeout (status done + pr) happens at merge.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(plans): record validation + notes for docs-revision-discoverabi…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:27:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5a39c623025bf713c0e9d0ca515123422d57740a",
          "body": "Resolve spec-drift audit findings (all spec-wording clarifications; no code\nchange — the implementation was correct and more specific than the prose):\n\n- docs-read: failure case emits a `revisions: history unavailable` scalar;\n  the unconditional version-history help entry covers the redirect.\n- doc\n[…]\n the fidelity caveat\n  lives in help[].\n- drive-revisions: REVISION_CONTENT_UNAVAILABLE also covers native export\n  HTTP failures.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(specs): tighten docs read/diff specs to match shipped behavior",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:26:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "14e9be58d1fe55bdde070f99fdba478d5c7cff98",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: update implementation status for docs read revisions + docs diff",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:22:49Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "99fc82e6b83c8366e35f9fe3c98b8cc35e7dd515",
          "body": "`docs diff <fileId> <revA> [revB]` exports both revisions to markdown\nserver-side and computes a unified diff locally (Google has no diff API),\nso agents don't download both sides and diff themselves. revB defaults to\nthe head revision.\n\nOutput: document/from/to provenance + summary{lines_added,line\n[…]\ntical revisions,\nREVISION_NOT_FOUND, VALIDATION_ERROR, and --help routing. computeDiff +\nparseFlags unit-tested (126 tests green).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(docs): add diff command for comparing two revisions",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:22:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6cb942dc64beaa99c80f513ec830bdfe43b2d527",
          "body": "docs read now shows a `revisions[5]{id,modified,author}` block on every read\n(provenance-by-default) and funnels help to `docs revisions`,\n`docs download --revision`, and `docs diff` with real revision ids.\n\nThe revisions fetch is best-effort: a failed secondary Drive call degrades to\na `revisions: history unavailable` note rather than failing the content read.\nVerified live against a real multi-tab Doc.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(docs): inline recent revisions in docs read",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:18:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d4acb86fd563895f985d5a9710ecf9e4230b18ea",
          "body": "Factor the revision-export logic out of `docs download --revision` into\nsrc/commands/docs/revision-content.ts:\n\n- fetchNativeRevisionExport — exportLinks fetch + markdown-default fallback,\n  returning bytes + provenance. Reused by the upcoming `docs diff`.\n- listRecentRevisions — minimal newest-firs\n[…]\nevision branch now calls the\nhelper; the binary branch keeps its own metadata + alt=media fetch. Build\nclean, all 116 tests green.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(docs): extract shared revision helpers",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:15:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fbfeff11a1094a78a1a999c8dae4c0c9d16b708c",
          "body": "Commands:\n  bun add diff\n  bun add -d @types/diff\n\nUsed by the upcoming `docs diff` to compute unified diffs of two\nrevisions' markdown exports locally (Google exposes no diff API).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(deps): add diff for docs diff command",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:11:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d897294ba9e4f2e780090c46ce3f2cdb50eac9e2",
          "body": "…e-convert\n\nTwo planned upload-side capabilities surfaced while specing the\nread->edit->write-back round trip:\n\n- drive-upload-inline-content: upload from stdin/--content (no temp file).\n- drive-upload-update-convert: allow --convert + --update so an existing\n  native Doc's content can be replaced from markdown as a new revision.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(plans): note follow-up plans for upload inline-content and updat…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:11:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5543aed6761f86c9a235a2a85c4b8104ec77c236",
          "body": "Spec groundwork for making Google Doc version history discoverable and\ndiffable, before implementation:\n\n- principles.md: new `provenance-by-default` — content reads carry their\n  source revision by default (deliberately overrides minimal-default-schemas);\n  justified by porting content between syst\n[…]\nmd: diff out-of-scope line now points at docs diff.\n- plans/docs-revision-discoverability.md: the implementing plan (in-progress).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(specs): add provenance-by-default, docs read revisions, docs diff",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-24T15:11:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "527c52beeb19bb5d32be5f777ea3c1ddfbfff03a",
          "body": "…hooks\n\nfeat(setup): add `setup hooks` command for session-hook install",
          "is_bot": false,
          "headline": "Merge pull request #26 from JarvusInnovations/feat/standardize-setup-…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-23T19:35:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3b202e6acd7923e5b442d64d847993d11e211660",
          "body": "Add an explicit `setup hooks` command that installs/repairs the agent\nSessionStart hook via installSessionStartHooks() (Claude Code, Codex,\nOpenCode), matching the AXI standard (principle 7) and the first-party\nreference tools (gh-axi, chrome-devtools-axi).\n\n- remove the stale auto-install path (the\n[…]\nle-skill as the two ambient-\n  context paths\n- update specs (architecture.md, new commands/setup.md), docs/design.md,\n  and README\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(setup): add `setup hooks` command for session-hook install",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-23T19:05:10Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9787f8797d30b7b4ce94ea2a8c4e78399b065983",
          "body": "feat(drive): add mkdir command (create folders)",
          "is_bot": false,
          "headline": "Merge pull request #24 from JarvusInnovations/feat/drive-mkdir",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-23T13:33:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ad912f8256840f3048fadaf3a11e336ea99ed7d5",
          "body": "Add `gws-axi drive mkdir <name>` — create a Drive folder via files.create\nwith mimeType application/vnd.google-apps.folder (no media); --parent nests\nit under an existing folder. Returns action: created + folder{id,name,\nparents,web_view_link} and leads help[] with `drive upload --parent <id>`.\n\nRep\n[…]\nd-to-end: folder -> nested folder -> upload into it -> ls.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01DsJVnPZmZWd4KdLHJYXCPQ",
          "is_bot": false,
          "headline": "feat(drive): implement mkdir command (create folders)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-23T13:32:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9bc90c233704d1df34c17a1f5846bd263f569138",
          "body": "Second Drive write: `gws-axi drive mkdir <name>` creates a folder\n(files.create with the folder MIME, no media), with optional --parent.\nProduces the folder ID that `drive upload --parent` consumes. Rides the\nexisting full `drive` scope — no new scope. Spec is source of truth.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01DsJVnPZmZWd4KdLHJYXCPQ",
          "is_bot": false,
          "headline": "docs(specs): add drive mkdir command spec",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-23T13:32:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "85eb7a653d81d60920ffdcf20d0927a7c8911b07",
          "body": "feat(drive): add upload command (create / convert / update)",
          "is_bot": false,
          "headline": "Merge pull request #22 from JarvusInnovations/feat/drive-upload",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-23T13:03:11Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c39cdebb6cf22a0a31870c9006e9f178f1400437",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01DsJVnPZmZWd4KdLHJYXCPQ",
          "is_bot": false,
          "headline": "chore(plans): mark drive-upload done (PR #22)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-23T12:55:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d535510ffa93836bc3712d0c029ba14f7085c78b",
          "body": "Add `gws-axi drive upload <local-path>` — the first Drive write:\n\n- create-new (default): stream a local file to files.create\n- --convert: server-side conversion to native Doc/Sheet/Slides\n- --update <fileId>: replace an existing file's content (new revision) + rename\n- --parent/--name/--mime, with \n[…]\nped via docs download), and the unsupported-convert guard.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01DsJVnPZmZWd4KdLHJYXCPQ",
          "is_bot": false,
          "headline": "feat(drive): implement upload command (create/convert/update)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-23T12:54:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "df89aa30cf9a718d458f180c4892156d903bd083",
          "body": "First Drive write: `gws-axi drive upload <local-path>` to push local file\nbytes into Drive, with --parent/--name/--mime, --convert (native Google\nformat), and --update <fileId> (replace content). Rides the existing full\n`drive` scope — no new scope. Spec is source of truth; implementation follows.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01DsJVnPZmZWd4KdLHJYXCPQ",
          "is_bot": false,
          "headline": "docs(specs): add drive upload command spec",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-23T12:54:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "013a0b5fa9a8e5cc9a972b35675ceed03f804198",
          "body": "…reauth-hints\n\nfix(doctor): emit per-account re-auth commands for scope/token gaps",
          "is_bot": false,
          "headline": "Merge pull request #20 from JarvusInnovations/fix/doctor-per-account-…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T17:33:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "13544140429b0d16eb439f5d63de3a32e64949b1",
          "body": "The scope-gap and token-failure hints named the affected accounts but\ngave only a generic `auth login --account <email>` template — leaving an\nagent to construct the command per account. Per AXI contextual-help-\nsuggestions, emit one concrete runnable line per affected account:\n\n  gws-axi auth login\n[…]\n-wait\n\nwith the agent prepare/relay/`--wait` flow spelled out, so an agent can\nrun them directly without filling in a placeholder.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(doctor): emit per-account re-auth commands for scope/token gaps",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T17:32:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "dd623218639fc8ff8df9aaf074c8e2a99d0bd693",
          "body": "…cope-checks\n\nfix(doctor): check ADDITIONAL_SCOPES presence per account",
          "is_bot": false,
          "headline": "Merge pull request #18 from JarvusInnovations/fix/doctor-additional-s…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T16:06:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "25e4459d2dfda800c6ac807c5a93ed34c9e74ea8",
          "body": "doctor's runtime tier only probed the five representative SERVICE_SCOPES,\nso a granted-but-missing additional scope (drive.activity.readonly,\ngmail.settings.basic) was invisible — surfacing only when the dependent\ncommand was finally run and failed. For scopes that require a one-time\nre-auth that's \n[…]\nautomatically.\n\nUpdates specs/commands/drive-activity.md (the doctor behavior it\npreviously disclaimed) and adds probe unit tests.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(doctor): check ADDITIONAL_SCOPES presence per account",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T16:05:33Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "060275e34c97ebcdb08c27345d25eda1846e0ebc",
          "body": "…exploration\n\nfeat: workspace history & exploration reads (gmail headers/raw, drive revisions, drive activity)",
          "is_bot": false,
          "headline": "Merge pull request #17 from JarvusInnovations/feat/workspace-history-…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:53:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6733c9a6ab098194076deac05ea66823a6df5240",
          "body": "Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(plans): record PR #17 on workspace-history-exploration",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:50:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a43031b285008a76dcb4df622c86684b7c242543",
          "body": "Flip status to done, check verified validation criteria, record Notes\n(live-verification scope, the audit pass) and Follow-ups (People API\nactor resolution, --full activity, revision --diff — all deferred).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(plans): close out workspace-history-exploration",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:48:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1c7423abf360f7539926ee468939b09551c1e058",
          "body": "Update CLAUDE.md \"Current implementation status\": gmail read\n--headers/--raw, drive/docs revisions + download --revision, drive\nactivity (with the drive.activity.readonly re-auth note), and the\nexpanded Vitest coverage.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(status): record workspace history & exploration reads",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:46:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cc64a8ef021d02b8eb88f559e787b1509468f718",
          "body": "Spec-drift audit of the three new features surfaced one bug and several\ngaps; bring code and specs back into conformance:\n\n- gmail read --raw --out: emit the same message{id,thread_id,internal_date,\n  bytes} shape as the inline path (was missing internal_date and nested\n  bytes at the wrong level).\n\n[…]\nhe additional\n  action labels + actor types; clarify the API-enablement vs runtime-probe\n  split for driveactivity.googleapis.com.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(workspace-history): resolve spec-drift audit findings",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:46:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4febee2fd5369ed64abb5bc04adc33dd31fd177b",
          "body": "Implements specs/commands/drive-activity.md.\n\n`drive activity <itemId>` reports an attributed, timestamped action\ntimeline — create/edit/move/rename/delete/restore, permission changes,\nand comments — as activities[N]{time,action,actor,target}, newest first.\nRicher than `drive revisions` (content ver\n[…]\nplied by auth/drive, so pre-existing accounts must re-auth\nonce — surfaced via an INSUFFICIENT_SCOPE error pointing at auth login.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(drive): add activity timeline via Drive Activity API v2",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:40:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "25bd94144b4256d659083d432a8e112d2622474d",
          "body": "Implements specs/commands/drive-revisions.md.\n\n`drive revisions <fileId>` (and `docs revisions` alias) lists a file's\nrevision history newest-first as revisions[N]{id,modified,author}, with\na document{} header (type native|binary, revision_count, head_revision),\n--full for size/mime/kept/published, \n[…]\nON_NOT_FOUND, EXPORT_FORMAT_REQUIRED, REVISION_CONTENT_UNAVAILABLE\n(purged binary revisions). No new scope — auth/drive covers it.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(drive): add revisions list + revision content download",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:37:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5243da41d7c12a407a2e307fa40a08e47b51c2bb",
          "body": "Implements specs/commands/gmail-read.md.\n\n--headers renders the full RFC 2822 header set (every Received hop,\nMessage-ID, In-Reply-To, References, DKIM/ARC auth results) as a\nheaders[N]{name,value} list plus internal_date, alongside the parsed\nbody so an agent gets provenance and readable content in\n[…]\nessage (noted in help[]). No new scope — gmail.modify already covers\nformat=raw and full payload headers. Reading stays read-only.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(gmail): add read --headers and --raw modes",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:32:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1e47b153730b0e544475e9fcb2b85aeb3591ef46",
          "body": "Spec-first for three additive read-only capabilities:\n- specs/commands/gmail-read.md — --raw (format=raw) + --headers (full\n  RFC 2822 header set + internalDate) modes; no new scope\n- specs/commands/drive-revisions.md — drive revisions list (+ docs\n  revisions alias) and docs download --revision; ma\n[…]\n tracking the build (three\ncommits, validation criteria) and IDs-first-class + completeness-limit\ndisclosure baked into each spec.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(specs): spec workspace history & exploration reads",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:29:40Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "854dda111e76fd228bc19e68978a5b4f7b123546",
          "body": "Reverse-engineer the existing codebase into specs/ as the source of truth:\n- specs/principles.md — decisive cross-cutting principles (agent-first\n  output, minimal default schemas, ids-are-first-class,\n  surface-completeness-limits, write-protection, read-only-stays-read-only,\n  byo-oauth, single-so\n[…]\nlans\ndashboard SessionStart hook (repo-relative path so it's portable across\ncontributors). Document the methodology in CLAUDE.md.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(specops): scaffold spec-driven development",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:23:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7600b67cf585897ad95a708a12ead4a66a91ec3e",
          "body": "Ran: npx skills add JarvusInnovations/specops\n\nVendors the skill subtree under .agents/skills/specops (universal +\nClaude Code symlink at .claude/skills/specops) and records skills-lock.json.\nInstalled per-project and committed so the spec-and-plan methodology\ntravels with the repo for every contributor and agent.\n\nProject scaffolding (specs/, plans/, session hook) follows separately.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(skills): install specops spec-driven-development skill",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:15:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7d7b31d1b3123aee4a6cd708aca0c5f591502f4b",
          "body": "Ran: bun add googleapis@latest google-auth-library@latest\n\nPin google-auth-library via `overrides` so the top-level copy and the one\nnested under googleapis-common resolve to a single instance. Without the\npin, googleapis-common pulls its own 10.5.x, producing two\nstructurally-distinct OAuth2Client \n[…]\ny range — npm rejects a literal version that differs from\nthe direct-dep spec (EOVERRIDE), which would break npm/npx in this repo.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(deps): bump googleapis 173.0.0 + google-auth-library 10.7.0",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-11T15:14:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "85d5714231831d5227eca91f0bd8071150a35c89",
          "body": null,
          "is_bot": false,
          "headline": "chore(asdf): bump nodejs to 22.22.3",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-10T22:13:10Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "da748289de8e19f03c20a2387f33c73660923d41",
          "body": "feat(gmail): implement write surface (decline send by design)",
          "is_bot": false,
          "headline": "Merge pull request #14 from JarvusInnovations/feat/gmail-writes",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-10T22:11:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ae1473962d1b32e12b3051fd9503bd6c84f53d0",
          "body": "Refresh README status blurb, add a full Gmail writes section (triage,\ndrafting, label CRUD, filters) with the send rationale and the\ngmail.settings.basic re-auth note, and update the roadmap. Correct the\nstale CLAUDE.md implementation-status block (Gmail writes done; Drive/Slides\nreads done; send deliberately omitted).\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: document Gmail write surface and send-is-out-of-scope",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-10T22:09:09Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0e48a54fc28a8a4223e9f7b5b020cd6c65dd23b8",
          "body": "Wire up the Gmail mutation commands behind the existing gmail.modify scope\n(plus gmail.settings.basic for filters):\n\n- draft        — compose a reviewable draft (text/plain, base64url MIME via\n                 compose.ts); --to/--cc/--bcc/--subject/--body|--body-file/--thread\n- modify       — add/re\n[…]\nhis is a\ncode/product boundary (guardrail against accidental sends), not a hard\nsecurity control — the token remains send-capable.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(gmail): implement write surface; decline send by design",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-10T22:09:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "52ff3c5854acdaa97526ef3f473359a0c8ae172a",
          "body": "Gmail filter management (users.settings.filters.*) requires\ngmail.settings.basic, which gmail.modify does not include. Add it as\nADDITIONAL_SCOPES — kept separate from the per-service representative\nscope so probe/health checks still key off a single scope each.\n\nAccounts authenticated before this change must re-run `auth login` once\nto pick up the new scope; filter commands surface SCOPE_MISSING until then.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(auth): request gmail.settings.basic scope for filter management",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-10T22:08:52Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1c80abfcce74ecaa3dbd767d1624ac089399883c",
          "body": "Pull label name↔id resolution (resolveLabelId, resolveLabelIds,\nlabelNamesFor, isSystemLabel, fetchLabels) out of search.ts into a shared\nlabels-shared.ts so the incoming write commands resolve labels identically.\nsearch.ts now imports the shared resolver; behavior is unchanged.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(gmail): extract shared label resolver",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-10T22:08:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d8b7302fac059798b6eee37c9ac3356b01f45fa4",
          "body": "Matches the first-party chrome-devtools-axi + slack-axi, which hand-render help\nas a multi-line `help[N]:` block rather than letting encode() inline it:\n- renderHelp now formats the block manually (all renderListResponse commands).\n- home returns a composed string (was an object the SDK inlined) so its help\n  is multi-line too; account/setup fields unchanged.\n\n37 tests passing.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(output): render help as multi-line block (canonical AXI form)",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-09T02:12:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "83bbc13eff023659bd88952c93c5fddc84392c66",
          "body": "Match the AXI home-screen convention: the final help line now reads\n\"Run `gws-axi --help` to see the full command list, or\n`gws-axi <command> --help` for usage on any command\".\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(home): expand command-list hint to point at per-command --help",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-06-08T13:15:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5c13336a85135ff3c52e266b05f27cfd490421cf",
          "body": "…rrent gaps\n\nThe README still described the v0.3 state (Calendar-only, Gmail/Docs/Drive/\nSlides as NOT_IMPLEMENTED stubs, 7-day token expiry as an open issue).\nRewrites the status banner, adds usage sections for the four newly-shipped\nservices, fixes the auth-login example to reflect the blocking-by\n[…]\n\nbehavior, and updates Known issues to the actual remaining gaps (Gmail\nwrites, Docs writes) plus the `auth publish` escape hatch.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): refresh for v0.8 — full read coverage, auth publish, cu…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-22T16:29:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4ab1a7601885376c1767080bc947470715739a8c",
          "body": "Gmail's composer stamps a Content-ID on every user-attached file\nalongside Content-Disposition: attachment. The previous heuristic\ntreated any Content-ID as inline, demoting real attachments to\n\"inline image\" and hiding them from `gmail read` output. Let the\nexplicit disposition win; fall back to the cid-heuristic only when\nno disposition was declared.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(gmail): surface attachments that also carry Content-ID",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-22T04:36:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ad86362a6435b90955e38843ec353dffdde21e56",
          "body": "Replaces buildServiceStub with a real dispatcher mirroring docs.ts /\ngmail.ts / drive.ts. Registers the three read handlers (get, page,\nsummarize); the two write subcommands (create, update) stay as\nplanned stubs with their own --help text.\n\nRemoves slides from cli.ts COMMAND_HELP so `slides <sub> -\n[…]\n(per the routing rule in CLAUDE.md) —\nwhich also means COMMAND_HELP is now empty of services: every\nservice has a real dispatcher.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(slides): wire up real dispatcher, drop stub",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-13T17:30:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "be79fe1f05f6d8c82d3ac768a791cf49dd8ce9ec",
          "body": "Read-only v1 slice for the slides service. Three handlers plus a\nshared text-extraction helper:\n\n- `slides/text.ts` — extractSlideContent walks a Page's pageElements,\n  pulling a best-effort title (from TITLE / CENTERED_TITLE\n  placeholders), body text from every other shape and table in\n  document \n[…]\nitalic line\n  noting images / tables / video. Same truncation + --out escape\n  hatches as `docs read` (default 8000 chars inline).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(slides): add get, page, summarize handlers",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-13T17:30:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "6ef814b484756daa6b81e554a7d3e4a01d9daa78",
          "body": "…bound\n\nThe arbitrary depth=10 default could cut off deeply-nested trees\nunexpectedly. The --limit (total file count, default 500, max 5000)\nis the real safety bound that prevents runaway walks. Default to\nNumber.POSITIVE_INFINITY for depth so the practical limit is just\ntotal file count; callers who want a \"shallow overview\" still pass\n--depth explicitly (e.g., --depth 2 for \"top two levels only\").\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(drive): default --depth to unlimited; --limit is the real safety …",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-13T17:05:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "844371c4e64123a4753aa22f2b494b91a88afae8",
          "body": "Replace buildServiceStub with a real dispatcher mirroring docs.ts and\ngmail.ts. Registers the four read handlers (ls, get, search,\npermissions) plus a `download` subcommand that delegates to\ndocs/download.ts — same implementation handles native Google file\nexport and uploaded-file media fetch regard\n[…]\n\nRemoves drive from cli.ts COMMAND_HELP so `drive <sub> --help` routes\nthrough the dispatcher (per the routing rule in CLAUDE.md).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(drive): wire up real dispatcher, drop stub",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-13T16:33:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "02d9cf21439da29003e8b0b50e558c33c38678c9",
          "body": "…lers\n\nRead-only v1 slice for the drive service. Four handlers:\n\n- `drive ls [<folder-id>] [--recursive] [--depth <n>] [--limit <n>]\n  [--page <token>] [--include-trashed]` — folder listing. Default is\n  shallow (one level); --recursive walks the tree and emits a flat\n  list with relative paths. Rec\n[…]\ns table (role, type,\n  email_or_domain). Flags \"anyone with link\" sharing and counts\n  external (off-domain) users in suggestions.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(drive): add ls (with --recursive), get, search, permissions hand…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-13T16:33:02Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8ded157ebb7f1379ac924471b69c504342daa16e",
          "body": "Closes #5.\n\nA \"what's on my calendar this week\" query against a busy schedule hits\n25 fast — AXI principle 2 (\"default limits high enough to cover common\ncases in one call\") prefers a default that doesn't force agents to\nre-run with --limit. 100 covers a full week of dense scheduling\ncomfortably; th\n[…]\nsearch at 25, docs find/\ncomments at 50) in this change — those have different volume\ncharacteristics and warrant separate review.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(calendar): bump events --limit default from 25 to 100",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-13T15:32:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f18af7db335494b618e68031086972549be99e8a",
          "body": "Closes #6.\n\nPreviously emitted `<name>[0]:` plus a separate `message:` sibling\n(parser-stability defense). The AXI convention is a single scalar\nfield — `<name>: <human-readable reason>` — which trades type\npolymorphism (array vs string) for one less field for agents to read.\nExternal review pointed\n[…]\nents that\nmirrored the old pattern. Populated lists are unchanged.\n\nUpdated the test guidance in CLAUDE.md to match the new shape.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(output): collapse empty lists to AXI canonical scalar form",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-13T15:32:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "28515af761c44acf48aa766e1e8ffad0f9aa07ca",
          "body": "Calendar events can carry Drive attachments — typically meeting notes\n(Gemini Notes / Notes by Gemini), agendas, slide decks. The Calendar\nAPI returns these on the event resource as attachments[], but neither\ncalendar events nor calendar get exposed them, so an agent looking up\n\"my meeting earlier t\n[…]\n at\n    least one is a Google Doc). Agents scanning events see \"this one\n    has notes\" at-a-glance without knowing to ask for it.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(calendar): surface event attachments to enable handoff to docs read",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-05-01T22:28:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d650e48170674b59ea0c4830511ba4d276cd065d",
          "body": "When --account doesn't match any existing authenticated account but is\nwithin edit distance ≤2 of one, abort BEFORE preparing the OAuth flow\n(LIKELY_TYPO error) with a \"did you mean\" pointing at the corrected\ncommand. The post-OAuth account-mismatch check still exists as a\nbackstop, but most typos n\n[…]\nunt ... double-check spelling\n\nAlso dedupes the inline editDistance helper out of loopback.ts in favor\nof the shared util/typo.ts.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(auth): pre-flight typo check on `auth login --account`",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T14:26:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "9d0d5cddaa0248ffba057c868b4e51522d2a85ee",
          "body": "Pulled out of loopback.ts so other commands can also flag close-match\ntypos before doing expensive work. Two exports:\n\n  - editDistance(a, b): Levenshtein distance, iterative DP.\n  - findLikelyTypo(value, candidates, maxDistance=2): returns the closest\n    candidate within the threshold, or undefine\n[…]\n/ substitutions, the \"themightychris@gmai.com\" → \"gmail.com\"\ncase that triggered this, threshold respect, and best-of-N selection.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(util): add reusable typo / edit-distance helper with tests",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T14:26:38Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "89cc33ab3163c2a5d1b0e4c8dd2174bf932ea24a",
          "body": "When the authenticated email differs from --account by ≤2 characters\n(and length differs by ≤2), the error now says \"Likely typo in\n--account\" with the corrected command pre-filled, instead of just\nshowing the two strings side-by-side. Two long emails differing by one\ncharacter were nearly impossibl\n[…]\ngws-axi auth login --account themightychris@gmail.com`...\n\nInlines a small Levenshtein helper rather than pulling in a dependency.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(auth): explicitly flag likely typos in account-mismatch errors",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T14:21:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "c2a5d58d47c985fe6f08ffce90bcf21c5cd6580a",
          "body": "prepareLogin's instructions array now adds a bullet calling out the\n\"Google hasn't verified this app\" warning and the \"Advanced → Go to\n<app> (unsafe)\" path. Phrased emphatically when predictUnverifiedApp\nWarning returns \"always\" (personal Gmail / Testing-state app — the\nwarning will appear), softer\n[…]\n auth command file so future\nflows (e.g., agents that re-issue prepare without a new login) inherit\nthe same conditional language.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(auth): include Advanced-link instruction in agent-flow login output",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T14:14:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "753912ec9f193231f09de4b8b2b17be406e1e064",
          "body": "waitForCallback was sending the \"Authenticated\" page to the browser\nimmediately on receiving the OAuth code, BEFORE token exchange and\nwriteAccountFiles ran. If exchange failed or the authenticated email\ndidn't match what we asked for (account-mismatch), the browser still\nshowed success while the CL\n[…]\nnverifiedAppWarning into the\nloopback's writeSetupHtml call so the html panel gets the right\nwarning level for the target account.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(auth): defer success page until token write actually succeeds",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T14:13:55Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ec56a53fa26de899de1b8074f1e83c7e0a3c2d56",
          "body": "Add predictUnverifiedAppWarning(email, published) classifying when the\n\"Google hasn't verified this app\" intermediate screen will appear:\n\n  - \"always\": personal Gmail (@gmail.com / @googlemail.com), OR app\n    still in Testing state. Render a strong yellow banner instructing\n    the user to click \"\n[…]\n see the\nguidance right next to the \"Authenticate with Google\" button rather\nthan discovering the small Advanced link by accident.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(auth): predict + display unverified-app warning on setup.html",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T14:13:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ad9fe55016fb37963ed5170a8f0ba4b33eac45e7",
          "body": "doctor now exposes an `auth_health:` section between accounts and\nruntime that summarizes:\n  - whether the consent screen is published (the 7-day vs permanent\n    distinction)\n  - per-account token permanence rolled into the failing/warning tally,\n    so a pre-publish account warns even when API pro\n[…]\nt\n\"restricted scope (gmail.modify) ✓\" (separately committed) so the\nrestricted-scope dimension is also visible in the same output.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(doctor): report token permanence per account in auth_health block",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T14:00:36Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2a3b99099bc56144a24675ad3f29e8baf96bc7db",
          "body": "…n success\n\nAfter a successful OAuth callback, the response now carries:\n  - token_permanence: e.g. \"permanent — issued 0s after publish\" or\n    \"7-day clock — consent screen still in Testing...\"\n  - restricted_scope: live API probe of gmail.modify via\n    gmail.users.getProfile, reporting \"gmail.mo\n[…]\ny expiration —\nrunning auth login now tells you whether the new token is permanent\nwithout having to remember to run doctor after.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(auth): report token permanence + restricted-scope status on logi…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T14:00:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "53bddaf43cb22a308ad13e560c16f5da5b215057",
          "body": "… probe\n\nTwo reusable checks both `auth login` and `doctor` should report:\n\n1. summarizeAccountHealth(email): compares the account's stored\n   obtained_at against state.published.confirmed_at and classifies\n   permanence as 'permanent', 'pre-publish-7-day' (published but token\n   pre-dates publish),\n[…]\nscope verification explicitly (\"restricted scope\n(gmail.modify) ✓\") rather than burying that signal under an opaque\nmessage count.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(auth): add health helper for token permanence + restricted-scope…",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T14:00:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "d613eab02cfc5d0f0f45630a64cc7c865aaf6113",
          "body": "…timestamp\n\n`auth publish` (no flag) now reads each account's obtained_at and\ncompares it against state.published.confirmed_at to flag which tokens\nwere issued under the 7-day Testing-state policy vs which were issued\npost-publish. Pre-publish accounts get a per-account re-auth checklist;\nall-post-p\n[…]\nuires verification\" banner is about consent-screen warnings, NOT\nabout token longevity (the 7-day expiry is purely Testing-state).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(auth): publish reports per-account token status against publish …",
          "author_name": "Chris Alfano",
          "author_login": "themightychris",
          "committed_at": "2026-04-28T13:52:27Z",
          "body_truncated": true,
          "is_coding_agent": true
        }
      ],
      "releases_count": 28,
      "commits_last_year": 181,
      "latest_release_at": "2026-07-20T22:08:31Z",
      "latest_release_tag": "v0.17.0",
      "releases_from_tags": false,
      "days_since_last_push": 6,
      "active_weeks_last_year": 9,
      "days_since_latest_release": 6,
      "mean_days_between_releases": 3
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 50,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "gws-axi",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "google",
            "google-workspace",
            "gmail",
            "calendar",
            "docs",
            "drive",
            "slides",
            "cli",
            "agent",
            "axi",
            "toon"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/gws-axi",
          "is_deprecated": false,
          "latest_version": "0.17.0",
          "repository_url": "https://github.com/JarvusInnovations/gws-axi",
          "versions_count": 28,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 2188,
          "first_published_at": "2026-04-19T19:26:14.414000Z",
          "latest_published_at": "2026-07-20T22:09:02.105000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 6
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 8,
      "watchers": 0,
      "fork_history": {
        "days": [
          {
            "date": "2026-07-25",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [
        "tsconfig.json"
      ],
      "toolchain_manifests": [],
      "largest_source_bytes": 53959,
      "source_files_sampled": 97,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        ".claude/CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 13597
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [
          {
            "name": "brace-expansion",
            "direct": false,
            "version": "2.1.2",
            "severity": "high",
            "ecosystem": "npm",
            "cvss_score": 7.5,
            "advisory_ids": [
              "GHSA-mh99-v99m-4gvg"
            ],
            "fixed_version": "5.0.8",
            "advisory_count": 1,
            "oldest_advisory_days": 2
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "high": 1
        },
        "advisory_count": 1,
        "affected_count": 1,
        "assessed_count": 93,
        "malicious_count": 0,
        "assessed_package": "npm:gws-axi@0.17.0",
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@toon-format/toon",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^2.1.0"
        },
        {
          "name": "addressparser",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.0.1"
        },
        {
          "name": "axi-sdk-js",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.1.4"
        },
        {
          "name": "diff",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^9.0.0"
        },
        {
          "name": "google-auth-library",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.7.0"
        },
        {
          "name": "googleapis",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^173.0.0"
        },
        {
          "name": "turndown",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^7.2.4"
        }
      ],
      "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": 42,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 3,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "themightychris",
          "commits": 181,
          "avatar_url": "https://avatars.githubusercontent.com/u/458494?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml",
        "publish-npm.yml",
        "release-prepare.yml",
        "release-publish.yml",
        "release-validate.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "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": 3,
            "reason": "branch protection is not maximal on development and all release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": 10,
            "reason": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/8 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 5 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 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 3 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": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 7,
            "reason": "3 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "8e0b492538df01efd83ce02d8336ebd4f6030e2c",
        "ran_at": "2026-07-27T16:10:39Z",
        "aggregate_score": 4.6,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-20T22:08:34Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": "2026-07-20T22:08:20Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/JarvusInnovations/gws-axi",
    "host": "github.com",
    "name": "gws-axi",
    "owner": "JarvusInnovations"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 62,
      "inputs": {
        "security": 54,
        "vitality": 82,
        "community": 37,
        "governance": 63,
        "engineering": 67
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 82,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "commits_last_year": 181,
              "human_commit_share": 1,
              "days_since_last_push": 6,
              "active_weeks_last_year": 9
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 6 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "9/52 weeks with commits",
                "points": 6.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 9
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "181 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 181
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 28,
              "latest_release_tag": "v0.17.0",
              "releases_from_tags": false,
              "days_since_latest_release": 6,
              "mean_days_between_releases": 3
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "28 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 28
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 6 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~3 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 3
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "at_risk",
        "name": "Community & Adoption",
        "value": 37,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 14,
            "inputs": {
              "forks": 1,
              "stars": 8,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "8 stars",
                "points": 13.7,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 8
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "moderate",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 50,
            "inputs": {
              "has_readme": true,
              "has_license": true,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "recognized license (MIT)",
                "points": 22.5,
                "status": "met",
                "details": [
                  {
                    "code": "license_standard",
                    "params": {}
                  },
                  {
                    "code": "license_spdx",
                    "params": {
                      "spdx": "MIT"
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": 56,
            "inputs": {
              "packages": [
                "gws-axi"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 2188
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "2,188 downloads/month across npm",
                "points": 44.5,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 2188,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "not reported by this ecosystem",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_reported_by_this_ecosystem",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 63,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 20,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "merged_prs": 42,
              "open_issues": 0,
              "closed_issues": 3,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "42/42 decided PRs merged",
                "points": 38.2,
                "status": "met",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 42,
                      "decided": 42
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/8 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": null,
            "notes": [],
            "value": 63,
            "inputs": {
              "followers": 12,
              "owner_type": "Organization",
              "is_verified": null,
              "owner_login": "JarvusInnovations",
              "public_repos": 225,
              "account_age_days": 5646
            },
            "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": "12 followers of JarvusInnovations",
                "points": 8,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 12,
                      "login": "JarvusInnovations"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "225 public repos, account ~15 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 225
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 15
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "gws-axi"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 6
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on npm",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "npm"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 6 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 6
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "28 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 28
                    }
                  }
                ],
                "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": "moderate",
        "name": "Engineering Quality",
        "value": 67,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 68,
            "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": "5 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "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": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "moderate",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 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": "moderate",
        "name": "Security",
        "value": 54,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 46,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 17,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 1,
              "scorecard_aggregate": 4.6
            },
            "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 is not maximal on development and all release branches",
                "points": 2.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "8 out of 8 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/8 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file detected",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 3 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": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "3 existing vulnerabilities detected",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "excellent",
            "name": "Dependency advisories",
            "note": "Matched the npm:gws-axi@0.17.0 runtime dependency closure — what installing the published package pulls in — 93 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:gws-axi@0.17.0",
                  "assessed": 93
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 85,
            "inputs": {
              "source": "osv",
              "advisories": 1,
              "affected_packages": 1,
              "assessed_packages": 93,
              "unassessed_packages": 0,
              "affected_by_severity": "high 1",
              "direct_affected_packages": 0
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "no direct dependency carries a known advisory",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "no_direct_advisories",
                    "params": {}
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "1 affected: brace-expansion 2.1.2 (high 7.5)",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "brace-expansion 2.1.2 (high 7.5)"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory has been public longer than 90 days",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "advisories_none_stale",
                    "params": {
                      "days": 90
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "malicious_dependencies",
            "band": "excellent",
            "name": "Malicious dependencies",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "source": "osv",
              "meaning": "reported as a malicious package by the OpenSSF corpus; the remedy is removal or moving off the compromised name, never an upgrade of the same artifact. Versions the registry has since pulled are listed but not scored",
              "packages": [],
              "red_flag": false,
              "assessed_packages": 93,
              "malicious_packages": 0,
              "direct_malicious_packages": 0,
              "withdrawn_malicious_packages": 0,
              "installable_malicious_packages": 0
            },
            "components": [
              {
                "key": "no_dependency_reported_as_a_malicious_package",
                "name": "No dependency reported as a malicious package",
                "detail": "no dependency is reported as a malicious package",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "no_malicious_dependencies",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "excellent",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "review_only_matches": 0,
              "assessed_self_published_locations": 5
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 68,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 1,
              "agent_instruction_files": [
                ".claude/CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 13597
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": ".claude/CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": ".claude/CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "100 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 100,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 43,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "tsconfig.json"
              ],
              "agent_commit_share": 0.82,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "tsconfig.json",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "tsconfig.json"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "82 of the last 100 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 82,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "TypeScript",
              "largest_source_bytes": 53959,
              "source_files_sampled": 97,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "TypeScript (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "TypeScript"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/97 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 97,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-27T16:10:57.302980Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/j/JarvusInnovations/gws-axi.svg",
  "full_name": "JarvusInnovations/gws-axi",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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