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

koriym / xdebug-mcp

Enable AI to debug PHP with Xdebug

PHP未检测到许可证★ 53 星标⑂ 9 复刻始于 2025年8月在 GitHub 上查看 ↗

koriym/xdebug-mcp 的健康指数为 100 分中的 68 分,处于「中等」区间。 其得分最高的类别是Vitality(90/100),最低的是Community & Adoption(42/100)。 最近一次更新在今天。 近期的大部分工作由 1 位贡献者完成。

68
总分 / 100
中等

软件健康指数

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

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

评分画像

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

所有权

Akihito Koriyama个人账户
261 关注者255 个公开仓库始于 2010年12月

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

软件包生态系统

注册表软件包版本月下载量版本数最近发布标签
Packagistkoriym/xdebug-mcpv0.11.14,5811924 天前phpdebuggingxdebugtraceprofilingaimcp

按类别列示的指标

活力

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

90优秀 · 占总体的 22%
评分方式
36/36推送新近度 — 最近一次推送于 0 天前
20.1/36提交节奏 — 52 周中有 29 周有提交
18/18提交量 — 最近一年 1,181 次提交
10/10OpenSSF Scorecard:Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
所用输入
commits_last_year1,181
human_commit_share1
days_since_last_push0
active_weeks_last_year29

发布纪律

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

社区与采用

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

42存在风险 · 占总体的 18%

流行度与采用

35存在风险
评分方式
27.8/60星标 — 53 个星标
7.5/25复刻 — 9 个复刻
0/15关注者 — 1 位关注者
所用输入
forks9
stars53
watchers1
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history

社区健康

45存在风险
评分方式
22.5/22.5README
0/22.5许可证 — 未检测到许可证文件
18/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
评分方式
48.8/80月度下载量 — packagist 合计每月 4,581 次下载
2/20注册表被依赖数 — 1 个软件包依赖它
所用输入
packageskoriym/xdebug-mcp
dependents1
ecosystemspackagist
total_downloads31,055
monthly_downloads4,581

可持续性与治理

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

69中等 · 占总体的 24%
评分方式
9/54巴士系数 — 1 位贡献者贡献了半数提交
1.7/22.5提交分布 — 头号贡献者编写了 92% 的提交
9.5/13.5贡献者广度 — 7 位贡献者
10/10OpenSSF Scorecard:Contributors — project has 5 contributing companies or organizations
所用输入
bus_factor1
contributors_sampled7
top_contributor_share0.924
评分方式
46.8/46.8议题解决 — 100% 的议题已关闭
35.7/38.3PR 接受 — 已裁定的 PR 中 70/75 已合并
10.5/15OpenSSF Scorecard:Code-Review — Found 7/10 approved changesets -- score normalized to 7
所用输入
merged_prs70
open_issues0
closed_issues15
issue_closed_ratio1
closed_unmerged_prs5
评分方式
10/30所有权背书 — 个人(用户)账户
0/20已验证域名 — 不适用于个人账户
17.4/25所有者影响力 — koriym 有 261 位关注者
25/25既往记录 — 255 个公开仓库,账户约 15 年
所用输入
followers261
owner_typeUser
is_verified
owner_loginkoriym
public_repos255
account_age_days5,699
已排除计分(无数据或不适用):已验证域名。 其余权重已重新归一化。
评分方式
25/25已发布且可解析 — packagist 上有 1 个软件包
35/35发布时效 — 最近一次发布于 24 天前
20/20版本历史 — 19 个已发布版本
20/20未被弃用 — 活跃,未被弃用或撤回
所用输入
packageskoriym/xdebug-mcp
ecosystemspackagist
any_deprecated
min_days_since_publish24

工程质量

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

82良好 · 占总体的 20%

工程实践

84良好
评分方式
24/24CI 工作流 — 1 个工作流
24/24存在测试
16/16Linter 配置 — phpcs.xml, phpstan.neon
0/9.6Pre-commit 钩子
0/6.4.editorconfig
20/20OpenSSF Scorecard:CI-Tests — 7 out of 7 merged PRs checked by a CI test -- score normalized to 10
所用输入
has_ci
has_tests
has_editorconfig
has_linter_config
has_precommit_config

文档

80良好
评分方式
30/30README
25/25文档目录
15/15文档 / 主页站点 — https://packagist.org/packages/koriym/xdebug-mcp
10/10仓库描述
0/10主题标签
0/10Wiki
所用输入
topics
has_wiki
homepagehttps://packagist.org/packages/koriym/xdebug-mcp
has_readme
has_docs_dir
has_description

安全

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

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

安全态势

47存在风险
评分方式
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
2.5/2.5CI-Tests — 7 out of 7 merged PRs checked by a CI test -- score normalized to 10
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
5.2/7.5Code-Review — Found 7/10 approved changesets -- score normalized to 7
2.5/2.5Contributors — project has 5 contributing companies or organizations
0/10Dangerous-Workflow — 无数据
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
0/2.5许可证 — license file not detected
7.5/7.5Maintained — 30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
0/5Packaging — 无数据
0/5Pinned-Dependencies — 无数据
0/5SAST — SAST tool is not run on all commits -- score normalized to 0
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — 无数据
0/7.5Token-Permissions — 无数据
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
所用输入
sourceopenssf_scorecard
checks_evaluated13
scorecard_versionv5.5.0
checks_inconclusive5
scorecard_aggregate4.7
已排除计分(无数据或不适用):dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions。 其余权重已重新归一化。

AI 就绪度

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

66中等 · 占总体的 0%
评分方式
45/45代理指令 — AGENTS.md, CLAUDE.md
15/15机器可读文档(llms.txt) — 存在 llms.txt
40/40可读的提交历史 — 100 次人类提交中有 92 次说明了意图(结构化标题或解释性正文)
所用输入
has_llms_txt
legible_history_share0.92
agent_instruction_filesAGENTS.md, CLAUDE.md
agent_instruction_max_bytes34,870
评分方式
0/18一条命令的引导启动
22/22自动化测试
11/11Lint / 格式化配置 — phpcs.xml, phpstan.neon
0/11静态类型检查
10/10可复现环境 — Dockerfile
6/10已体现的代理实践 — 最近 100 次提交中有 3 次由代理编写或署名代理
0/8自动化维护 — 未观察到自动依赖更新
0/10OpenSSF Scorecard:Pinned-Dependencies — 无数据
所用输入
has_nix
has_tests
lockfiles
has_dockerfile
typed_language
bootstrap_files
has_devcontainer
has_linter_config
typecheck_configs
agent_commit_share0.03
toolchain_manifests
dependency_bot_commit_share0
已排除计分(无数据或不适用):OpenSSF Scorecard:Pinned-Dependencies。 其余权重已重新归一化。
评分方式
0/45可类型检查的代码 — PHP,未配置类型检查
54.4/55可控的文件大小 — 采样的 97 个源文件中有 1 个超过 60KB
所用输入
primary_languagePHP
largest_source_bytes143,186
source_files_sampled97
oversized_source_files1

机器可读接口

40存在风险
评分方式
0/40API 模式(OpenAPI/GraphQL/proto)
0/20MCP 服务器
40/40可运行示例 — examples
所用输入
example_dirsexamples
has_mcp_signal
api_schema_files

关键数据

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

数据采集警告

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

更多细节

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

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

0246810912025-082026-012026-06
主版本 0次版本 9修订 6
OpenSSF Scorecard 4.7 / 10
4.7综合

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

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
10CI-Tests7 out of 7 merged PRs checked by a CI test -- score normalized to 10
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
7Code-ReviewFound 7/10 approved changesets -- score normalized to 7
10Contributorsproject has 5 contributing companies or organizations
不适用Dangerous-Workflowno workflows found
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
0Licenselicense file not detected
10Maintained30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10
不适用Packagingpackaging workflow not detected
不适用Pinned-Dependenciesno dependencies found
0SASTSAST tool is not run on all commits -- score normalized to 0
0Security-Policysecurity policy file not detected
不适用Signed-Releasesno releases found
不适用Token-PermissionsNo tokens found
10Vulnerabilities0 existing vulnerabilities detected
直接依赖 4
注册表软件包版本约束清单文件
Packagistsymfony/polyfill-php83^1.33composer.json
Packagistamphp/socket^2.3composer.json
Packagistpsr/log^3.0composer.json
Packagistamphp/http-server^3.4composer.json
全部依赖 未采集

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

