公开记录
软件健康报告模式 0.27.0 · 指标 1.13.0 · 2026-07-25 19:13 UTC

C4T4 / heyamigo

Personal AI powered by Claude Code, Codex and Grok Build. Remembers people, browses the web, learns over time. First party, no API keys.

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

C4T4/heyamigo 的健康指数为 100 分中的 52 分,处于「中等」区间。 其得分最高的类别是Vitality(77/100),最低的是Community & Adoption(35/100)。 最近一次更新在 5 天前。 近期的大部分工作由 1 位贡献者完成。

52
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

Catalin Waack个人账户
16 关注者15 个公开仓库始于 2015年5月Waack International

该仓库由个人账户拥有。相较于组织支持的项目,单一所有者项目的延续性风险更高。

软件包生态系统

注册表软件包版本月下载量版本数最近发布标签
npm@c4t4/heyamigo0.12.62,186855 天前whatsapptelegramchatbotclaudeaibaileysbotanthropic

按类别列示的指标

活力

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

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

发布纪律

88优秀
评分方式
16.2/27有发布版本 — 10 个版本标签(无 GitHub 发布版本)
36/36发布时效 — 最近一次发布版本于 60 天前
27/27发布节奏 — 约每 5.5 天发布一次
0/10OpenSSF Scorecard:Signed-Releases — 无数据
所用输入
releases_count10
latest_release_tagv0.10.4
releases_from_tags
days_since_latest_release60
mean_days_between_releases5.5
已排除计分(无数据或不适用):OpenSSF Scorecard:Signed-Releases。 其余权重已重新归一化。

社区与采用

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

35存在风险 · 占总体的 18%
评分方式
7.7/60星标 — 4 个星标
0/25复刻 — 0 个复刻
0/15关注者 — 0 位关注者
所用输入
forks0
stars4
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,186 次下载
0/20注册表被依赖数 — 该生态系统不报告此项
所用输入
packages@c4t4/heyamigo
dependents
ecosystemsnpm
total_downloads
monthly_downloads2,186
已排除计分(无数据或不适用):注册表被依赖数。 其余权重已重新归一化。

可持续性与治理

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

39存在风险 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
0/22.5提交分布 — 头号贡献者编写了 100% 的提交
1.4/13.5贡献者广度 — 1 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 3 contributing companies or organizations -- score normalized to 10
所用输入
bus_factor1
contributors_sampled1
top_contributor_share1
评分方式
0/46.8议题解决 — 没有议题或无数据
0/38.3PR 接受 — 没有已裁定的拉取请求或无数据
0/15OpenSSF Scorecard:Code-Review — Found 0/30 approved changesets -- score normalized to 0
所用输入
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs0
已排除计分(无数据或不适用):议题解决, PR 接受。 其余权重已重新归一化。
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
8.8/25所有者影响力 — C4T4 有 16 位关注者
20.8/25既往记录 — 15 个公开仓库,账户约 11 年
所用输入
followers16
owner_typeUser
is_verified
owner_loginC4T4
public_repos15
account_age_days4,092
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — npm 上有 1 个软件包
35/35发布时效 — 最近一次发布于 5 天前
20/20版本历史 — 85 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packages@c4t4/heyamigo
ecosystemsnpm
any_deprecated
min_days_since_publish5

工程质量

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

58中等 · 占总体的 20%

工程实践

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

文档

100优秀
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://heyamigo.org
10/10仓库描述
10/10主题标签 — 3 个主题标签
10/10Wiki
所用输入
topicsclaude-code, openclaw, whatsapp-bot
has_wiki
homepagehttps://heyamigo.org
has_readme
has_docs_dir
has_description

安全

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

51中等 · 占总体的 16%

安全态势

45存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — 无数据
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
2.5/2.5Contributors — project has 3 contributing companies or organizations -- score normalized to 10
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 0 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 — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — 无数据
7.5/7.5Token-Permissions — GitHub workflow tokens follow principle of least privilege
0/7.5Vulnerabilities — 18 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate4.5
已排除计分(无数据或不适用):ci_tests, signed_releases。 其余权重已重新归一化。
评分方式
9.5/35直接依赖不含已知公告 — 1 个受影响:baileys 7.0.0-rc.9 (critical 9.1)
25/25间接依赖不含已知公告 — 没有间接依赖携带已知公告
40/40没有长期未处理的公告 — 没有公告公开超过 90 天
所用输入
sourceosv
advisories1
affected_packages1
assessed_packages141
unassessed_packages0
affected_by_severitycritical 1
direct_affected_packages1
比对的是 npm:@c4t4/heyamigo@0.12.6 的运行时依赖闭包——安装已发布的软件包时真正被拉取进来的内容——共 141 个软件包。 未对可达性进行分析。

AI 就绪度

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

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

关键数据

4GitHub 星标
1贡献者
94最近 12 个月提交数
5距最近推送天数
10发布版本数
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.5 / 10
4.5综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
不适用CI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
10Contributorsproject has 3 contributing companies or organizations -- score normalized to 10
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
10Licenselicense file detected
10Maintained30 commit(s) and 0 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
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
10Token-PermissionsGitHub workflow tokens follow principle of least privilege
0Vulnerabilities18 existing vulnerabilities detected
直接依赖 11
注册表软件包版本约束清单文件
npm@clack/prompts^1.2.0package.json
npm@hapi/boom^10.0.1package.json
npmbaileys7.0.0-rc.9package.json
npmbetter-sqlite3^12.10.0package.json
npmcommander^14.0.3package.json
npmcroner^10.0.1package.json
npmdrizzle-orm^0.45.2package.json
npmfastq^1.17.1package.json
npmpino^9.3.2package.json
npmqrcode^1.5.4package.json
npmzod^3.23.8package.json
全部依赖 未采集

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

依赖安全公告 1

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