原始 JSON 报告 机器可读
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 3077,
      "has_wiki": false,
      "homepage": "https://packagist.org/packages/koriym/xdebug-mcp",
      "languages": {
        "PHP": 710702,
        "Shell": 2420,
        "Dockerfile": 701
      },
      "pushed_at": "2026-07-27T22:06:53Z",
      "created_at": "2025-08-16T18:24:31Z",
      "owner_type": "User",
      "updated_at": "2026-07-06T08:56:57Z",
      "description": "Enable AI to debug PHP with Xdebug",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "1.x",
      "license_spdx_raw": null,
      "primary_language": "PHP",
      "significant_languages": [
        "PHP"
      ]
    },
    "owner": {
      "blog": "http://koriym.github.io/about/",
      "name": "Akihito Koriyama",
      "type": "User",
      "login": "koriym",
      "company": null,
      "location": "Tokyo, Japan",
      "followers": 261,
      "avatar_url": "https://avatars.githubusercontent.com/u/529021?v=4",
      "created_at": "2010-12-19T01:16:45Z",
      "is_verified": null,
      "public_repos": 255,
      "account_age_days": 5699
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.11.1",
          "kind": "patch",
          "published_at": "2026-07-02T22:34:25Z"
        },
        {
          "tag": "v0.11.0",
          "kind": "minor",
          "published_at": "2026-06-26T16:06:53Z"
        },
        {
          "tag": "v0.10.2",
          "kind": "patch",
          "published_at": "2026-06-15T05:24:38Z"
        },
        {
          "tag": "v0.10.1",
          "kind": "patch",
          "published_at": "2026-05-21T12:00:28Z"
        },
        {
          "tag": "v0.10.0",
          "kind": "minor",
          "published_at": "2026-05-08T12:22:14Z"
        },
        {
          "tag": "v0.9.0",
          "kind": "minor",
          "published_at": "2026-04-29T16:11:09Z"
        },
        {
          "tag": "v0.8.0",
          "kind": "minor",
          "published_at": "2026-01-30T15:01:26Z"
        },
        {
          "tag": "v0.7.1",
          "kind": "patch",
          "published_at": "2026-01-15T16:32:43Z"
        },
        {
          "tag": "v0.7.0",
          "kind": "minor",
          "published_at": "2026-01-11T07:11:51Z"
        },
        {
          "tag": "v0.6.1",
          "kind": "patch",
          "published_at": "2026-01-10T23:50:31Z"
        },
        {
          "tag": "v0.6.0",
          "kind": "minor",
          "published_at": "2026-01-10T23:09:02Z"
        },
        {
          "tag": "v0.5.0",
          "kind": "minor",
          "published_at": "2025-12-18T13:34:02Z"
        },
        {
          "tag": "v0.4.0",
          "kind": "minor",
          "published_at": "2025-12-04T17:26:36Z"
        },
        {
          "tag": "v0.3.2",
          "kind": "patch",
          "published_at": "2025-11-03T13:51:10Z"
        },
        {
          "tag": "v0.3.1",
          "kind": "patch",
          "published_at": "2025-09-24T01:52:26Z"
        },
        {
          "tag": "v0.3.0",
          "kind": "minor",
          "published_at": "2025-09-02T18:06:55Z"
        },
        {
          "tag": "v0.2.1",
          "kind": "patch",
          "published_at": "2025-08-31T10:13:37Z"
        },
        {
          "tag": "0.2.0",
          "kind": "minor",
          "published_at": "2025-08-30T15:22:14Z"
        },
        {
          "tag": "0.1.0",
          "kind": "minor",
          "published_at": "2025-08-26T14:17:47Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "7868a08835afecf19fa1f8f3f5d4869016de74ea",
          "body": null,
          "is_bot": false,
          "headline": "0.11.1",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-07-02T22:33:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f93855fccfb3934510b08163a689c0610af75105",
          "body": "Report actual and requested debug port in xstep JSON output",
          "is_bot": false,
          "headline": "Merge pull request #90 from koriym/xstep-json-report-effective-port",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-07-02T22:13:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4a5a855d334c4ab374e37e81caae2c95436ba44d",
          "body": "When the configured debug port (9004) is already in use, DebugServer\nfalls back to an OS-assigned ephemeral port but only mentions this via\nlog(), which is a no-op in --json mode. A caller that only sees the\nJSON output had no way to know a fallback happened, or which port\nXdebug actually bound to.\n\n[…]\non paths -\noutputStepRecordingResults() and outputMultipleBreakResults() - via a\nshared addPortInfoToResult() helper. Update the XstepJsonOutput\nphpstan-type and the public xstep.json schema to match.",
          "is_bot": false,
          "headline": "Report actual and requested debug port in xstep JSON output",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-07-02T22:04:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "96534e44e98fc5b7b7158ac72a37d3849a0b82fc",
          "body": "Fix silent debug-session failures and related reliability/perf issues",
          "is_bot": false,
          "headline": "Merge pull request #89 from koriym/claude/nostalgic-napier-6ec936",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-07-02T21:51:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bf3b3d5d1ff3d2c9cc70bbfc71ceba6c5badaf57",
          "body": "- McpServer: encode responses with JSON_INVALID_UTF8_SUBSTITUTE via a new\n  encodeResponse() that never lets a bad encode terminate the STDIN loop\n  (non-UTF-8 bytes from exec() tool output no longer wedge it on the response\n  side); harden debugLog() the same way.\n- DebugServer::readDbgpFrame(): do\n[…]\ning the 'unknown' sentinel and recording a\n  breakpoint that was never set.\n- CompareRunner worktree test: assert the child exits non-zero so it pins the\n  fatal-error path, not just shutdown-on-exit.",
          "is_bot": false,
          "headline": "Address CodeRabbit review: prevent encoding/read-failure wedges",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-07-02T20:32:55Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7757eee42da85fce3d70a34a2c7e861d6d7af62c",
          "body": "run()'s try/finally removed the --compare-with worktree on a normal return or\na thrown exception, but a fatal error skipped it and leaked the worktree.\nRegister a shutdown handler in createWorktree() to cover that path (it reuses\nthe idempotent cleanupWorktree(), so a normal run is a no-op). A SIGTERM/SIGKILL\ndelivered while blocked in proc_close() still cannot be cleaned this way and is\ndocumented as a known gap.",
          "is_bot": false,
          "headline": "Remove temporary git worktree on fatal exit in CompareRunner",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-07-02T17:49:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "10feab720adbed73431d76908de155d84c96bb17",
          "body": "analyzeCachegrindFile() read the profile with file_get_contents() and\nexplode(), holding 2-3x the file size in memory; Cachegrind profiles can be\nhundreds of MB. Parse it in a single fgets() pass, reading the events:/summary:\nheaders inline. total_lines keeps the previous count(explode(\"\\\\n\")) value\nexactly (newline count + 1), verified byte-identical against the old parser on\nreal and edge-case files.",
          "is_bot": false,
          "headline": "Stream Cachegrind parsing instead of loading the whole file",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-07-02T17:49:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b382436deaadeeae29f9f3b7e5956d739e0d9992",
          "body": "The stdin loop accumulated bytes until isCompleteJsonRpc() succeeded, so a\nsingle malformed line was never cleared and silently swallowed every\nsubsequent request (the -32700 parse-error path was unreachable). Parse each\nline independently in a new, unit-testable handleLine(): a bad line now returns\n[…]\nor and cannot wedge the stream.\n\nAlso route the per-request DEBUG logs through the MCP_DEBUG-gated debugLog()\n(and add JSON_UNESCAPED_SLASHES) so request payloads are no longer logged\nunconditionally.",
          "is_bot": false,
          "headline": "Fix MCP stdin framing wedge and gate debug logging",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-07-02T17:49:49Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "9271bf9c75e0a41059917bb8171688ec3679f873",
          "body": "…gServer\n\nAddress several reliability and performance issues in the DBGp debug server:\n\n- Surface debug-session failures instead of masking them as success.\n  __invoke() awaited tasks with Future\\awaitAll(), which never throws (it\n  returns [errors, values]), so listener-bind/connection/spawn failur\n[…]\nL\n  bytes inside the payload are preserved.\n\n- Run the lsof existing-session diagnostic lazily (only on a real bind failure)\n  instead of on every construction, and extract parsePidList() for testing.",
          "is_bot": false,
          "headline": "Fix silent failures, concurrency, and conditional breakpoints in Debu…",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-07-02T17:49:36Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "fecb9b07ef3068e9a441e3886ef42cbb075924b2",
          "body": null,
          "is_bot": false,
          "headline": "0.11.0",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-26T16:06:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "518d9d78a380887b768e24078d9a6ef0d2ea81d5",
          "body": "Remove dead XdebugProfiler and unused profile DTOs",
          "is_bot": false,
          "headline": "Merge pull request #88 from koriym/remove-dead-xdebugprofiler",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-26T16:01:31Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "89f5381e62803c90886a0d4944aef924faf7d454",
          "body": "XdebugProfiler was never instantiated (grep: zero callers). Both the CLI\n(bin/xprofile) and the MCP path (McpServer::executeXProfile execs\nbin/xprofile --json) bypass it, and it also mis-parsed the cachegrind summary\nline. ProfileStatistics and ProfileAnalysis were tagged \"@codeCoverageIgnore\nUsed by XdebugProfiler runtime\" but were referenced only by that dead class.\n\ncomposer tests and static analysis stay green after removal.",
          "is_bot": false,
          "headline": "Remove dead XdebugProfiler and unused profile DTOs",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-26T15:54:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a8ce64d2c48e9321b78d84f369ee9bb45301f79c",
          "body": "Make xprofile time/memory measured and bottlenecks structured",
          "is_bot": false,
          "headline": "Merge pull request #87 from koriym/xprofile-accuracy",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-26T15:51:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c7fb0f4f528d3cb761c9e5ef4f215abbc518950f",
          "body": "- Read the cachegrind `events:` header to locate the Time/Memory columns\n  instead of hard-coding positions, so a non-default xdebug.cachegrind_events\n  order works. The summary parse and the cost-line aggregation both use the\n  mapped indices.\n- Render structured bottlenecks in the human-readable C\n[…]\nI path\n  (displayHumanReadableProfile was echoing the arrays as \"Array\").\n- Fix the profile tool description: xprofile emits `schema`, not `$schema`\n  (McpServer description + mirrored SKILL wording).",
          "is_bot": false,
          "headline": "Address CodeRabbit review on xprofile",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-26T14:51:31Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "d47a893dbd490783d67a4772184f4526c9b08a5b",
          "body": "time_ms and memory_mb were heuristic estimates (time_ms could round to 0;\nmemory_mb was a fixed-base formula). Parse the cachegrind `summary:` line for\nthe real measured totals (units from the `events:` header, Time_(10ns) and\nMemory_(bytes)), keeping the estimate only as a fallback.\n\nbottlenecks we\n[…]\n were meaningless.\nNow percentages and time_ms are time-based, and the bottleneck time_ms values\nsum to the reported total.\n\nSchema, MCP tool description, skill, and TROUBLESHOOTING jq example follow.",
          "is_bot": false,
          "headline": "Make xprofile time/memory measured and bottlenecks structured",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-26T14:34:03Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "c218088de4c4aae83111d7fd6f8865e51bae78af",
          "body": "Slim down xstep step-recording JSON output",
          "is_bot": false,
          "headline": "Merge pull request #86 from koriym/claude/exciting-galileo-19657b",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-26T14:33:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57f5ad6e12fadd2fb7d511d2578ff38aae4dbc36",
          "body": "The test seeds breaks directly, so it would still pass if\noutputStepRecordingResults() dropped stack. Pin breaks[0]['stack'] — the\nreplacement for per-step location/function — so the contract can't regress\nsilently.",
          "is_bot": false,
          "headline": "Assert the per-step stack contract in the hoisting regression test",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-26T13:25:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "87be67f9c3b8a1811f1a81ff86ead9f868cdc2c7",
          "body": "- xstep.json: require stack minItems:1 — consumers read the stop frame from\n  stack[0], so an empty stack must not validate.\n- xstep.json: correct the diff description. A stack-frame change does NOT\n  guarantee every variable reappears as `added` (the producer skips\n  same-name/same-value entries), \n[…]\nso the machine-readable file/line is\n  never lost after dropping location/function.\n- DebugServerTest: pin breakpoint hoisting and the absence of per-step\n  location/function in step-recording output.",
          "is_bot": false,
          "headline": "Address CodeRabbit second review",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-26T13:20:18Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "13fb59f0bf0ca0ddfbaea28913464bf7fd97d044",
          "body": "Per review: the skill and MCP tool description are for telling the model to\nread the schema, not for re-describing the output format. Restated formats\ndrift out of sync -- the skill had kept the stale {step, location, variables}\nshape from before the slim-down. Remove the inlined read-rules, field list,\nand concrete examples from both surfaces; they now point to the linked\n$schema, which is the single source of truth for the output structure.",
          "is_bot": false,
          "headline": "Defer output format to the schema, don't restate it in skill/description",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-19T22:31:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cf61dfc83b298f46aa3af7fd8e01a82aa7a7162a",
          "body": "The skill's xstep \"Key fields\" still advertised the pre-slim shape\n({step, location, variables}). Update it to the current shape and add a\n\"Reading the output\" guide: stack[0] = current frame, diff reconstruction\nonto the last full snapshot, scope reset on a frame change, and the\n'type: value' rendering.\n\nThe skill is the surface that actually reaches the model when /xdebug is\nused, so the read-rules belong where they will be read -- more reliable than\nhoping the model fetches the $schema URL.",
          "is_bot": false,
          "headline": "Update xdebug skill: xstep output contract and reading guide",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-19T22:21:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a0a59e23d31a6b030dd197fe55323bab2faec57c",
          "body": "Sub-agent testing showed AIs interpret the slimmed output from structure\nalone (~90% correct) without fetching the $schema URL. Make the remaining\nread-rules explicit so that reading the schema -- or the MCP tool\ndescription, which is delivered to the model directly -- removes the gap:\n\n- stack: inn\n[…]\nded\n- recording_type: empty/absent diff means no change; values are 'type: value'\n\nMirror the stack[0] hint into the MCP xstep tool description too, since the\nschema URL is not auto-fetched by models.",
          "is_bot": false,
          "headline": "Document the slimmed output contract for AI consumers",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-19T22:18:15Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "7781fea6d2b24a13816a9ef38ef17f425f8197e4",
          "body": "- handlePromptsList() still advertised the old {step, location, variables}\n  shape; align it with initializeTools() so both MCP surfaces agree.\n- Schema variables description: removed entries carry `before` (not `after`);\n  clarify the rehydration rule for diff frames.",
          "is_bot": false,
          "headline": "Address CodeRabbit review",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-19T22:01:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f95b513ebd1612a853cd11d56e22c924cf8d0b24",
          "body": "Remove fields from the xstep --steps JSON that duplicate data available\nelsewhere, cutting token cost for AI consumers with zero information loss:\n\n- Drop per-step `location` and `function` (both duplicate stack[0])\n- Omit `variables` on diff steps (recoverable from diff.after)\n- Emit the shared `br\n[…]\nompareRunner (the only machine consumer of xstep output) now reads the\nbreakpoint location from stack[0]. Schema, PHPStan types and tests follow.\n\nMeasured: 6673B -> 4632B (-30.5%) on a 12-step trace.",
          "is_bot": false,
          "headline": "Slim down xstep step-recording JSON output",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-19T21:40:58Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "64cccbe98e22f5afd4a5c52b0633131a24221e16",
          "body": "Clean up stray files, unify prepend filters, fix stale CLAUDE.md references",
          "is_bot": false,
          "headline": "Merge pull request #85 from koriym/claude/observation-suggestions-721dka",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-19T00:39:59Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "410900dbcaf12d301f42e97f4ba2f396b35fb2b7",
          "body": "Address CodeRabbit review on PR #85:\n- Line 482: drop the stale \"listener-first\" requirement; ./bin/xstep is a\n  single command that builds the DebugServer and spawns the target, matching\n  the Step Debugging Connection Protocol section.\n- Add `text` language to the two trace-output/table fences.\n- \n[…]\n at 620/741 are closing\nfences of existing ```bash blocks.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CsYZ8A6wKgjwc82KuUuQaz",
          "is_bot": false,
          "headline": "docs: fix CLAUDE.md code-fence languages and stale step-debug note",
          "author_name": "Claude",
          "author_login": "claude",
          "committed_at": "2026-06-18T21:16:46Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "be8033570631930378fbcc3b424ccb06600e71cd",
          "body": "Three maintenance fixes observed while reviewing the repo:\n\n1. Remove stray root-level files\n   - breakpoint_test.php: an unused fixture committed to the repo root,\n     not referenced anywhere.\n   - prepend_filter.php (root): see below.\n\n2. Unify the two same-named prepend_filter.php scripts\n   The\n[…]\nAll tests pass (293), PHPStan level 10 clean, phpcs clean.\n\nCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>\nClaude-Session: https://claude.ai/code/session_01CsYZ8A6wKgjwc82KuUuQaz",
          "is_bot": false,
          "headline": "Clean up stray files, unify prepend filters, fix stale docs",
          "author_name": "Claude",
          "author_login": "claude",
          "committed_at": "2026-06-18T19:13:59Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "88f69d7678832fe49a6f0bc59fa92e946b95a0f1",
          "body": null,
          "is_bot": false,
          "headline": "0.10.2",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-15T05:24:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f575ac48661d24f62b331452c27228503600ca55",
          "body": "Harden xcompare worktree and error handling",
          "is_bot": false,
          "headline": "Merge pull request #84 from koriym/codex/xcompare-hardening-pr62",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-15T05:22:48Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "323e8b431c8e0c3bde82fecb213a06e39a273ff5",
          "body": null,
          "is_bot": false,
          "headline": "fix: preserve worktree path when cleanup fails after failed worktree add",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-15T05:18:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "de69db446a6736de279bebe5beba4d481175b740",
          "body": null,
          "is_bot": false,
          "headline": "Harden xcompare worktree and error handling",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-08T23:31:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59b2b489b3c3006ee2bea44e005a2db8d2a51262",
          "body": null,
          "is_bot": false,
          "headline": "Merge pull request #83 from koriym/codex/php-r",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-06T12:30:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cdd6e2656f79202729103ea6c81b6ad7b0d5a0ec",
          "body": "Address CodeRabbit review on #83: -r/--run detection scanned the whole\ncommand, so a script's own arguments (e.g. `php app.php -r dry-run`) were\nmistaken for interpreter inline code.\n\n- findPhpRunCodeArgument() (bin/xcoverage): stop at the first non-option\n  token or \"--\", and skip option values (sh\n[…]\nrary bootstrap file creation/write in bin/xcoverage and fail\n  with a clear message instead of proceeding with an invalid prepend file.\n- Add unit tests for the script-boundary and option-value cases.",
          "is_bot": false,
          "headline": "fix: stop inline-code detection at the PHP script boundary",
          "author_name": "Claude",
          "author_login": "claude",
          "committed_at": "2026-06-06T12:18:56Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "963cfb54a0bb43176d8250c3e42c1a038311afe5",
          "body": "…g PHP options\n\nRemove dead code that became unreachable after rejecting php -r branch\ncoverage, and close a file-detection gap for long-form PHP options.\n\n- buildRawCoverageBootstrap(): drop the commandLineCodeOffset adjustment\n  block (callers always passed 0) and the filterCommandLineBootstrap\n  \n[…]\n/-end) so their space-separated value is not mistaken for the\n  target script (e.g. `php --define memory_limit=512M file.php`).\n- Add unit tests for the long-form (attached and space-separated) cases.",
          "is_bot": false,
          "headline": "refactor: drop unreachable raw-coverage bootstrap code and handle lon…",
          "author_name": "Claude",
          "author_login": "claude",
          "committed_at": "2026-06-06T11:07:46Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "6b4dd29f3f25404bc83587e992f9249feab45f79",
          "body": null,
          "is_bot": false,
          "headline": "fix: reject php -r branch coverage",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-06T06:09:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "34dde6136745bd1837e47ce6e4f2c5d12dbeddf1",
          "body": null,
          "is_bot": false,
          "headline": "Add php -r support for coverage and profile",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-06-06T05:53:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0da17574dac9c421792b3616ac56e097093503b1",
          "body": null,
          "is_bot": false,
          "headline": "0.10.1",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-21T11:58:57Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "95609c5e65ff3ddcad64ca671c045968d5c68c05",
          "body": "Clean up CLI help and vendor filtering",
          "is_bot": false,
          "headline": "Merge pull request #82 from koriym/codex/help-command-cleanup",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-21T11:56:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "57934768f22de992f40c483319fa1e38b5e04ea8",
          "body": null,
          "is_bot": false,
          "headline": "fix: address CodeRabbit review comments",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-21T11:28:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "dca447e70ebfc0692d27f548b37aabb585ea5489",
          "body": null,
          "is_bot": false,
          "headline": "docs: add public output guidance",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-21T05:18:46Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "bebc0ec49c187e2be9585eb4071adfae4f42d3ae",
          "body": null,
          "is_bot": false,
          "headline": "fix: clean up CLI help and vendor filtering",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-21T04:04:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "aa843311aff9205b8dbfff491b8e646806bda4b4",
          "body": null,
          "is_bot": false,
          "headline": "docs: note that release-prep minor commits can go directly to 1.x",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-08T12:21:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2be60203ea3e6f2c8895ec8c98d38c389dd5bb79",
          "body": null,
          "is_bot": false,
          "headline": "chore: prepare release v0.10.0",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-08T12:19:56Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a011d44d4c5189ca98b9217c643bdea523b46cc1",
          "body": "- DebugServerXmlSanitizerTest: use assertStringNotContainsString to avoid false negative when null byte sits at offset 0\n- print_cwd.php: add declare(strict_types=1)\n- McpServer::executeXCoverage: enforce documented mutual exclusivity between source and include_vendor",
          "is_bot": false,
          "headline": "Address CodeRabbit feedback",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-08T12:19:27Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "eb353ef739b3aee2f73a0675fa82551f14cf1066",
          "body": "Handle invalid XML character references",
          "is_bot": false,
          "headline": "Merge pull request #81 from koriym/codex/issue-79-debugserver-charref",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-08T12:15:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "da8bd00fa3a12a975ede368f354b3de1e701b09f",
          "body": null,
          "is_bot": false,
          "headline": "Handle invalid XML char references",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-08T05:26:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b54cbb4f1f24661eba94a39eadd71108531b9642",
          "body": "Fix xcoverage / xback ergonomics for external projects (#79)",
          "is_bot": false,
          "headline": "Merge pull request #80 from koriym/issue-79-xcoverage-ergonomics",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-08T01:10:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2e051ecf2ff97e53149684e056cdf5835c1068ad",
          "body": "PHPStan flagged the new $this->options['phpBinary'] ?? '' lookup because\nthe @param array shape on DebugServer::__construct didn't declare\n`phpBinary`. Without the shape entry PHPStan inferred the offset as\nabsent and folded the ?? '' to a literal '', triggering both an\n\"offset does not exist\" error and a \"strict comparison '' !== '' always\nfalse\" follow-up at each of the two new call sites.\n\nAdd `phpBinary?: string` to the array shape so PHPStan agrees with the\nruntime behavior. No code change.",
          "is_bot": false,
          "headline": "Add phpBinary to DebugServer options array shape",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-07T22:12:12Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "112151f636ab53f120f0895dd9916a0ed23b453f",
          "body": "…nary\n\nCodeRabbit flagged that bin/xback's --php option replaced $command[0]\nwith the resolved override path, but DebugServer::executeTargetScript()\nselects the local-PHP execution branch via a strict $command[0] === 'php'\ncheck and otherwise throws \"Custom command must start with 'php' or be a\nDock\n[…]\nting to 'php' when unset.\n\nAdds testXbackPhpOption that runs `xback --php=<absolute php> -- php\n<fixture>` and asserts the run doesn't fall through to the error path\nand emits the expected xback JSON.",
          "is_bot": false,
          "headline": "Fix --php override for xback so DebugServer can spawn the override bi…",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-07T22:09:59Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "b50f9a8801f758cd6450b71b322d9f56c0eec070",
          "body": "Adds --cwd and --php options to xcoverage and xback so they can be invoked\nagainst external projects (e.g. Ray.MediaQuery) without shell stitching, and\nadds --source for the xcoverage --raw mode to restrict coverage to specific\npaths.\n\nAlso fixes a libxml SimpleXML parse failure in DebugServer when \n[…]\numbing.\n- tests: new DebugServerXmlSanitizerTest (unit) and\n  XdebugCommandsTest::testXcoverage{Help,CwdOption,RawSourceFilter}*,\n  testXback{Help,CwdOption} (integration), plus print_cwd.php fixture.",
          "is_bot": false,
          "headline": "Address issue #79: xcoverage / xback ergonomics",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-05-07T22:00:50Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "88787c732c3f6604d2a04ca696c021bfc5bcdd0b",
          "body": "chore: release v0.9.0",
          "is_bot": false,
          "headline": "Merge pull request #78 from koriym/release-prep-v0.9.0",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-29T16:10:37Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "0aa59a94a0025ca1c57dedc0070fab20c8b6a971",
          "body": null,
          "is_bot": false,
          "headline": "chore: release v0.9.0",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-29T16:08:47Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7b5883a001533b9f8663895f91e289829f087ab2",
          "body": "docs: clarify README and demo smoke test scope",
          "is_bot": false,
          "headline": "Merge pull request #76 from koriym/readme-cli-discoverability",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-29T16:07:32Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "327f93f3b95628cd66b1a5a5cd6dbafa422b79cc",
          "body": null,
          "is_bot": false,
          "headline": "docs: clarify MCP and CLI tool boundaries",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-29T16:05:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "77b3bbdc9d2b733e3ba0c3036b21b5f492854d96",
          "body": null,
          "is_bot": false,
          "headline": "test(demo): avoid conflict marker-like separator",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-29T15:57:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae4607e730ca6858c9e2e245c8e319c9c5d5a38f",
          "body": "…lity\n\n# Conflicts:\n#\tdemo/run-demo.sh",
          "is_bot": false,
          "headline": "Merge remote-tracking branch 'origin/1.x' into readme-cli-discoverabi…",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-29T15:56:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "70afd2c48a06d4de73c59001217c6a6385070dfb",
          "body": "chore: prepare release notes and clean up stale 8.1 references",
          "is_bot": false,
          "headline": "Merge pull request #77 from koriym/release-prep",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-29T15:51:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4b5a55a2e775ba785268cec36d46636bbfb653f7",
          "body": "- Narrow header comment to non-interactive CLI tools, document the\n  xrepl/xdebug-mcp scope exclusion (Copilot review on #76).\n- Fail fast if cd to repo root fails (Copilot review on #76).\n- Fix run() so the FAIL message reports the failing command's exit\n  status; previously $? after the if was always 0, masking the real\n  code.\n- Add xrepl --help presence smoke check (CodeRabbit review on #77).",
          "is_bot": false,
          "headline": "demo: address review feedback on run-demo.sh",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-28T22:25:36Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "88db21b0e084f3845a852e9b7cdbe47a1b2aee39",
          "body": "- Fail fast if `cd \"$(dirname \"$0\")/..\"` fails so PASS/FAIL output\n  cannot be emitted from the wrong working directory.\n- Add a non-interactive `xrepl --help` smoke check so the script\n  actually covers every CLI tool the README documents (matches the\n  top-of-file claim).",
          "is_bot": false,
          "headline": "docs(demo): address CodeRabbit feedback on run-demo.sh",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-28T21:51:01Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "899560d157beccc35f3d06599f3737dd19dec76b",
          "body": "- Update CHANGELOG.md [Unreleased] with the changes from #74 (xstep JSON\n  ergonomics), #75 (PHPUnit 11 / drop PHP 8.1), and #76 (README + composer\n  demo + bin discoverability) so the next release tag has full notes.\n- Replace lingering `php8.1` examples in profiler/examples/basic-usage.md\n  (CI ma\n[…]\n bug is intentionally not addressed here — the fix\nrequires a non-trivial refactor of DebugServer (which currently calls\n`exit()` before xback can transform the output) and will be tracked\nseparately.",
          "is_bot": false,
          "headline": "chore: prepare release notes and clean up stale 8.1 references",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-28T09:46:30Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "2175eac5b373bcad21cc4f080baf35b4375852f6",
          "body": "…ADME\n\n- demo/run-demo.sh runs every command listed in the README's \"Try CLI\n  Tools\" / \"CLI Usage\" sections (xstep, xtrace, xprofile, xcoverage,\n  xback, xcompare) against the bundled demo/ scripts and reports\n  PASS/FAIL for each. Useful as a smoke test after dependency or\n  Xdebug upgrades.\n- Wir\n[…]\no PHPUnit\n  mode and requires `--raw` for plain PHP scripts. The previous example\n  failed with \"Class coverage cannot be found\" because PHPUnit\n  interpreted `demo/coverage.php` as a test class path.",
          "is_bot": false,
          "headline": "feat: add `composer demo` to exercise every CLI tool documented in RE…",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-28T09:25:41Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "53688f93f6319b98eac41bf8aad1a1013f3d9814",
          "body": "- Add bin/xrepl and bin/xcompare to composer.json's bin array so users\n  who install via `composer global require` actually get those commands\n  on PATH (README extensively documents both).\n- Drop `--exit-on-break` from xstep examples; the flag is not parsed by\n  bin/xstep and was silently dropped. \n[…]\n-bytes`, `--max-depth` (added in #74).\n- Replace hard-coded `~/.composer/vendor/bin/check-env` with\n  `composer global config bin-dir` so the snippet works across modern\n  XDG-based composer installs.",
          "is_bot": false,
          "headline": "docs: fix README CLI examples and expose xrepl/xcompare via composer bin",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-28T09:22:00Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "44bad52c39b343e5f78b93991d5b662a1ee102e3",
          "body": "build: upgrade to PHPUnit 11 and drop PHP 8.1",
          "is_bot": false,
          "headline": "Merge pull request #75 from koriym/phpunit11-upgrade",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-28T09:09:38Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "67383f672f5ed53430ce9731935701b0522d4b71",
          "body": "feat(xstep): improve JSON ergonomics for real debugging sessions",
          "is_bot": false,
          "headline": "Merge pull request #74 from koriym/xstep-json-ergonomics",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-28T09:09:05Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e42f8971bdbeb6b9238b1aaf4f5bf491ff13e0a4",
          "body": "- truncateStringValue now uses mb_strcut to preserve UTF-8 boundaries,\n  preventing JsonException when JSON_THROW_ON_ERROR encounters split\n  multi-byte sequences\n- introduce DEFAULT_CHILD_VALUE_BYTES constant in place of the magic\n  literal 20 used by extractChildDetails, mirroring DEFAULT_MAX_VALUE_BYTES\n- assert shallow_key_diff exists in xstep schema definitions to guard\n  against silent breakage of the variable_diff.keys $ref",
          "is_bot": false,
          "headline": "fix(xstep): address CodeRabbit review feedback on PR #74",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T20:25:26Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "749a1019a14f945e3754f82224b01bfb3367faa3",
          "body": "…DebugServer",
          "is_bot": false,
          "headline": "fix(phpstan): resolve noMixed.arrayShape and unused method errors in …",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T19:38:50Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "86ce3f5cf02a66ca200dcfa359bc81d303a02799",
          "body": "Address pain points that made xstep output hard to consume during\nbreakpoint-driven inspection (#69):\n\n- add --pretty for 2-space formatted JSON output\n- add --max-value-bytes and --max-depth to control truncation\n- include function name and a short stack summary on each step\n- enrich diff with scalar before/after and shallow array/object key diffs\n- attach breakpoint id/label to each step record\n\nCloses #69",
          "is_bot": false,
          "headline": "feat(xstep): improve JSON ergonomics for real debugging sessions",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T19:22:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c1ab87add92cd060f16bf30d43c6f62d88843f66",
          "body": null,
          "is_bot": false,
          "headline": "docs: document PHP 8.2 requirement",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T19:15:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "fb539791e47f28a73277b836ce5c1339d784e426",
          "body": null,
          "is_bot": false,
          "headline": "test: remove deprecated reflection accessibility call",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T19:15:28Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "38fc9678dfde6f82cbedffd792f560c376d3a930",
          "body": null,
          "is_bot": false,
          "headline": "build: require PHP 8.2 and PHPUnit 11",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T19:15:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "e53813de5e999ee1a85836c8112f34c340e1078c",
          "body": "docs(xstep): document recording_type field (closes #59)",
          "is_bot": false,
          "headline": "Merge pull request #73 from koriym/xstep-schema-recording-type",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T19:03:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2bdcf87dc748531094199ce3414441a3bbc86d69",
          "body": "Locks in the schema additions from the previous commits so a future\nedit cannot silently drop recording_type or its enum without a failing\ntest.",
          "is_bot": false,
          "headline": "test(xstep): assert recording_type is documented in xstep schema",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T18:59:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9dc41ba5a1ee9a38d4ad643f021028d0dcd0c80b",
          "body": "…ions",
          "is_bot": false,
          "headline": "docs(xstep): align flag-combination phrasing in xstep schema descript…",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T18:59:19Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "59f3302ba1652749a746968a8ccdc2bc053d6f40",
          "body": "The xstep runtime emits a 'recording_type' field on each step in\nstep-recording mode (--break combined with --steps), with values 'full'\nor 'diff'. The output was undocumented because docs/schemas/xstep.json\ndid not declare the field, leaving consumers to either ignore unknown\nkeys or reverse-engineer the meaning. Closes #59 (the breakpoint-mode\nduplicate JSON output it also reported is no longer reproducible on\n1.x).",
          "is_bot": false,
          "headline": "docs(xstep): document recording_type field in xstep schema",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T16:45:33Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b4ba6cc2003cefe0790dc9f6609fffdd8b518af2",
          "body": "fix: format PHPUnit coverage in xcoverage",
          "is_bot": false,
          "headline": "Merge pull request #72 from koriym/fix-xcoverage-phpunit-clover",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T15:07:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "011efc458c8508365ca7b8349f5a928e6df0c243",
          "body": "- Replace tempnam/unlink/mkdir dance with bin2hex(random_bytes(6)) for\n  the fixture directory; eliminates the brief race window between unlink\n  and mkdir.\n- Locate the JSON payload via the $schema token instead of a marker\n  string tightly coupled to JSON_PRETTY_PRINT's exact indentation, so\n  formatting changes produce a more useful failure than a silent miss.",
          "is_bot": false,
          "headline": "test(xcoverage): address CodeRabbit nitpicks on phpunit clover test",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T14:57:23Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "47660dd3f90940c4456b2535b2f36a4aa03f1753",
          "body": "fix(xcompare): post-merge follow-ups from PR #62 review",
          "is_bot": false,
          "headline": "Merge pull request #71 from koriym/xcompare-followups",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T14:34:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4818d8a8b192435f557a2fcf1b064f07fce57701",
          "body": null,
          "is_bot": false,
          "headline": "fix: format PHPUnit coverage in xcoverage",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T12:07:08Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "17d91eb765172480fed3165bf881024948eb362a",
          "body": null,
          "is_bot": false,
          "headline": "fix(xcompare): clamp --steps to >= 1",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T11:54:35Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9dc9799f7ebc5f69c867a517ac1b5249ce692f9b",
          "body": null,
          "is_bot": false,
          "headline": "docs(xcompare): declare $schema in xcompare JSON Schema",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T11:54:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1771c2dc8f1da4fb684f834a46456991b68dbc4c",
          "body": null,
          "is_bot": false,
          "headline": "test(xcompare): move CLI exec tests to Integration suite",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T11:53:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9fe5915983ba907a543497ea5ece7a4913a4fcfb",
          "body": null,
          "is_bot": false,
          "headline": "fix(xcompare): surface git stderr in --compare-with pre-check",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T11:52:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ccb5e775c2e635b366c1f165f274195308e8c110",
          "body": null,
          "is_bot": false,
          "headline": "fix(xcompare): reject malformed --break specs",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T11:52:09Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "133486a97ee26e133f8016403a191e3c5e0a82a1",
          "body": "…r1tgl\n\nfeat: Add xcompare breakpoint comparison tool",
          "is_bot": false,
          "headline": "Merge pull request #62 from koriym/claude/breakpoint-comparison-tool-…",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-27T01:29:13Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b738692c2dae553d9b6fa584abb9a6c848c5f5eb",
          "body": "…egration test\n\nextractLocation() previously returned {file:\"\", line:0} when xstep didn't hit\nthe breakpoint. That sentinel is hard to read and discards the only piece of\ninformation we actually have — where xcompare was looking. Fall back to the\nrequested file/line so consumers see the intent rathe\n[…]\n work tree). The unit\nsuite never reached this code, so a change in git's `worktree add` output\nformat would have slipped through.\n\nCo-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(xcompare): mirror requested breakpoint on no_break + worktree int…",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T23:02:23Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2a4e5d960e1e669d0ec8c27ce56eb170d0f5f7c3",
          "body": "xcompare only reads the break-point snapshot, so one step is enough by\ndefault. Tell users they can raise --steps if they want to see the\npost-break divergence between the two runs.",
          "is_bot": false,
          "headline": "docs(xcompare): document --steps=1 default and when to override",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2f9bc5ce7e9dad5165b69649d729965a0b19cddb",
          "body": "When --steps is omitted, xstep emits two JSON documents to stdout\n(the break data, followed by an empty breaks record from the cleanup\npath), breaking json_decode. xcompare only reads the first break\nanyway, so forcing --steps=1 is both a clean workaround and a minimal\npayload for comparison.\n\nUsers can still override via --steps to see forward-step evolution.\nThe underlying xstep behavior is tracked separately.",
          "is_bot": false,
          "headline": "fix(xcompare): default --steps=1 to avoid xstep double-JSON output",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "4c90b3ffd49a2871df6f3aa5290c1cf04c9b9114",
          "body": "Explicitly redirect fd 0 to /dev/null so the child xstep process cannot\ninherit or block on the parent's stdin. Harmless today since xstep does\nnot read stdin, but closes the gap before any future change would expose\nit.\n\nAddresses CodeRabbit nit on PR #62.",
          "is_bot": false,
          "headline": "fix: isolate xstep child stdin from parent",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "5ebbff4e0dc1c36039f3d57531882f4200dcd28f",
          "body": "Consolidates the shell-safety work from PR #65 with CodeRabbit's\nfollow-ups on that PR. Closes #65.\n\n- resolveCompareWithMode: drop str_replace($cwd, worktree, $run).\n  Both runs now receive the same user command; the worktree selection\n  is done via proc_open's cwd option instead of rewriting the c\n[…]\n than the pipe buffer can hold; a file\n    descriptor has no such limit.\n  * Escape $xstepBin defensively (__DIR__ may contain spaces).\n\n- FakeCompareRunner: match the new signature ($cwd is ignored).",
          "is_bot": false,
          "headline": "fix: harden xcompare shell invocation (supersedes #65)",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "f58175898594c145b706fa5d8853814f64893a30",
          "body": "- README: fix src/calc.php vs calc.php path mismatch in --compare-with\n  example so --break and --run reference the same file.\n- bin/README.md + bin/xcompare --help: add a shell-execution note to\n  --run / --run-a / --run-b so CLI users see the same caveat we\n  already added to the top-level README.",
          "is_bot": false,
          "headline": "fix: address CodeRabbit follow-ups on PR #62",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "c4fcbf23ec8e7f88f85609d6e78fb721e83971a2",
          "body": "Items not covered by PR #65 (shell hardening):\n\n- createWorktree: pre-check that we're inside a git work tree and\n  switch to uniqid('', true) so parallel runs can't collide on the\n  temp dir.\n- cleanupWorktree: capture stderr and warn to STDERR on non-zero\n  exit instead of silently swallowing clea\n[…]\ns is no_break.\n- xcompare schema: add optional breakpoint.condition field.\n- README: note that xcompare's --run / --run-a / --run-b values go\n  through the shell and should only receive trusted input.",
          "is_bot": false,
          "headline": "fix: address PR #62 review follow-ups",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": true,
          "is_coding_agent": false
        },
        {
          "oid": "efe83a985a9d97b922ff2eb7fafafc30522e38db",
          "body": null,
          "is_bot": false,
          "headline": "style: phpcbf-fix CompareRunner import and docblock alignment",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "f651b26f7f63e87d08a7b5bb3e7aa115b0b47946",
          "body": "- Auto-fix 56 CS errors in tests/Unit/CompareRunnerTest.php via phpcbf\n- Extract FakeCompareRunner to its own file to satisfy\n  Squiz.Classes.ClassFileName.NoMatch and\n  PSR1.Classes.ClassDeclaration.MultipleClasses\n- Strip section-divider comments that tripped\n  Squiz.Commenting.FunctionComment.WrongStyle",
          "is_bot": false,
          "headline": "style: phpcs-fix CompareRunnerTest and extract FakeCompareRunner",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "2592b00c12304dfe10a74ba2f3181022dd4f0736",
          "body": null,
          "is_bot": false,
          "headline": "docs: install Codex CLI via Skills, not MCP config",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a197c803814ba79f51c4ab1f6d317075ea37f48a",
          "body": null,
          "is_bot": false,
          "headline": "docs: add Codex CLI MCP config example",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b217522fbfbc2f5c331eadfe2ed239299f350943",
          "body": null,
          "is_bot": false,
          "headline": "docs: restore 'Why xdebug-mcp?' section with CLI-first framing",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "38627481cb544dbd2ee42a10ce365d429727ac9c",
          "body": null,
          "is_bot": false,
          "headline": "docs: drop Cursor/Windsurf name-dropping in favor of 'any MCP client'",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3f9b0a097d9e6fcbd5e3415a94e8b4357c149b6c",
          "body": "- Simplify tagline and Requirements to treat AI assistant as optional\n- Rename \"Setup AI Integration\" to \"(Optional) Wire up an AI assistant\"\n  and note CLI-only usage is fine\n- Add \"Schema-Backed JSON Output\" section showing $schema-tagged result\n  and pointing to docs/schemas/\n- Compress MCP Configuration copy\n- Drop trailing \"Why xdebug-mcp?\" meta-paragraph\n\nImages, badges, tool tables, and all xcompare examples are preserved.",
          "is_bot": false,
          "headline": "docs: trim MCP emphasis and add schema-backed output section",
          "author_name": "Akihito Koriyama",
          "author_login": "koriym",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a2bca9d1720303e74b0e8b9c910489984b9d6099",
          "body": "https://claude.ai/code/session_012Wa1b8asqLqrr321ibpPKF",
          "is_bot": false,
          "headline": "docs: Add --compare-with examples to README",
          "author_name": "Claude",
          "author_login": "claude",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "91c01f57fe1b6ad861613f0ceb2b10202b302e3b",
          "body": "Enables comparing variable states between current code and another git ref:\n  xcompare --break=file.php:25 --run=\"php test.php\" --compare-with=main\n\n- Creates temporary worktree for the target ref\n- Runs same command on both refs\n- Computes variable diff at breakpoint\n- Automatically cleans up worktree\n\nUse cases:\n- Compare before/after implementation\n- Debug regressions by comparing with main\n- Analyze behavior changes across commits\n\nhttps://claude.ai/code/session_012Wa1b8asqLqrr321ibpPKF",
          "is_bot": false,
          "headline": "feat: Add --compare-with mode for git ref comparison",
          "author_name": "Claude",
          "author_login": "claude",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "9865fdafa3e36129b80d6b4caf902fb4933705a0",
          "body": "- Use single-quoted '$schema' key in return type annotation\n- Add proper array shape types for executeXstep return type\n- Add proper array shape types for extract* method parameters\n- Remove unnecessary array_values() calls on array_keys() results\n\nhttps://claude.ai/code/session_012Wa1b8asqLqrr321ibpPKF",
          "is_bot": false,
          "headline": "Fix PHPStan errors in CompareRunner",
          "author_name": "Claude",
          "author_login": "claude",
          "committed_at": "2026-04-24T16:11:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 19,
      "commits_last_year": 1181,
      "latest_release_at": "2026-07-02T22:34:25Z",
      "latest_release_tag": "v0.11.1",
      "releases_from_tags": false,
      "days_since_last_push": 0,
      "active_weeks_last_year": 29,
      "days_since_latest_release": 24,
      "mean_days_between_releases": 19.2
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "has_description": true,
      "has_contributing": true,
      "health_percentage": 42,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": [
        {
          "name": "koriym/xdebug-mcp",
          "exists": true,
          "license": "MIT",
          "keywords": [
            "php",
            "debugging",
            "Xdebug",
            "trace",
            "profiling",
            "ai",
            "mcp"
          ],
          "ecosystem": "packagist",
          "matches_repo": true,
          "registry_url": "https://packagist.org/packages/koriym/xdebug-mcp",
          "is_deprecated": false,
          "latest_version": "v0.11.1",
          "repository_url": "https://github.com/koriym/xdebug-mcp",
          "versions_count": 19,
          "total_downloads": 31055,
          "dependents_count": 1,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": 4581,
          "first_published_at": null,
          "latest_published_at": "2026-07-02T22:33:35Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 24
        }
      ]
    },
    "popularity": {
      "forks": 9,
      "stars": 53,
      "watchers": 1,
      "fork_history": {
        "days": [
          {
            "date": "2025-08-29",
            "count": 1
          },
          {
            "date": "2025-09-13",
            "count": 1
          },
          {
            "date": "2025-10-24",
            "count": 1
          },
          {
            "date": "2025-12-07",
            "count": 1
          },
          {
            "date": "2026-01-29",
            "count": 1
          },
          {
            "date": "2026-02-04",
            "count": 1
          },
          {
            "date": "2026-02-25",
            "count": 1
          },
          {
            "date": "2026-03-03",
            "count": 1
          },
          {
            "date": "2026-06-15",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 9,
        "total_forks": 9
      },
      "star_history": null,
      "open_issues_and_prs": 1
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [
        "examples"
      ],
      "has_llms_txt": true,
      "has_dockerfile": true,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 143186,
      "source_files_sampled": 97,
      "oversized_source_files": 1,
      "agent_instruction_files": [
        "AGENTS.md",
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 34870
    },
    "dependencies": {
      "manifests": [
        "composer.json"
      ],
      "advisories": {
        "error": null,
        "scope": null,
        "source": null,
        "findings": [],
        "collected": false,
        "malicious": [],
        "truncated": false,
        "by_severity": {},
        "advisory_count": 0,
        "affected_count": 0,
        "assessed_count": 0,
        "malicious_count": 0,
        "assessed_package": null,
        "unassessed_count": 0,
        "direct_affected_count": 0
      },
      "ecosystems": [
        "packagist"
      ],
      "dependencies": [
        {
          "name": "symfony/polyfill-php83",
          "manifest": "composer.json",
          "ecosystem": "packagist",
          "version_constraint": "^1.33"
        },
        {
          "name": "amphp/socket",
          "manifest": "composer.json",
          "ecosystem": "packagist",
          "version_constraint": "^2.3"
        },
        {
          "name": "psr/log",
          "manifest": "composer.json",
          "ecosystem": "packagist",
          "version_constraint": "^3.0"
        },
        {
          "name": "amphp/http-server",
          "manifest": "composer.json",
          "ecosystem": "packagist",
          "version_constraint": "^3.4"
        }
      ],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 1,
        "merged_prs": 70,
        "open_issues": 0,
        "closed_ratio": 1,
        "closed_issues": 15,
        "closed_unmerged_prs": 5
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "koriym",
          "commits": 1091,
          "avatar_url": "https://avatars.githubusercontent.com/u/529021?v=4"
        },
        {
          "type": "User",
          "login": "MarjovanLier",
          "commits": 42,
          "avatar_url": "https://avatars.githubusercontent.com/u/2212059?v=4"
        },
        {
          "type": "User",
          "login": "claude",
          "commits": 38,
          "avatar_url": "https://avatars.githubusercontent.com/u/81847?v=4"
        },
        {
          "type": "User",
          "login": "o0h",
          "commits": 4,
          "avatar_url": "https://avatars.githubusercontent.com/u/907122?v=4"
        },
        {
          "type": "User",
          "login": "crishoj",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/20393?v=4"
        },
        {
          "type": "User",
          "login": "ruudk",
          "commits": 2,
          "avatar_url": "https://avatars.githubusercontent.com/u/104180?v=4"
        },
        {
          "type": "User",
          "login": "gmorel",
          "commits": 1,
          "avatar_url": "https://avatars.githubusercontent.com/u/2279794?v=4"
        }
      ],
      "contributors_sampled": 7,
      "top_contributor_share": 0.924
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "ci.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [
        "phpcs.xml",
        "phpstan.neon"
      ],
      "has_editorconfig": false,
      "has_linter_config": true,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 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": 10,
            "reason": "7 out of 7 merged PRs checked by a CI test -- score normalized to 10",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 7,
            "reason": "Found 7/10 approved changesets -- score normalized to 7",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 10,
            "reason": "project has 5 contributing companies or organizations",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "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": 0,
            "reason": "license file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 10,
            "reason": "30 commit(s) and 1 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": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": null,
            "reason": "no dependencies found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "SAST tool is not run on all commits -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "7868a08835afecf19fa1f8f3f5d4869016de74ea",
        "ran_at": "2026-07-27T22:13:12Z",
        "aggregate_score": 4.7,
        "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-02T22:34:05Z",
      "oldest_open_prs": [
        {
          "number": 91,
          "created_at": "2026-07-27T22:07:04Z",
          "last_comment_at": "2026-07-27T22:07:26Z",
          "last_comment_author": "coderabbitai"
        }
      ],
      "last_merged_pr_at": "2026-07-02T22:13:06Z",
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/koriym/xdebug-mcp",
    "host": "github.com",
    "name": "xdebug-mcp",
    "owner": "koriym"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "moderate",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 68,
      "inputs": {
        "security": 47,
        "vitality": 90,
        "community": 42,
        "governance": 69,
        "engineering": 82
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "excellent",
        "name": "Vitality",
        "value": 90,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "good",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "commits_last_year": 1181,
              "human_commit_share": 1,
              "days_since_last_push": 0,
              "active_weeks_last_year": 29
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 0 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 0
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "29/52 weeks with commits",
                "points": 20.1,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 29
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "1181 commits in the last year",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 1181
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "releases_count": 19,
              "latest_release_tag": "v0.11.1",
              "releases_from_tags": false,
              "days_since_latest_release": 24,
              "mean_days_between_releases": 19.2
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "19 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 19
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 24 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 24
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "a release every ~19.2 days",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "release_cadence",
                    "params": {
                      "gap": 19.2
                    }
                  }
                ],
                "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": "maintained",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": null,
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": 24,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "last human commit 24 days ago",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_maintained",
                    "params": {
                      "days": 24
                    }
                  }
                ],
                "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": 42,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "at_risk",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 35,
            "inputs": {
              "forks": 9,
              "stars": 53,
              "watchers": 1,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "53 stars",
                "points": 27.8,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 53
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "9 forks",
                "points": 7.5,
                "status": "partial",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 9
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "1 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "at_risk",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 45,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "has_contributing": true,
              "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": "no license file detected",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "license_absent",
                    "params": {}
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributing_guide",
                "name": "CONTRIBUTING guide",
                "detail": null,
                "points": 18,
                "status": "met",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 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": null,
            "notes": [],
            "value": 51,
            "inputs": {
              "packages": [
                "koriym/xdebug-mcp"
              ],
              "dependents": 1,
              "ecosystems": "packagist",
              "total_downloads": 31055,
              "monthly_downloads": 4581
            },
            "components": [
              {
                "key": "monthly_downloads",
                "name": "Monthly downloads",
                "detail": "4,581 downloads/month across packagist",
                "points": 48.8,
                "status": "partial",
                "details": [
                  {
                    "code": "downloads_monthly",
                    "params": {
                      "count": 4581,
                      "ecosystems": "packagist"
                    }
                  }
                ],
                "max_points": 80
              },
              {
                "key": "registry_dependents",
                "name": "Registry dependents",
                "detail": "1 packages depend on it",
                "points": 2,
                "status": "partial",
                "details": [
                  {
                    "code": "registry_dependents",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "moderate",
        "name": "Sustainability & Governance",
        "value": 69,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "at_risk",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 30,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 7,
              "top_contributor_share": 0.924
            },
            "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 92% of commits",
                "points": 1.7,
                "status": "partial",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 92
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "7 contributors",
                "points": 9.5,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 7
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "excellent",
            "name": "Issue & PR responsiveness",
            "note": null,
            "notes": [],
            "value": 93,
            "inputs": {
              "merged_prs": 70,
              "open_issues": 0,
              "closed_issues": 15,
              "issue_closed_ratio": 1,
              "closed_unmerged_prs": 5
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "100% of issues closed",
                "points": 46.8,
                "status": "met",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "70/75 decided PRs merged",
                "points": 35.7,
                "status": "partial",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 70,
                      "decided": 75
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 7/10 approved changesets -- score normalized to 7",
                "points": 10.5,
                "status": "partial",
                "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": 66,
            "inputs": {
              "followers": 261,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "koriym",
              "public_repos": 255,
              "account_age_days": 5699
            },
            "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": "261 followers of koriym",
                "points": 17.4,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 261,
                      "login": "koriym"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "255 public repos, account ~15 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 255
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 15
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "packages": [
                "koriym/xdebug-mcp"
              ],
              "ecosystems": "packagist",
              "any_deprecated": false,
              "min_days_since_publish": 24
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on packagist",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "packagist"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 24 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 24
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "19 published versions",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 19
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "good",
        "name": "Engineering Quality",
        "value": 82,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "good",
            "name": "Engineering practices",
            "note": null,
            "notes": [],
            "value": 84,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": true,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "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": 24,
                "status": "met",
                "details": [],
                "max_points": 24
              },
              {
                "key": "linter_config",
                "name": "Linter config",
                "detail": "phpcs.xml, phpstan.neon",
                "points": 16,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "phpcs.xml, phpstan.neon"
                    }
                  }
                ],
                "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": "7 out of 7 merged PRs checked by a CI test -- score normalized to 10",
                "points": 20,
                "status": "met",
                "details": [],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 80,
            "inputs": {
              "topics": [],
              "has_wiki": false,
              "homepage": "https://packagist.org/packages/koriym/xdebug-mcp",
              "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://packagist.org/packages/koriym/xdebug-mcp",
                "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 47,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "dangerous_workflow",
                    "packaging",
                    "pinned_dependencies",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 47,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 13,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 5,
              "scorecard_aggregate": 4.7
            },
            "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": "7 out of 7 merged PRs checked by a CI test -- score normalized to 10",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 7/10 approved changesets -- score normalized to 7",
                "points": 5.2,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 5 contributing companies or organizations",
                "points": 2.5,
                "status": "met",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "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 not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "30 commit(s) and 1 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 not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "SAST tool is not run on all commits -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "0 existing vulnerabilities detected",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "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": 8
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 66,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "has_llms_txt": true,
              "legible_history_share": 0.92,
              "agent_instruction_files": [
                "AGENTS.md",
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 34870
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "AGENTS.md, CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "AGENTS.md, CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": "llms.txt present",
                "points": 15,
                "status": "met",
                "details": [
                  {
                    "code": "llms_txt_present",
                    "params": {}
                  }
                ],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "92 of 100 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 92,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "moderate",
            "name": "Verify loop (build / test / typecheck)",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_pinned_dependencies"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 54,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": true,
              "typed_language": false,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": true,
              "typecheck_configs": [],
              "agent_commit_share": 0.03,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": "phpcs.xml, phpstan.neon",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "phpcs.xml, phpstan.neon"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "Dockerfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Dockerfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "3 of the last 100 commits agent-authored or agent-credited",
                "points": 6,
                "status": "partial",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 3,
                      "sampled": 100
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "moderate",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 54,
            "inputs": {
              "primary_language": "PHP",
              "largest_source_bytes": 143186,
              "source_files_sampled": 97,
              "oversized_source_files": 1
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "PHP without a type-check config",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_typecheck_config_language",
                    "params": {
                      "language": "PHP"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "1/97 source files over 60KB",
                "points": 54.4,
                "status": "partial",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 97,
                      "oversized": 1
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          },
          {
            "key": "ai_interfaces",
            "band": "at_risk",
            "name": "Machine-readable interfaces",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "example_dirs": [
                "examples"
              ],
              "has_mcp_signal": false,
              "api_schema_files": []
            },
            "components": [
              {
                "key": "api_schema_openapi_graphql_proto",
                "name": "API schema (OpenAPI/GraphQL/proto)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 40
              },
              {
                "key": "mcp_server",
                "name": "MCP server",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 20
              },
              {
                "key": "runnable_examples",
                "name": "Runnable examples",
                "detail": "examples",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "examples"
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? 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-27T22:13:28.367084Z",
  "schema_version": "0.27.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/k/koriym/xdebug-mcp.svg",
  "full_name": "koriym/xdebug-mcp",
  "license_state": "absent",
  "license_spdx": null
}

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

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

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