软件包版本关系严重程度公告数修复版本
baileys7.0.0-rc.9直接严重17.0.0-rc12

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [
        "claude-code",
        "openclaw",
        "whatsapp-bot"
      ],
      "is_fork": false,
      "size_kb": 1462,
      "has_wiki": true,
      "homepage": "https://heyamigo.org",
      "languages": {
        "Shell": 18984,
        "JavaScript": 4976,
        "TypeScript": 523782
      },
      "pushed_at": "2026-07-19T20:06:40Z",
      "created_at": "2026-04-06T12:56:57Z",
      "owner_type": "User",
      "updated_at": "2026-07-19T20:06:43Z",
      "description": "Personal AI powered by Claude Code, Codex and Grok Build. Remembers people, browses the web, learns over time. First party, no API keys.  ",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": "MIT",
      "default_branch": "main",
      "license_spdx_raw": "MIT",
      "primary_language": "TypeScript",
      "significant_languages": [
        "TypeScript"
      ]
    },
    "owner": {
      "blog": "catalinwaack.com",
      "name": "Catalin Waack",
      "type": "User",
      "login": "C4T4",
      "company": "Waack International",
      "location": "Remote",
      "followers": 16,
      "avatar_url": "https://avatars.githubusercontent.com/u/12415654?v=4",
      "created_at": "2015-05-12T17:23:06Z",
      "is_verified": null,
      "public_repos": 15,
      "account_age_days": 4092
    },
    "license": {
      "state": "standard",
      "spdx_id": "MIT",
      "raw_spdx": "MIT",
      "file_present": true,
      "scorecard_found": true,
      "profile_has_license": true
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.10.4",
          "kind": "patch",
          "published_at": "2026-05-25T21:59:34Z"
        },
        {
          "tag": "v0.10.3",
          "kind": "patch",
          "published_at": "2026-05-25T19:09:46Z"
        },
        {
          "tag": "v0.1.8",
          "kind": "patch",
          "published_at": "2026-04-06T17:06:38Z"
        },
        {
          "tag": "v0.1.7",
          "kind": "patch",
          "published_at": "2026-04-06T15:03:25Z"
        },
        {
          "tag": "v0.1.6",
          "kind": "patch",
          "published_at": "2026-04-06T14:55:03Z"
        },
        {
          "tag": "v0.1.5",
          "kind": "patch",
          "published_at": "2026-04-06T14:51:01Z"
        },
        {
          "tag": "v0.1.4",
          "kind": "patch",
          "published_at": "2026-04-06T14:45:34Z"
        },
        {
          "tag": "v0.1.3",
          "kind": "patch",
          "published_at": "2026-04-06T14:37:01Z"
        },
        {
          "tag": "v0.1.2",
          "kind": "patch",
          "published_at": "2026-04-06T14:30:47Z"
        },
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-04-06T14:25:07Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "72ce2e770a4217ae9bac59f794c2b5a82f86b454",
          "body": null,
          "is_bot": false,
          "headline": "Gate oversized media errors behind triggers",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-07-19T20:06:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "86abade117398e8d2fd6bcadb9d4272e357a10de",
          "body": null,
          "is_bot": false,
          "headline": "Show versions before upgrading Heyamigo",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-07-16T16:47:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "744e0f615a07503271fcb5f25ac88c3a57a6e58b",
          "body": null,
          "is_bot": false,
          "headline": "Use global heyamigo CLI commands",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-07-16T16:34:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "861ea4172324ffd68cda45a74725ee0ca8616d7e",
          "body": null,
          "is_bot": false,
          "headline": "Show model and thinking in reply footer",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-07-16T16:29:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e60629d1c2b5ffa52f5ec490fd01447cd57b76cc",
          "body": null,
          "is_bot": false,
          "headline": "Add per-chat Codex thinking controls",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-07-16T16:21:14Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d8c34bd6b69cdd278f1797be14da69b69b56d56c",
          "body": null,
          "is_bot": false,
          "headline": "Allow owner replies in active DMs",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-07-02T15:05:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9b59146360cfaf9242247ef082c5111abdc216f1",
          "body": null,
          "is_bot": false,
          "headline": "Add optional ElevenLabs voice replies",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-06-25T02:07:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4d4e34cf5dcfa0b8152ed10673e26c31dcc87fa3",
          "body": null,
          "is_bot": false,
          "headline": "Allow standalone audio trigger pronunciations",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-06-25T01:46:18Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "43bd72c9de7eb40199887d97291a94185f5e2e54",
          "body": null,
          "is_bot": false,
          "headline": "Bump version to 0.11.1",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-06-25T01:28:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "893c0ae618fc81c7da13869b10c0c90904bb1242",
          "body": null,
          "is_bot": false,
          "headline": "Tolerate audio trigger pronunciations",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-06-25T01:26:51Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "66a3782182b8ae23e9774d82e67cc01b0618ca7c",
          "body": null,
          "is_bot": false,
          "headline": "Add provider-backed audio transcription",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-06-25T00:41:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f7f7592aabe0a20815de6f1032efb11e83b51cef",
          "body": null,
          "is_bot": false,
          "headline": "Add standalone job installer docs",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-27T22:14:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb45220ee289c06c4488a0cfc8cae9ee45ad1e95",
          "body": null,
          "is_bot": false,
          "headline": "Move trigger mode into access config",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-27T14:50:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "143ecd7845439df000aba1b7291dda70842e9ff3",
          "body": null,
          "is_bot": false,
          "headline": "Route web lookup through BrowserUse",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-27T14:48:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "44c2bfd56b2ee629bff1f534e2249acf7f72e4ed",
          "body": null,
          "is_bot": false,
          "headline": "0.10.4",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T21:59:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "96cd68ed36ee7aee2774bf4ad548a34c0593a23c",
          "body": null,
          "is_bot": false,
          "headline": "harden queued tag and media flow",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T21:59:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4a3ad17ac93df50d8bce2fe590d3aaea02a9b5e3",
          "body": null,
          "is_bot": false,
          "headline": "0.10.3",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T19:09:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59bac80ce2a2ee99f9edd7838bedf1dc4a5da831",
          "body": "- Keep only heyamigo-premium-clean.jpg as the official banner\n- Update README hero image\n- Add grok/codex/xai to trigger aliases in config.example.json",
          "is_bot": false,
          "headline": "Branding: Switch to clean minimal premium image as main banner",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T19:07:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fe1b2b76d00f4b9b1d60a5d9c084bb1ba18413d0",
          "body": null,
          "is_bot": false,
          "headline": "add telegram channel support",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T18:28:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8431bffee21dcd11c92d1e6b8a4ba48db030e501",
          "body": null,
          "is_bot": false,
          "headline": "add grok build provider",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T18:03:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5b33e8f23ac3fdf60ee3dd7813d2091454ce2bbd",
          "body": "Default-deny was the right rule for proactive messaging (unsolicited\nsends into groups). Threads in v1 is reactive only — preamble block\n+ tag processing during normal conversation, no unsolicited anything.\nDefaulting off was applying the wrong rule.\n\nFlipping to enabled=true. Worst case on upgrade \n[…]\n trade for the\nfeature actually being available without a config dig.\n\nTo disable: set threads.enabled=false in config.local.json.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Threads default on",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T17:22:37Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "a0941be7f7b47a81c900a31ac639cc3d519b6e9d",
          "body": "Pull the engineering substance out of the README into a separate\ndocs/architecture.md, leaving the README as a fast skim. The\nREADME focuses on what the system does at the surface; the\narchitecture doc explains the design decisions behind it.\n\nSpecifics moved to docs/architecture.md:\n- per-address c\n[…]\n\nREADME keeps the quick-start, in-chat commands, roles, and where\nto run it. Links once to docs/architecture.md for the deep dive.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "README rewrite + architecture doc",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T16:56:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "863c370064881a863e27994f3265109b0ded114f",
          "body": "A new layer between cold memory (journals/profiles/buckets) and\nlive conversation. The AI tracks open loops — things the user\nmentioned in passing that have a future resolution point —\nbrings them up naturally when relevant, and updates its own\nhotness as signals arrive. Replaces the brittle journal\n[…]\n.\n\nMigration 0010 adds the two new tables. Scheduler boot now drops\nthe legacy journal-nudge-tick cron row from existing installs.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Threads: AI-curated relevance watchlist",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T16:38:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4f236dbe1c4b30d9277105a57166de562fa63ccd",
          "body": "Per-tag visibility so the user gets instant confirmation that a\nside effect fired, instead of waiting for the reminder to trigger\nto find out whether [REMIND:] actually got emitted.\n\nBefore: 9.9s · 465k↑ (230k cached) 169↓\nAfter:  9.9s · 465k↑ (230k cached) 169↓ · +remind\n\nNew footer entries (plural\n[…]\n extras parameter to\nformatStatsFooter so ReplyStats stays cohesive (AI-run stats\nonly) instead of mixing in outbound-shaped data.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Footer: surface every emitted tag",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T15:42:50Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "63470eed9c4aeb51eecfe0e7db1ebc3dcb92438d",
          "body": "Per-turn skeleton 1,600 → 282 tokens (82% cut). Cached system\nprompt 5,510 → 2,472 tokens (55% cut). Same behavior, both\nClaude and Codex read terse fine.\n\npreamble.ts:\n- DIGEST/JOURNAL/ASYNC reminders: 1-line pointers, full rules\n  live in cached memory-instructions.md\n- buildSchedulingReminder: 75\n[…]\ncondensed to one paragraph\n\ndb/schema.ts: comment cleanup + cost-tracking columns\ncatching up to migration 0009 (already in prod).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Prompt diet: -1300 tokens/turn, -3000 tokens cached",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T15:29:17Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "779727fe705bee7c9ba6f9747f13c9bcc6f79e75",
          "body": "Three intertwined wins. Standard cron expressions (via croner) +\nexplicit variant verbs (SAY/PROMPT/ASYNC/BROWSER) that route the\nfiring into the right queue + token-cost attribution per cron row.\n\n### Schema\nMigration 0009: ALTER TABLE crons ADD fire_count,\ntotal_input_tokens, total_output_tokens (\n[…]\n;\n  needs cronId threaded OR migration to SQLite\n- BROWSER cost tracking — needs cron_id column on browser_tasks\n\nBumps to 0.9.23.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "CRON: standard cron + variant verbs + per-cron token cost",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T15:08:05Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "734b34c40f12a3e360ba67c6dcb2b09eaf258086",
          "body": "User feedback: forget the multi-format menu. Have the agent translate\nEVERY natural-language date/time into one canonical\n[REMIND: YYYY-MM-DD HH:MM — text] form. Single format = no\nambiguity, no locale concerns, no parser surprises.\n\nPrompt-only change (parser unchanged — its multi-grammar support\ns\n[…]\nymbolic forms (@daily/@every/@weekly) —\nthey're abstract recurrences, can't be translated to a single\ntimestamp.\n\nBumps to 0.9.22.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "REMIND: force agent to emit single ISO canonical format",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T14:35:16Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b9900c91d00eafc66886d85ef4dbc5c2d34132ec",
          "body": "User reported reminders + crons not firing. Three compounding bugs:\n\n1. Agent was never told the [REMIND:]/[CRON:]/[SEND-TEXT:] tags\n   exist — so it never emitted them. Saying \"I'll remind you in 2h\"\n   in chat doesn't create a schedule.\n\n2. Parser only accepted \"in N{s|m|h|d}\" — user's \"at 10:30am\n[…]\nday if future\n- 10:30am in BA vs Sydney → unix times exactly 13h apart\n- Bad inputs rejected, bad markers logged\n\nBumps to 0.9.21.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix reminders/crons: per-user-tz, permissive grammar, agent doc",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T14:26:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "fb2ddb2b82ea04114a9715683ee7116dfabcd495",
          "body": "Closes a real UX gap: the estimator at ingest works for direct user\ninput (image-gen happy path) but agent-delegated async/browser tasks\nwere silent — no ETA visible to user unless the agent manually wrote\none inline.\n\nThree changes that compose to \"card-on-enqueue\":\n\n1. EstimationContext.taskKind: \n[…]\n240s → mean \"~3min\"\n- async-task → \"~3min\" default\n- card text format: \"🔄 browser task, ~3min\\n<truncated desc>\"\n\nBumps to 0.9.20.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Job cards: visible ETAs for [ASYNC:] / [ASYNC-BROWSER:] delegations",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T05:14:15Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "40bc00b31c6823170cd63838e19f7756fa6d59a9",
          "body": "CLI /goal mode (Claude Code / Codex) runs multi-hour sessions; the\n5min main spawn cap was killing them prematurely. Bumping caps\ngenerally — no per-message routing, no /goal detection logic.\n\nsrc/ai/spawn.ts TIMEOUT_MS:\n  main       5 min → 30 min   (chat track, covers /goal)\n  async     15 min → 6\n[…]\n-threading within one chat ever bites, the route-to-async\noption exists; not adding the complexity preemptively.\n\nBumps to 0.9.19.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Bump spawn timeouts + matching claim TTLs (/goal support)",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T04:51:21Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7f91835ed35c158b2809c2e2201cbf8df8fe44fe",
          "body": "Bug: user saw '15s · 14015k↑ (6566k cached) 22k↓ · ⚠ 7018% ctx'.\n14M tokens per turn is impossible against 200k window.\n\nRoot cause: bot assumed providers report per-turn usage (true for\nClaude CLI's `result.usage`). Codex's `turn.completed.usage` reports\nCUMULATIVE totals across the resume thread. \n[…]\n-recovery turn\nscenario. Bug-recovery turn shows 3290% (correctly hidden by clamp);\nnext turn would be accurate.\n\nBumps to 0.9.18.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Fix context% showing 7018%: per-turn delta + clamp",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T04:22:47Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "8c1521e8c646ce0c3276c32cd450f899233dc1f7",
          "body": "Adds a per-kind duration estimation system so the user gets honest\n\"in ~N min\" timelines at message receipt, based on past durations\nof the same kind. Built as a plugin architecture — each new kind is\na self-contained file that registers itself; outside code only\ntouches the registry.\n\nInterface (sr\n[…]\nfidence)\n- 5 with outlier  → \"generating image, anywhere from ~1s to ~3min\"\n- non-matching message → no estimate\n\nBumps to 0.9.17.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Job duration estimates: plugin interface + image-gen plugin",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T04:01:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3f21522d5e3ada9f36297dde32f233a374dff59e",
          "body": "Replaces the in-memory fastq browser lane with a SQLite-backed\nbrowser_tasks table. Tasks now survive process crashes; orchestrator\nreclaims stuck rows via TTL.\n\nSchema:\n- browser_tasks (id, address, actor_person_id, description,\n  originating_message, sender_number/name, allowed_tools JSON,\n  statu\n[…]\n-memory fastq is the GENERAL async lane (non-\nbrowser [ASYNC:] tasks). Same migration pattern applies; deferred.\n\nBumps to 0.9.16.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 4: durable browser ticket queue",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T02:56:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e57e7c819eabf5ed66c82fcd8cd3a04c0463194f",
          "body": "The chat-track agent can now schedule recurring or one-shot future\nsends back to the originating chat.\n\nTag grammar:\n- [CRON: @every 1h — body]           (or @daily HH:MM, @weekly DOW HH:MM)\n- [REMIND: in 30m — body]            (or in Ns / Nm / Nh / Nd)\n\nBoth fire into outbound at the scheduled time\n[…]\nectly strips for guest, REMIND row\nenqueued with past firstRunAt → orchestrator fires it → outbound row\nappears.\n\nBumps to 0.9.15.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "[CRON:] + [REMIND:] agent tags",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T02:47:06Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "0b4ada94ddcb756dea5a660c988075fee03be3ba",
          "body": "Two small commits worth of deferred work, bundled because they're\nboth regression closures from the Phase 4 swap:\n\n1. memory/scheduler.ts: sweep migrated to cron entry. Last\n   application-level setInterval gone. Same cadence\n   (config.memory.sweepIntervalMs), same body; orchestrator drives\n   it v\n[…]\negression introduced by Phase 4's\n   chat worker pool. Behavior is back to roughly pre-refactor for\n   WhatsApp.\n\nBumps to 0.9.14.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Close remaining deferred items: sweep cron + typing indicator",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T02:32:44Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "282f9132ee41f20b3e29dc111fbce410f741145a",
          "body": "Reframed from refactor.md's \"always-async on images\" — Phase 4's\nparallel chat workers made the original premise (chat lane is the\nbottleneck) obsolete. Per-chat reply ordering is the right\ninvariant; rerouting images through the async lane would break it.\n\nThe real UX gap is the typing-indicator re\n[…]\nBaileys\nretransmits.\n\nLong-term proper fix: ChannelAdapter.sendTyping() — separate small\ncommit.\n\nBumps to 0.9.13. Closes Phase 3.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 3: immediate ack on media-bearing messages",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T02:27:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "892c07921025fa37aa24836d5c7c26ab873387ec",
          "body": "Closes the last single-concurrency lane. browserQueue concurrency\nbumped from 1 → 3 (config.browser.maxWorkers). Multiple browser\ntasks now run in parallel on the shared Chrome, each driving its\nown tab.\n\nPersistent agent session dropped. Every browser task is a fresh\nagent run with the chat-track a\n[…]\nwas refactor.md's\ntarget; 3 is safer for shared rate-limited sites (IG/TT bans by IP).\n\nBumps to 0.9.12. Closes Phase 4 minimally.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 4: browser worker parallelism (minimal)",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T02:23:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "85cd2e72a9af0fe6d2f8ea2819052ecf2be4ebab",
          "body": "Adds an independent gate for what side-effect markers each role can\nemit. Existing tools allowlist stays unchanged (tools = what the AI\ncalls; tags = what bot-internal effects it triggers).\n\naccess.json schema gains optional `roles.<X>.tags` field:\n  - 'all' or omitted → no restriction\n  - ['DIGEST'\n[…]\n\nASYNC + SEND-TEXT markers: guest strips everything, user passes\nJOURNAL only, admin passes all.\n\nBumps to 0.9.11. Phase 6 closed.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 6: per-role tag permission gate",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T02:16:13Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "034915dd03470a92e7d51f2ba529f6c9bfea36c7",
          "body": "Closes the parallel-worker race window from Phase 4. With 5 chat\nworkers running concurrently, direct calls to appendEntry /\ncreateJournal / scheduleDigest could race on file edits (full-file\nrewrites in particular). Now all memory mutations flow through a\nqueue drained by one memory worker.\n\nSchema\n[…]\nuches agent tag set\n+ digest pipeline + needs backfill); deferred. Phase 5a alone\ncloses the race-condition gap.\n\nBumps to 0.9.10.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 5a: memory_writes queue + single memory worker",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T02:10:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "563f8eb5d2f52c00d0b26171512b2cf265564713",
          "body": "After Phase 4 the in-memory fastq queue (src/queue/queue.ts) and its\ndisk persistence layer (src/queue/persistence.ts) had no callers. The\ninbound table is now the source of truth — anything pending at restart\ngets claimed by the new chat worker pool automatically, no replay step\nneeded.\n\n- Deleted \n[…]\nersistence.ts.\n- Setup wizard no longer creates storage/queue/ (the disk-persist dir\n  the old fastq queue used).\n\nBumps to 0.9.9.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Cleanup: remove orphaned fastq queue + persistence",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T01:49:49Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f3db16737e68f09d2f3cf416ebe483a190b2fb4c",
          "body": "Shipped early (refactor.md says \"optional\") because Phase 4's\nparallel workers add enough moving parts that operators now need a\nway to ask the bot \"are you stuck?\" from chat.\n\nOutput (mobile-friendly format, ~10-15 lines):\n- queues: pending / in-flight / failed / dlq per table\n- workers: counts by \n[…]\nhrough 'sending' during\nthe adapter call. Fixed to match either, so stale sender activity now\nsurfaces correctly.\n\nBumps to 0.9.8.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 7: /queues chat command for queue introspection",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T01:47:45Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e23fa60a30d1e75fc0cfab1bb673019bb1c2947c",
          "body": "Hot-path swap. Incoming WA messages no longer push to an in-memory\nfastq queue with single-concurrency processing; they enqueue into the\ninbound SQLite table, and a pool of N chat workers (default 5) drains\nit with per-address serialization.\n\nConcurrency story: 5 chat workers handle up to 5 differen\n[…]\nn, claim\nsafety, idempotency all retested.\n\nCloses Phase 4 core. Browser pool + MCP pooling are a separate slice.\n\nBumps to 0.9.7.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 4: chat worker pool replaces in-memory fastq",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T01:41:31Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b5725eb73a5302ee20a4224ebe8d1593151b7200",
          "body": "Adds the inbound queue's schema and claim primitive. Nothing is\nrouted through it yet — that's the next slice. This commit alone is\nadditive and safe.\n\nSchema:\n- inbound (address, actor_address, person_id, actor_person_id,\n  external_msg_id, text, media_*, push_name, trigger_reason,\n  status, attemp\n[…]\nrrive in order.\nDetailed in refactor-scrap.md.\n\nBumps to 0.9.6. Next slice: chat worker pool + routing incoming\nthrough the table.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 4 (foundation): inbound table + per-address claim",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T01:26:56Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "caa4eb5c77fe6bbd2271220940b0b270b729f8ac",
          "body": "Adds the 'internal' cron target — an in-process handler registry for\nperiodic work that doesn't fit the queue→worker model. Payload shape:\n  { handler: <name> }\nDispatcher looks up name in src/queue/cron-handlers.ts, invokes the\nfunction. ~30 lines of registry; small surface, no new types.\n\nMigrates\n[…]\naining timers (sweep, prune, daily quota reset)\ndeferred — pattern is proven, each is mechanical.\n\nBumps to 0.9.5. Closes Phase 2.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 2: 'internal' cron target + nudge tick migration (proof)",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T01:20:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7e34a6ff5818302f4fe65bf5779f110152d96dec",
          "body": "Adds the schedule mechanism the refactor doc describes. Orchestrator\npolls the crons table each tick and fires due rows into their target\nqueue.\n\nSchema:\n- crons (name, enqueue_into, payload, recurrence, next_run_at,\n  last_run_at, enabled). Partial unique on name for recurring\n  schedules → upsert-\n[…]\nhot cron deleted after firing.\n\nBumps to 0.9.4. Next slice: migrate one existing setInterval to\nprove the pattern in the real bot.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 2: cron table + orchestrator polling",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T01:13:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "97b12bdfc593a97d34df0f0112b6d213db7725f9",
          "body": "Adds the bot-wide orchestrator: a polling loop (~500ms) that handles\ncross-cutting work no single worker should own. Phase 2 scope is\nnarrow:\n  - Read the control table → apply shutdown/pause signals.\n  - Reclaim stuck claims (reclaimStuckOutbound from Phase 1).\n  - Mark workers dead when last_seen \n[…]\nGINT').\n\nValidated end-to-end with a smoke test simulating busy/idle worker\ntransitions through a shutdown cycle.\n\nBumps to 0.9.3.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 2: orchestrator + control-table graceful shutdown",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T01:08:42Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "125a8f0e7f19f3004fa73cadaa76231a898f7353",
          "body": "Adds the only genuinely-new SEND-* tag from refactor.md: cross-chat\ntext send. Format:\n  [SEND-TEXT: address=wa:dm:5491234@s.whatsapp.net body=\"heads up\"]\n\nThe agent can now text a different chat than the one it's currently\nresponding in. Wired through the main chat worker AND both async\nlanes (gene\n[…]\n-* variants would create two ways to do the same thing → agent\nconfusion + drift. Rationale in refactor-scrap.md.\n\nBumps to 0.9.2.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 1: [SEND-TEXT] cross-chat send tag",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T01:02:09Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "7986a9514bfcb4853ec89c47e5bbbbc00437c550",
          "body": "Routes every reply through a durable queue instead of calling Baileys\ndirectly. AI workers (handleReply, initiate) now insert outbound rows\nand return immediately; the sender worker drains the queue and pushes\nto the matching ChannelAdapter.\n\nWhat ships:\n- outbound table (text + media + idempotency_\n[…]\nlow-up by caching\nrecent WAMessages by id in-memory.\n\nStill pending in Phase 1: SEND-* tag handlers (next slice).\n\nBumps to 0.9.1.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 1: outbound queue + sender worker + Baileys adapter",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T00:55:29Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1f75d731c8ebf7f78b4c8f11c6317d3b6fd49412",
          "body": "Derives DB rows from the existing access.json on every boot.\nIdempotent: first boot inserts, subsequent boots are no-ops unless\naccess.json was edited (in which case display_name updates land).\n\nDecision reversal from refactor.md: keep access.json's existing\nshape (richer than the doc described — ha\n[…]\nties\non first run, 0/0 on second. Still nothing reads these tables yet —\nthey're the foundation for inbound resolution in Phase 4.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 0: sync persons + identities from access.json",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T00:39:18Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f9a996ca27b167ae3030163bfb4309f065b7215f",
          "body": "Opens the heavy refactor described in refactor.md. Lands the\nfoundation without touching any existing flat-file storage:\n\n- drizzle-orm + drizzle-kit + better-sqlite3 added as deps\n- src/db/schema.ts: persons, identities, workers, control tables\n- drizzle.config.ts at repo root (drizzle-kit default)\n[…]\nritative until later phases\nswap them in. Phase 0 is zero-risk to ship.\n\nBumps to 0.9.0 (signals the refactor sequence has begun).\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Phase 0: drizzle + sqlite scaffolding (additive)",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T00:35:19Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "cf7565f8f8b73294adad5364b4f95dec210f875f",
          "body": "Working doc capturing the agreed direction from a long design\ndiscussion. Four primitives (queues, workers, tags, interfaces).\nIdentity model with Address + Person for multi-channel. Six queues\nbacked by SQLite. Observations log replaces the journal/profile/brief\nsplit. Drizzle for schema + migratio\n[…]\nss control stays file-based. Phased plan ~2 weeks.\n\nNot a spec — agreed direction + trade-offs to revisit before each\nphase ships.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add refactor.md — architecture for heyamigo as a job system",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-25T00:18:39Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "bfc0e146adec72edf4647ce31d08d73a615680ba",
          "body": "Empirically --yolo is the right flag: it skips approvals AND the\ntrust-directory gate. The narrower --dangerously-bypass-approvals-\nand-sandbox skips approvals only, so the process sits hanging on the\ntrust prompt waiting for stdin instead of failing fast.\n\nStdin piping (kept from 0.8.14) is still correct for prompt size,\nand the info-level argv log stays so future flag drift is visible\nnot silent.\n\nBumps to 0.8.15.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Codex: revert to --yolo (bundles trust-check bypass)",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-24T17:19:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c927c79abe74928385e9569ea00a8a7ff72d7fdc",
          "body": "The previous turn went silent — message captured, no spawn logs, no\nerror. The likely cause: prompt was being shoved into argv as a\npositional argument. System prompt + memory preamble + history can\npush past Linux's ARG_MAX, causing the exec to hang.\n\nFix: pass `-` as the positional (the documented\n[…]\nAlso promotes the spawn log to info level with the full argv so\nhangs/failures are debuggable instead of silent.\n\nBumps to 0.8.14.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Codex: pipe prompt via stdin + log argv",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-24T17:16:07Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "5369587a52d99513980ec2a5c02f801526c2e5cb",
          "body": "Pulled `codex exec --help` instead of guessing. Two changes:\n\n1. Switch from --yolo (alias only in some builds) to the documented\n   --dangerously-bypass-approvals-and-sandbox. Portable across all\n   versions that support the behavior.\n\n2. Add config.codex.model. When set, emits `-m <model>` so user\n[…]\nx, --skip-git-repo-check, --json, and the `resume` subcommand\nare all spelled exactly as we use them in 0.133.0.\n\nBumps to 0.8.13.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Codex: use canonical bypass flag + add model knob",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-24T17:12:04Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f522b1675813b57ede99c779fb164f9ecd7e842e",
          "body": "Observed live output from the installed CLI:\n  thread.started → thread_id (sessionId)\n  item.completed with item.type='agent_message' → item.text (reply)\n  turn.completed → usage block\n\nThe previous parser looked for msg.message / top-level message|text,\nwhich was wrong nesting, so every successful Codex run was failing the\nparse step. Older shapes kept as fallbacks.\n\nBumps to 0.8.12.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Codex: match real --json event shapes",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-24T17:08:28Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b7ac212c6f087211ac4ec787e5e7e7e8ef64e1e7",
          "body": "Adds typed config knobs for Codex CLI flags so users can pick their\nown posture without editing source:\n  - yolo (default true): pass --yolo, which bundles no-approvals +\n    full sandbox + skip-trust-check. Right default for an owner-bot\n    and fixes the \"Not inside a trusted directory\" failure.\n \n[…]\nepoCheck (default true): used when yolo=false.\n  - extraArgs: appended verbatim, escape hatch for version drift.\n\nBumps to 0.8.11.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Codex: config.codex block with --yolo default",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-24T17:03:11Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2c9a08230a24528114f86fffe08abb33249236a0",
          "body": "Sessions are now keyed by (jid, provider) so swapping ai.provider\ndoesn't feed Claude session ids to Codex (or vice versa). Old\nsessions.json entries auto-migrate as claude sessions on read.\nBrowser worker's persistent session moves to\nbrowser-session-<provider>.json with one-time migration of the\nl\n[…]\nume is a subcommand\nof `codex exec`, not a `--resume` flag. Layout now:\n  codex exec [opts] resume <id> [prompt]\n\nBumps to 0.8.10.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Per-provider session storage + codex resume subcommand",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-24T16:51:54Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "ed22541bb895d4dc11f93f1fed7d37319c0fef58",
          "body": "Installed Codex CLI rejects --sandbox-mode; the actual flag is\n--sandbox. Found on first real run.\n\nBumps to 0.8.9.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Codex: --sandbox-mode → --sandbox",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-24T16:41:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "068dd41de9667908f0e71f6a1fc7d91061343000",
          "body": "Mirrors the schema field added in 084a54b so new installs see the\nprovider switch in their generated config.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add ai.provider to example config",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-24T15:17:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "084a54bd8aa47eeb4c34af6ce355e23885133466",
          "body": "Adds AiProvider abstraction (ask + runTask) so the worker, memory\npipelines (digest, observer, nudger, compressed), and async task lanes\nall route through a swappable backend selected by ai.provider in config.\nClaude provider preserves existing behavior; Codex provider implemented\nagainst codex exec\n[…]\nlso\nmirrors the Playwright MCP entry into ~/.codex/config.toml so the\nbrowser lane works on Codex out of the box.\n\nBumps to 0.8.8.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Provider interface: Claude + Codex CLI backends",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-24T15:01:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "185dcf815a94b1d0b7ef612e573eb351af101d6f",
          "body": "access.json role overrides used to replace the whole role object,\nsilently wiping any field the user hadn't explicitly set. That meant new\nfields added in code (maxFileBytes, dailyTokenLimit) were null for every\nexisting install — file/token caps weren't being enforced for anyone\nwhose access.json defined the role at all.\n\nNow overrides are per-field: omitted fields fall through to DEFAULT_ROLES.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Per-field merge for role overrides",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-21T23:03:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9c34157b8988317eac163872a3b4db1745d22b34",
          "body": "The pre-download check silently skipped whenever protobuf fileLength was\nmissing or nested (documentWithCaptionMessage, some stickers/forwards),\nwhich let oversize files through to Claude. Now we also re-check against\nthe real buffer size after download — if over the cap, unlink the file,\nstore the message without media metadata, and reply with a generic\n\"Could not process that, please try a smaller file.\"\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "File-size gate: post-download safety net + softer error copy",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-21T22:14:22Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5cba0e49a0b02038a6024c5692dcf8f6fed7b425",
          "body": "Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "0.8.5",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-21T15:59:02Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "42c7877e0b46c3669302e7c285db79678a1f0041",
          "body": "Adds two optional role fields (maxFileBytes, dailyTokenLimit) so the\nowner's Claude budget can't be drained by any single chatter. Owner is\nalways unlimited regardless of role. Oversized files get a clear reply;\ndaily-cap hits are silently dropped (still stored) to avoid nagging.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Per-role limits: 1MB file cap + daily token cap per user",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-05-21T15:20:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "82cf6649c98d0081f9d71ec1ff9bd5831738ddb6",
          "body": "Browser task from tonight's successful Pinterest scrape returned:\n  \"Here are two McQueen shots...\n   [FILE: storage/outbox/ref1_mcqueen_tee.jpg]\n   [FILE: storage/outbox/ref2_mcqueen_knit.jpg]\"\n\nThe file tags leaked into WhatsApp as literal text instead of\nattaching the images. Cause: initiate() in\n[…]\n mentions of storage/temp/ → storage/outbox/\n  (matches what setup.ts actually creates)\n- preamble.ts Capabilities: clarified outbox (send, auto-deletes) vs\n  temp (scratch, not sent)\n\nBumps to 0.8.4.",
          "is_bot": false,
          "headline": "initiate(): extract file tags so async/browser can send media",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-20T00:49:21Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f829709d150323d9c76fcc1149c3acb58d298b40",
          "body": "Baileys' extensionForMediaMessage throws when the underlying media has\nno mimetype field. Happens on forwarded PDFs (and other documents)\nwhere the original metadata was stripped along the way. The exception\nwas caught at the outer try/catch, but the whole media save was\nabandoned — the PDF never la\n[…]\nget a filename.\n\nThe downloadMediaMessage call itself had already succeeded before the\ncrash — we had the buffer. Now we save it with a sensible extension\ninstead of throwing it away.\n\nBumps to 0.8.3.",
          "is_bot": false,
          "headline": "Fix: don't crash media download when mimetype is undefined",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T22:15:54Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c74832807794cc9157edf424e15cc5a5c523878e",
          "body": "Claude CLI rejects -p + --output-format stream-json without --verbose:\n\"When using --print, --output-format=stream-json requires --verbose\"\n\nv0.8.1 shipped stream-json without the flag; every spawn failed with\nexit code 1, bot was fully broken.\n\nAdded --verbose to 7 sites (all stream-json callers):\n\n[…]\noduces expected NDJSON stream ending in a type:result event.\nExisting parseStreamJson already handles this shape correctly.\n\nImporter still uses --output-format json; no change there.\n\nBumps to 0.8.2.",
          "is_bot": false,
          "headline": "Fix: add --verbose to all stream-json spawns (required by Claude CLI)",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T18:31:05Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f8e8162bb5674ed69669449c481e8df43f540ae6",
          "body": "…ptlog\n\nNo more blind spots. Three changes for full diagnostic visibility into\nwhat Claude subprocesses are actually doing.\n\n1. ANTHROPIC_LOG=debug env on every spawn (src/ai/spawn.ts).\n   Claude SDK internals log HTTP request/response traffic, retry\n   backoffs, status codes, rate-limit notices to \n[…]\no see\n  the last tool_use before the turn hung.\n- \"Was the hang an API issue or a Playwright issue?\" → stderr shows\n  API traffic; MCP logs show browser traffic; correlate timestamps.\n\nBumps to 0.8.1.",
          "is_bot": false,
          "headline": "Instrumentation: ANTHROPIC_LOG=debug + stream-json + size-capped prom…",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T16:56:38Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2d1c3f2931fc130ae53bd04034f25e00bec2348f",
          "body": "Major architectural shift. Instead of one-shot async spawns per browser\ntask, introduces a dedicated BROWSER TRACK with a persistent Claude\nsession that accumulates memory across browser tasks.\n\nThe two tracks:\n  - Chat track (per-JID sessions, unchanged): talks to you in WhatsApp\n  - Browser track \n[…]\ng memory and communicating through markers.\nBrowser tasks queue one-at-a-time against a persistent session. No\nqueue-jams, session continuity across tasks, natural chat/browser split.\n\nBumps to 0.8.0.",
          "is_bot": false,
          "headline": "Two-track architecture: chat Claude + persistent browser Claude",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T16:20:37Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b490a411ccc89a49419a8214c099a319d07e0363",
          "body": "Previous commit (0.7.4) suppressed long chat output when markers fired,\non the theory that findings belonged in journal files rather than chat.\nWrong default for the common case — \"claude check my IG\" expects the\nactual answer back in chat, not silent writes to a journal the user\ndidn't ask to popul\n[…]\nence, not a substitute for the reply\n- Failure mode: short clean text explaining what went wrong, no fake\n  findings\n- Example now shows both chat reply AND journal markers coexisting\n\nBumps to 0.7.5.",
          "is_bot": false,
          "headline": "Async: chat reply is primary, markers are parallel persistence",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T14:29:08Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "63fb596e82d89063ee85231bbbb1d28dce17fdff",
          "body": "Async tasks are data-generators — like the digester and observer, they\nshould land findings in structured memory files, not as chat replies.\nToday the async worker ended its turn by calling initiate() with the\nfull result as a WhatsApp message. That:\n- Dumps long scrape results into chat (noisy, esp\n[…]\nude check @rivoara_official\" when auth is broken → async worker\n  hits login wall, outputs short failure text (no markers) → that\n  text IS sent to chat so the owner sees the problem.\n\nBumps to 0.7.4.",
          "is_bot": false,
          "headline": "Async worker: route output via markers, stop chat-dumping",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T14:19:04Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "165a4b7aa3765494b9ab9ca9a3f4135b151b990b",
          "body": "The old regex /\\[(DIGEST|JOURNAL|JOURNAL-NEW|ASYNC):\\s*([^\\]]+)\\]\\s*$/i\nterminates at the first inner `]`, so any marker payload containing\nnested square brackets breaks. This bit us twice today:\n\n1. ~morning: a [DIGEST:...] payload contained [JOURNAL:slug, note]\n   with a literal `]` inside. Regex \n[…]\njects unknown kinds ([FAKE: ...] left in clean text)\n\nNo API changes. extractFlags / extractDigestFlag return the same\nFlagResult / LegacyFlagResult shape. All 6 call sites unchanged.\n\nBumps to 0.7.3.",
          "is_bot": false,
          "headline": "Marker extractor: parse by bracket-depth instead of regex",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T12:28:19Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "a39f5c342a9136d2afd59ad54b580e34e261cad9",
          "body": "The bot diagnosed today's root cause while I was pushing disallowedTools:\nthe preamble itself was contradicting the memory-instructions ASYNC rule.\n\nBefore:\n  - memory-instructions.md: \"ANY browser tool use goes through async. Never\n    inline.\"\n  - preamble Capabilities section: \"Use the browser to\n[…]\ne will actually see it.\n\nCredit to the bot (Claude running on the server) for the diagnosis —\nspotted the preamble contradiction I had missed across three rounds of\nprompt tightening.\n\nBumps to 0.7.2.",
          "is_bot": false,
          "headline": "Preamble: resolve ASYNC contradiction — browser always goes async",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T04:47:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e3f787a863e327e90c2eb9e269bf0d3a85bf4de1",
          "body": "Real-world evidence: with the current rules, Claude goes inline on every\nbrowser request and blocks the chat queue. The \"single quick URL fetch\"\nexception clause gave Claude permission to rationalize inline use even\nfor Instagram/TikTok pages that routinely stall for minutes.\n\nChanges:\n- Removed the\n[…]\n (pending user call): disallowedTools\ninfrastructure enforcement. Prompt-only for now. If Claude still\nrationalizes its way past this wording, infra enforcement becomes the\nnext step.\n\nBumps to 0.7.1.",
          "is_bot": false,
          "headline": "Memory-instructions: browser is ALWAYS async, no exceptions",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T04:31:13Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "45cf0b3ddd8416314587637ca95cf11015b30669",
          "body": "Today a Playwright-MCP hang jammed the group-chat queue for 16 minutes\n(Chromium never finished responding, tool response never came back to\nClaude, Claude looped in ep_poll forever, typingHeartbeat kept firing,\nevery subsequent message in that chat stacked up behind the stuck turn).\nOnly way out wa\n[…]\nllowedTools in main lane or ingress heuristic routing to async)\n  - /cancel command for manual pre-timeout kill\n  - Playwright-MCP-level navigation timeouts (MCP config, not our code)\n\nBumps to 0.7.0.",
          "is_bot": false,
          "headline": "Hard timeouts on every claude subprocess + defense-in-depth cleanup",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T02:45:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "cc4c84af96e5dd4f1e91b13d9d1c7c29da65f49c",
          "body": "Every chat reply now gets a tiny italicized stats line appended just\nbefore sending via WhatsApp. Send-only — never stored in the message\nlog, never in recent-context, never in digest input. Pure feedback\nchannel for the owner.\n\nDefault (boring reply):\n  _3.2s · 180↑ 40↓_\n\nInteresting reply (heavy, \n[…]\n itself — the system does it.\n\nNot applied to proactive nudges (those should feel native) or to\nasync-task results yet (straightforward follow-up; deferred to keep\nthis change small).\n\nBumps to 0.6.1.",
          "is_bot": false,
          "headline": "Reply footer: adaptive stats appended at send time only",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T01:46:48Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8922f4542fa13af98c4aff6ba55d12b3e1c9e9e3",
          "body": "Adds a rolling \"state of the world\" index that sits at the top of every\nsession's preamble. Across every chat, every session, every /reset —\nClaude starts with the same cheat sheet of who exists, what norms apply,\nwhat projects are active, and what journals are in flight (with their\nlast entries ver\n[…]\nt compressed views (global is simpler), recency\nweighting inside the generator (current prompt does it implicitly via\n\"current state\"). All deferrable until real usage shows the need.\n\nBumps to 0.6.0.",
          "is_bot": false,
          "headline": "Compressed memory: rolling state index across sessions",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T01:36:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "272cc6fa127342413c6a0ef6588da0e2474dcc46",
          "body": "Principle shift: the owner does not run /journal, /snooze, /tasks. They\nask Claude in natural language. Claude acts via markers or by editing\nmemory files directly. Every slash command is context surface area the\nowner has to learn and remember - all of that moves into Claude's head.\n\nWhat goes away\n[…]\nrealistic examples, no fluff. This file is the spec\nClaude loads into its system prompt - every section earns its place.\n\nBumps to 0.5.0. Breaking change for anyone who was using the removed\ncommands.",
          "is_bot": false,
          "headline": "Strip feature-level commands: Claude is the only interface",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T01:18:12Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "8ed3c6ca7a900ca9b2c9fcaefdfe15866e33ce6a",
          "body": "The chat queue is serialized per-chat, so a single browser-using turn\n(scraping, multi-step research) blocks every subsequent message in that\nchat until it finishes. This introduces a separate async queue so Claude\ncan delegate long work and keep chatting.\n\nFlow:\n1. Claude decides the request needs \n[…]\nPer-chat concurrency cap. One chat can currently fill all 3 slots.\n- Cancel command. You have to wait or restart the bot.\n- Progress updates mid-task. One ack, one result, no polling.\n\nBumps to 0.4.0.",
          "is_bot": false,
          "headline": "Async work lane: long tasks run in background, chat stays responsive",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T01:05:09Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "e368d1180e829b59e54640d03e911a2f581c643a",
          "body": "The bot can now create and manage journals itself, and can proactively\nmessage the owner when check-ins or silent-nudges are due.\n\nBot-side lifecycle markers (in addition to the existing [JOURNAL:slug - note]\nentry tag), peeled off the reply tail by the worker:\n- [JOURNAL-NEW:<slug> - <purpose>]\n- [\n[…]\ner use):\n- Critique pass over composed nudges\n- Engagement tracking / adaptive timing\n- Cadence-setting via marker\n- Follow-up-after semantics (frontmatter field parsed but not wired)\n\nBumps to 0.3.0.",
          "is_bot": false,
          "headline": "Journals: bot self-service creation + proactive nudges",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T00:34:17Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b7aeddc5f14bca82d424ab66931b4c1a4f227aa8",
          "body": "Long-running tracking projects the owner sets up (health journal, dog\ntraining log, etc.). Owner-scoped, global across all chats/sessions.\n\nStorage:\n- storage/memory/journals/<slug>/index.md (frontmatter + body)\n- storage/memory/journals/<slug>/entries.jsonl (append-only log)\n\nReactive capture:\n- Me\n[…]\n):\n- /journal list\n- /journal create <slug> <purpose>\n- /journal show <slug>\n- /journal entries <slug> [n]\n- /journal pause|resume|archive <slug>\n\nBumps to 0.2.0 (first minor of the journals feature).",
          "is_bot": false,
          "headline": "Journals: reactive capture + observer sweep + slash commands",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-18T00:28:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "0907a62742e9fa6c5d48d8e7703d190df34e7b87",
          "body": "Reads version from package.json at runtime via import.meta.url. The old\nstring literal in src/cli/index.ts was never updated on version bumps,\nso \\`heyamigo -V\\` always printed 0.1.0 regardless of the installed\nversion.\n\nBumps to 0.1.18.",
          "is_bot": false,
          "headline": "Fix: CLI -V flag reports hardcoded 0.1.0 instead of package version",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-17T23:57:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "6dbb6f51191809866051ee177a4a7b7a72cc9f6a",
          "body": "Adds a \"Don't people-please\" section covering validation openers, honest\ndisagreement, position-holding under pressure, no reflexive flattery or\nsilver linings. Adds explicit rules that uncomfortable truths are part of\nthe job and that truth beats moralizing (no lecturing or moral caveats\nin place of a straight answer). Two new self-check items reinforce it.\n\nBumps version to 0.1.17.",
          "is_bot": false,
          "headline": "Sharp personality: less people-pleasing, truth > moralizing",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-17T23:54:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8a2732a4d7e39faa92e89be012c853fdbf82fcab",
          "body": "Unsolicited messages (future journal nudges, observer check-ins, any other\nproactive path) must be gated per recipient. Added proactive:boolean\n(default false) to access.json group and DM entries, plus a\ncanSendProactive(jid) helper. Default is deny — explicit opt-in only.\n\nBumps version to 0.1.16.",
          "is_bot": false,
          "headline": "Proactive-send guardrail: default-deny per-chat opt-in",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-17T23:44:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4b07ac18780d66a9c27078836e7959b306e3f400",
          "body": "- Model: claude-opus-4-6 -> claude-opus-4-7\n- Ongoing sessions now include last N prior messages as recent context,\n  so forgotten-mention messages still get picked up (bootstrap.recentContextDepth, default 3)\n- Preamble: new [Time] section anchored to owner.timezone so Claude\n  stops guessing date/time\n- Preamble: [Character] marked highest-priority and override-resistant\n  against CRITICAL rules for tone/voice",
          "is_bot": false,
          "headline": "Bump to Opus 4.7; add recent-context, timezone, character reinforcement",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-17T23:39:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "d92949b34c2da29b75e150b869c7d59286289173",
          "body": "Detects self-chat (owner's own JID) and responds to every message\nwithout needing alias mention. Also saves files to storage/temp/.\n\nCo-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Self-chat support: owner can DM the bot via \"Message yourself\"",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-08T21:58:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "709455e0bfb594338040dd771e0ba5d32e6ae9ea",
          "body": null,
          "is_bot": false,
          "headline": "added self messaging",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-08T21:44:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e998373a9c880165310129b8a80baeeca7561c16",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Tell Claude to save files to storage/temp/, not project root",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-08T13:35:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "26e95826d0c3f2e9f8c127ee84b335a0fd64a4e9",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Sharp personality: fight back when attacked, hold ground",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-07T12:19:31Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1d9f64075d8287f2821247e3ce3d476cf0acea35",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Stronger character reminder: read personality, align every answer",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-07T12:18:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "01b59e4ded2d9554a1708d28bbed2df65bc07c82",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Add character reminder to preamble pointing to personality file",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-07T12:13:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c6f83a7ae79a0a948716ae375e1981bdc5b4d6ee",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "README: npx install as primary quick start path",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-06T23:35:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dad9e6fa041c7ba9b69fbcbf71142bebc9d54945",
          "body": "Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "Link personality files in README",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-06T20:21:59Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "dc287195d5a7de7136df9a8d38d9f1c57c700929",
          "body": null,
          "is_bot": false,
          "headline": "Initial commit",
          "author_name": "Catalin Waack",
          "author_login": "C4T4",
          "committed_at": "2026-04-06T20:16:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 10,
      "commits_last_year": 94,
      "latest_release_at": "2026-05-25T21:59:34Z",
      "latest_release_tag": "v0.10.4",
      "releases_from_tags": true,
      "days_since_last_push": 5,
      "active_weeks_last_year": 9,
      "days_since_latest_release": 60,
      "mean_days_between_releases": 5.5
    },
    "community": {
      "has_readme": true,
      "has_license": true,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "@c4t4/heyamigo",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "whatsapp",
            "telegram",
            "chatbot",
            "claude",
            "ai",
            "baileys",
            "bot",
            "anthropic"
          ],
          "ecosystem": "npm",
          "matches_repo": true,
          "registry_url": "https://www.npmjs.com/package/@c4t4/heyamigo",
          "is_deprecated": false,
          "latest_version": "0.12.6",
          "repository_url": "https://github.com/C4T4/heyamigo",
          "versions_count": 85,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": 1,
          "monthly_downloads": 2186,
          "first_published_at": "2026-04-06T17:36:38.325000Z",
          "latest_published_at": "2026-07-19T20:07:08.196000Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 5
        }
      ]
    },
    "popularity": {
      "forks": 0,
      "stars": 4,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "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": 37001,
      "source_files_sampled": 89,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [
        "package.json"
      ],
      "advisories": {
        "error": null,
        "scope": "published_package",
        "source": "osv",
        "findings": [
          {
            "name": "baileys",
            "direct": true,
            "version": "7.0.0-rc.9",
            "severity": "critical",
            "ecosystem": "npm",
            "cvss_score": 9.1,
            "advisory_ids": [
              "GHSA-qvv5-jq5g-4cgg"
            ],
            "fixed_version": "7.0.0-rc12",
            "advisory_count": 1,
            "oldest_advisory_days": 44
          }
        ],
        "collected": true,
        "malicious": [],
        "truncated": false,
        "by_severity": {
          "critical": 1
        },
        "advisory_count": 1,
        "affected_count": 1,
        "assessed_count": 141,
        "malicious_count": 0,
        "assessed_package": "npm:@c4t4/heyamigo@0.12.6",
        "unassessed_count": 0,
        "direct_affected_count": 1
      },
      "ecosystems": [
        "npm"
      ],
      "dependencies": [
        {
          "name": "@clack/prompts",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.2.0"
        },
        {
          "name": "@hapi/boom",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.0.1"
        },
        {
          "name": "baileys",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "7.0.0-rc.9"
        },
        {
          "name": "better-sqlite3",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^12.10.0"
        },
        {
          "name": "commander",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^14.0.3"
        },
        {
          "name": "croner",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^10.0.1"
        },
        {
          "name": "drizzle-orm",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^0.45.2"
        },
        {
          "name": "fastq",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.17.1"
        },
        {
          "name": "pino",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^9.3.2"
        },
        {
          "name": "qrcode",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^1.5.4"
        },
        {
          "name": "zod",
          "manifest": "package.json",
          "ecosystem": "npm",
          "version_constraint": "^3.23.8"
        }
      ],
      "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": 0,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "C4T4",
          "commits": 94,
          "avatar_url": "https://avatars.githubusercontent.com/u/12415654?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": false,
      "ci_workflows": [
        "publish.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "package-lock.json"
      ],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 3 contributing companies or organizations -- score normalized to 10",
            "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 0 issue activity found in the last 90 days -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": 10,
            "reason": "packaging workflow detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 10,
            "reason": "GitHub workflow tokens follow principle of least privilege",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 0,
            "reason": "18 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "72ce2e770a4217ae9bac59f794c2b5a82f86b454",
        "ran_at": "2026-07-25T19:13:32Z",
        "aggregate_score": 4.5,
        "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-19T20:07:12Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": null,
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/C4T4/heyamigo",
    "host": "github.com",
    "name": "heyamigo",
    "owner": "C4T4"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 52,
      "inputs": {
        "security": 51,
        "vitality": 77,
        "community": 35,
        "governance": 39,
        "engineering": 58
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "good",
        "name": "Vitality",
        "value": 77,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 70,
            "inputs": {
              "commits_last_year": 94,
              "human_commit_share": 1,
              "days_since_last_push": 5,
              "active_weeks_last_year": 9
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 5 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "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": "94 commits in the last year",
                "points": 17.8,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 94
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 88,
            "inputs": {
              "releases_count": 10,
              "latest_release_tag": "v0.10.4",
              "releases_from_tags": true,
              "days_since_latest_release": 60,
              "mean_days_between_releases": 5.5
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "10 version tags (no GitHub releases)",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "version_tags_no_releases",
                    "params": {
                      "count": 10
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 60 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 60
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~5.5 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 5.5
                    }
                  }
                ],
                "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": 35,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 8,
            "inputs": {
              "forks": 0,
              "stars": 4,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "4 stars",
                "points": 7.7,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 4
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "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": [
                "@c4t4/heyamigo"
              ],
              "dependents": null,
              "ecosystems": "npm",
              "total_downloads": null,
              "monthly_downloads": 2186
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "2,186 downloads/month across npm",
                "points": 44.5,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 2186,
                      "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": "at_risk",
        "name": "Sustainability & Governance",
        "value": 39,
        "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 3 contributing companies or organizations -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution, PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution",
                    "pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "merged_prs": 0,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "no decided pull requests or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_decided_prs_or_data",
                    "params": {}
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "moderate",
            "name": "Ownership & stewardship",
            "note": "Excluded from scoring (no data or not applicable): Verified domain. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "verified_domain"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 50,
            "inputs": {
              "followers": 16,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "C4T4",
              "public_repos": 15,
              "account_age_days": 4092
            },
            "components": [
              {
                "key": "ownership_backing",
                "name": "Ownership backing",
                "detail": "personal (user) account",
                "points": 10,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_personal",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "verified_domain",
                "name": "Verified domain",
                "detail": "not applicable to user accounts",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "not_applicable_to_user_accounts",
                    "params": {}
                  }
                ],
                "max_points": 20
              },
              {
                "key": "owner_reach",
                "name": "Owner reach",
                "detail": "16 followers of C4T4",
                "points": 8.8,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 16,
                      "login": "C4T4"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "15 public repos, account ~11 yr old",
                "points": 20.8,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 15
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 11
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "@c4t4/heyamigo"
              ],
              "ecosystems": "npm",
              "any_deprecated": false,
              "min_days_since_publish": 5
            },
            "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 5 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 5
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "85 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 85
                    }
                  }
                ],
                "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": 58,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "at_risk",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 30,
            "inputs": {
              "has_ci": true,
              "has_tests": false,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "1 workflow(s)",
                "points": 24,
                "status": "met",
                "details": [
                  {
                    "code": "ci_workflows",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 24
              },
              {
                "key": "tests_present",
                "name": "Tests present",
                "detail": null,
                "points": 0,
                "status": "missed",
                "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": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "topics": [
                "claude-code",
                "openclaw",
                "whatsapp-bot"
              ],
              "has_wiki": true,
              "homepage": "https://heyamigo.org",
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": "https://heyamigo.org",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "3 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 3
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "moderate",
        "name": "Security",
        "value": 51,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 45,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 4.5
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 3 contributing companies or organizations -- score normalized to 10",
                "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 0 issue activity found in the last 90 days -- score normalized to 10",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow detected",
                "points": 5,
                "status": "met",
                "details": [],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "GitHub workflow tokens follow principle of least privilege",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "18 existing vulnerabilities detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "dependency_advisories",
            "band": "good",
            "name": "Dependency advisories",
            "note": "Matched the npm:@c4t4/heyamigo@0.12.6 runtime dependency closure — what installing the published package pulls in — 141 packages. Reachability is not analyzed.",
            "notes": [
              {
                "code": "advisories_scope_published",
                "params": {
                  "package": "npm:@c4t4/heyamigo@0.12.6",
                  "assessed": 141
                }
              },
              {
                "code": "advisories_reachability",
                "params": {}
              }
            ],
            "value": 74,
            "inputs": {
              "source": "osv",
              "advisories": 1,
              "affected_packages": 1,
              "assessed_packages": 141,
              "unassessed_packages": 0,
              "affected_by_severity": "critical 1",
              "direct_affected_packages": 1
            },
            "components": [
              {
                "key": "direct_dependencies_free_of_known_advisories",
                "name": "Direct dependencies free of known advisories",
                "detail": "1 affected: baileys 7.0.0-rc.9 (critical 9.1)",
                "points": 9.5,
                "status": "partial",
                "details": [
                  {
                    "code": "advisories_affected",
                    "params": {
                      "count": 1,
                      "packages": "baileys 7.0.0-rc.9 (critical 9.1)"
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "indirect_dependencies_free_of_known_advisories",
                "name": "Indirect dependencies free of known advisories",
                "detail": "no indirect dependency carries a known advisory",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "no_indirect_advisories",
                    "params": {}
                  }
                ],
                "max_points": 25
              },
              {
                "key": "no_advisories_left_outstanding",
                "name": "No advisories left outstanding",
                "detail": "no advisory 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": 141,
              "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": 3
            },
            "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": "at_risk",
        "name": "AI Readiness",
        "value": 45,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 37,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.702,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "66 of 94 human commits state their intent (structured subject or explanatory body)",
                "points": 37.4,
                "status": "partial",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 66,
                      "sampled": 94
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 31,
            "inputs": {
              "has_nix": false,
              "has_tests": false,
              "lockfiles": [
                "package-lock.json"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [
                "tsconfig.json"
              ],
              "agent_commit_share": 0.543,
              "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": 0,
                "status": "missed",
                "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": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "51 of the last 94 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 51,
                      "sampled": 94
                    }
                  }
                ],
                "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": 37001,
              "source_files_sampled": 89,
              "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/89 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 89,
                      "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-25T19:13:37.731049Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/c/C4T4/heyamigo.svg",
  "full_name": "C4T4/heyamigo",
  "license_state": "standard",
  "license_spdx": "MIT"
}

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

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

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