Öffentliches Register
Software-GesundheitsberichtSchema 0.26.0 · Metriken 1.13.0 · 2026-07-22 07:23 UTC

xdfnet / iRelay

Codex ↔ DeepSeek 本机中转服务

SwiftKeine Lizenz erkannt★ 0 Sterne⑂ 0 Forksseit Juni 2026Auf GitHub ansehen ↗

xdfnet/iRelay erreicht einen Gesundheitsindex von 38 von 100 und liegt damit im Bereich Gefährdet. Am stärksten schneidet es bei Engineering Quality (66/100) ab, am schwächsten bei Community & Adoption (12/100). Zuletzt vor 1 Tag aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

38
gesamt / 100
Gefährdet

Software-Gesundheitsindex

Metriken werden auf einer Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr Mittel; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze 49 (Gefährdet). AI Readiness liegt außerhalb.

38
Exzellent85-100Vorbildlich; erfüllt im Wesentlichen alle geprüften Kriterien
Gut70-84Gesund; geringfügige Lücken
Mittel50-69Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Gefährdet30-49Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-29Schwerwiegende Probleme (aufgegeben, nur ein Maintainer, keine Hygiene)
VitalitätCommunity &VerbreitungNachhaltigkeit &GovernanceEngineering-QualitätSicherheitAI Readiness

Bewertungsprofil

Jede Achse ist eine Kategorie. Die Form zählt mehr als der Durchschnitt — ein gesundes Projekt füllt die gesamte Fläche, während ein Profil aus Spitzen und Kratern bedeutet, dass Stärke in einer Dimension Risiken in einer anderen verdeckt.

Eigentümerschaft

DavidPersönliches Konto
10 Follower9 öffentliche Reposseit Juli 2020

Dieses Repository gehört einem persönlichen Konto. Ein Projekt mit nur einem Eigentümer trägt ein höheres Kontinuitätsrisiko als ein organisationsgetragenes.

Metriken nach Kategorie

Vitalität

Lebt das Projekt — wird Code geschrieben und werden Releases ausgeliefert?

64Mittel · 22 % des Gesamtindex
Wie die Bewertung erfolgt
36/36Push-Aktualität — letzter Push vor 1 Tagen
4.2/36Commit-Rhythmus — 6/52 Wochen mit Commits
16.2/18Commit-Volumen — 62 Commits im letzten Jahr
0/10OpenSSF Scorecard: Maintained — project was created within the last 90 days. Please review its contents carefully
Verwendete Eingangsdaten
commits_last_year62
human_commit_share1
days_since_last_push1
active_weeks_last_year6
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 1 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 1 Tagen
12.6/27Release-Rhythmus — Rhythmus unbekannt (nur ein Release)
0/10OpenSSF Scorecard: Signed-Releases — Project has not signed or included provenance with any releases.
Verwendete Eingangsdaten
releases_count1
latest_release_tagv2.2.0
releases_from_tagsnein
days_since_latest_release1
mean_days_between_releases

Community & Verbreitung

Hat das Projekt Nutzer, Downloads, Aufmerksamkeit und ein einladendes Umfeld für Beitragende?

12Kritisch · 18 % des Gesamtindex
Wie die Bewertung erfolgt
0/60Stars — 0 Stars
0/25Forks — 0 Forks
0/15Watcher — 0 Watcher
Verwendete Eingangsdaten
forks0
stars0
watchers0
growth_stateunverified
growth_factor_pct100
growth_unverified_reasonno_history
Wie die Bewertung erfolgt
22.5/22.5README
0/22.5Lizenz — keine Lizenzdatei erkannt
0/18CONTRIBUTING-Leitfaden
0/13.5Verhaltenskodex
0/7.2Issue-Vorlage
0/6.3PR-Vorlage
Verwendete Eingangsdaten
has_readmeja
has_licensenein
has_contributingnein
has_issue_templatenein
has_code_of_conductnein
has_pull_request_templatenein

Nachhaltigkeit & Governance

Überdauert das Projekt die Menschen, die es tragen — Bus-Faktor, Reaktionsfähigkeit, Trägerschaft und Paketpflege?

18Kritisch · 24 % des Gesamtindex
Wie die Bewertung erfolgt
9/54Bus-Faktor — 1 Beitragende decken die Hälfte aller Commits ab
0/22.5Commit-Verteilung — wichtigste beitragende Person verfasste 100 % der Commits
1.4/13.5Breite der Beitragenden — 1 Beitragende
0/10OpenSSF Scorecard: Contributors — project has 0 contributing companies or organizations -- score normalized to 0
Verwendete Eingangsdaten
bus_factor1
contributors_sampled1
top_contributor_share1
Wie die Bewertung erfolgt
0/46.8Issue-Lösungsquote — keine Issues oder keine Daten
0/38.3PR-Annahme — 0/1 entschiedene PRs gemergt
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
merged_prs0
open_issues0
closed_issues0
issue_closed_ratio
closed_unmerged_prs1
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Issue-Lösungsquote. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
10/30Organisatorische Trägerschaft — persönliches (Nutzer-)Konto
0/20Verifizierte Domain — für Nutzerkonten nicht anwendbar
7.5/25Reichweite des Inhabers — 10 Follower von xdfnet
19.3/25Kontohistorie — 9 öffentliche Repos, Kontoalter ca. 6 Jahre
Verwendete Eingangsdaten
followers10
owner_typeUser
is_verified
owner_loginxdfnet
public_repos9
account_age_days2.201
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Verifizierte Domain. Die verbleibenden Gewichte wurden renormalisiert.

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

66Mittel · 20 % des Gesamtindex
Wie die Bewertung erfolgt
24/24CI-Workflows — 1 Workflow(s)
24/24Tests vorhanden
0/16Linter-Konfiguration
0/9.6Pre-Commit-Hooks
0/6.4.editorconfig
0/20OpenSSF Scorecard: CI-Tests — keine Daten
Verwendete Eingangsdaten
has_cija
has_testsja
has_editorconfignein
has_linter_confignein
has_precommit_confignein
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: CI-Tests. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
30/30README
25/25Dokumentationsverzeichnis
0/15Dokumentations-/Homepage-Site
10/10Repository-Beschreibung
0/10Topics
10/10Wiki
Verwendete Eingangsdaten
topics
has_wikija
homepage
has_readmeja
has_docs_dirja
has_descriptionja

Sicherheit

Sind die sichtbaren Sicherheits- und Lieferkettenpraktiken belastbar, ohne ungeklärte Exposition gegenüber Hochrisikojurisdiktionen?

26Kritisch · 16 % des Gesamtindex

Sicherheitslage

26Kritisch
Wie die Bewertung erfolgt
7.5/7.5Binary-Artifacts — no binaries found in the repo
0/7.5Branch-Protection — branch protection not enabled on development/release branches
0/2.5CI-Tests — keine Daten
0/2.5CII-Best-Practices — no effort to earn an OpenSSF best practices badge detected
0/7.5Code-Review — Found 0/30 approved changesets -- score normalized to 0
0/2.5Contributors — project has 0 contributing companies or organizations -- score normalized to 0
10/10Dangerous-Workflow — no dangerous workflow patterns detected
0/7.5Dependency-Update-Tool — no update tool detected
0/5Fuzzing — project is not fuzzed
0/2.5Lizenz — license file not detected
0/7.5Maintained — project was created within the last 90 days. Please review its contents carefully
0/5Packaging — keine Daten
0/5Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — Project has not signed or included provenance with any releases.
0/7.5Token-Permissions — detected GitHub workflow tokens with excessive permissions
7.5/7.5Vulnerabilities — 0 existing vulnerabilities detected
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated16
scorecard_versionv5.5.0
checks_inconclusive2
scorecard_aggregate2,6
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): ci_tests, packaging. Die verbleibenden Gewichte wurden renormalisiert.

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Ein unabhängiges, experimentelles Badge — Gewicht 0,0, es wird eigenständig ausgewiesen und verändert den Gesamt-Gesundheitswert nicht.

52Mittel · 0 % des Gesamtindex
Wie die Bewertung erfolgt
0/45Agentenanweisungen — keine CLAUDE.md / AGENTS.md / Editor-Regeln
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 61 von 62 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share0,984
agent_instruction_files
agent_instruction_max_bytes
Wie die Bewertung erfolgt
0/18Bootstrap mit einem Befehl
22/22Automatisierte Tests
0/11Lint-/Format-Konfiguration
11/11Statische Typprüfung — Swift (statisch typisiert)
0/10Reproduzierbare Umgebung
10/10Belegte Agentenpraxis — 47 der letzten 62 Commits von Agenten verfasst oder ihnen zugeschrieben
0/8Automatisierte Wartung — keine automatisierten Abhängigkeits-Updates beobachtet
0/10OpenSSF Scorecard: Pinned-Dependencies — dependency not pinned by hash detected -- score normalized to 0
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfiles
has_dockerfilenein
typed_languageja
bootstrap_files
has_devcontainernein
has_linter_confignein
typecheck_configs
agent_commit_share0,758
toolchain_manifests
dependency_bot_commit_share0
Wie die Bewertung erfolgt
45/45Typprüfbarer Code — Swift (statisch typisiert)
55/55Handhabbare Dateigrößen — 0/14 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languageSwift
largest_source_bytes36.857
source_files_sampled14
oversized_source_files0

Eckdaten

0GitHub-Sterne
1Mitwirkende
62Commits, letzte 12 Monate
1Tage seit letztem Push
1Releases
1Bus-Faktor
0offene Issues
Paket-Ökosysteme

Warnungen zur Datenerhebung

  • GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

Weitere Details

OpenSSF Scorecard 2.6 / 10
2.6Gesamtwert

Unabhängige, werkzeugneutrale Sicherheitsbewertung durch das quelloffene OpenSSF Scorecard. Jede Prüfung honoriert eine Sicherheits-Praxis, nicht das Werkzeug eines bestimmten Anbieters. Prüfungen, die Scorecard nicht ermitteln konnte, sind mit k. A. markiert und vom Sicherheitswert ausgeschlossen (nie als null gezählt).Scorecard v5.5.0 · 2026-07-22 07:23 UTC

10Binary-Artifactsno binaries found in the repo
0Branch-Protectionbranch protection not enabled on development/release branches
k. A.CI-Testsno pull request found
0CII-Best-Practicesno effort to earn an OpenSSF best practices badge detected
0Code-ReviewFound 0/30 approved changesets -- score normalized to 0
0Contributorsproject has 0 contributing companies or organizations -- score normalized to 0
10Dangerous-Workflowno dangerous workflow patterns detected
0Dependency-Update-Toolno update tool detected
0Fuzzingproject is not fuzzed
0Licenselicense file not detected
0Maintainedproject was created within the last 90 days. Please review its contents carefully
k. A.Packagingpackaging workflow not detected
0Pinned-Dependenciesdependency not pinned by hash detected -- score normalized to 0
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
0Signed-ReleasesProject has not signed or included provenance with any releases.
0Token-Permissionsdetected GitHub workflow tokens with excessive permissions
10Vulnerabilities0 existing vulnerabilities detected
Alle Abhängigkeiten nicht erhoben

Der aufgelöste Abhängigkeitssatz konnte für diesen Bericht nicht erhoben werden: GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository

JSON-Rohbericht maschinenlesbar
{
  "data": {
    "repo": {
      "topics": [],
      "is_fork": false,
      "size_kb": 2175,
      "has_wiki": true,
      "homepage": null,
      "languages": {
        "Shell": 2037,
        "Swift": 101262
      },
      "pushed_at": "2026-07-20T16:43:44Z",
      "created_at": "2026-06-14T13:41:27Z",
      "owner_type": "User",
      "updated_at": "2026-07-20T16:43:48Z",
      "description": "Codex ↔ DeepSeek 本机中转服务",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": null,
      "primary_language": "Swift",
      "significant_languages": [
        "Swift"
      ]
    },
    "owner": {
      "blog": null,
      "name": "David",
      "type": "User",
      "login": "xdfnet",
      "company": null,
      "location": "Beijing.China",
      "followers": 10,
      "avatar_url": "https://avatars.githubusercontent.com/u/68147460?v=4",
      "created_at": "2020-07-11T09:51:56Z",
      "is_verified": null,
      "public_repos": 9,
      "account_age_days": 2201
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [
        {
          "tag": "v2.2.0",
          "kind": "minor",
          "published_at": "2026-07-20T11:18:37Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "e653d5cf8a92cd2c87843d188aae1e8586d9e5da",
          "body": "- 黑色渐变底 + 饱和天蓝 house.fill 符号,居中略偏上\n- 新增 Scripts/gen_icon.swift 生成脚本,便于后续调整\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "更新 App 图标为 house.fill 设计",
          "author_name": "David",
          "author_login": "xdfnet",
          "committed_at": "2026-07-20T16:43:41Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9137aa127764d4a77f1250ce8122bbfb93428976",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to 2.2.0",
          "author_name": "David",
          "author_login": "xdfnet",
          "committed_at": "2026-07-12T12:04:34Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "1d3536e53a4b547ca79e39821a7a26478100eb97",
          "body": null,
          "is_bot": false,
          "headline": "fix: App 路径从 Codex.app 改为 ChatGPT.app",
          "author_name": "David",
          "author_login": "xdfnet",
          "committed_at": "2026-07-12T11:58:49Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "cee5149f4406f3b5a5821d253e7feb5a9b47b665",
          "body": "深蓝紫渐变背景 + 白色 r.circle.fill 符号。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: App 图标改为 SF Symbol r.circle.fill",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-07-03T07:35:45Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9ecee406dda5845899b7816b79f79972f47bf82c",
          "body": "双节点数据流转发图标,深蓝紫渐变底色 + 白色中继符号。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: 重新设计 App 图标",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-07-03T07:33:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "65b37e22654f091af349f383d66dbfb106218dba",
          "body": "Codex CLI 已将 Max 作为 first-class reasoning effort,\niRelay model catalog 同步添加。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: 模型目录新增 Max 推理等级",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-07-03T07:32:05Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9d00fc086cdf280e026e8458fa7c18459846dc79",
          "body": "- 修复:CodexAppPatcher 原始字符串 s → l 适配新版 Codex 0.142.x\n- 文档:README 新增 Codex 兼容性表格,写明版本支持范围\n- 版本号统一更新到 2.1.12\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump to v2.1.12, 适配新版 Codex asar 变量名",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-27T08:35:50Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d48bf3af73329d08207f1c6592cfaa1930cbc5aa",
          "body": "每次点开菜单同步查询 /user/balance,实时显示不退缓存\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: 菜单显示 DeepSeek 账户余额",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-25T12:42:18Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "82b7d1c164bff85473976c9376800334a89fa28e",
          "body": "解决下拉框对齐偏移问题。菜单改为点击时动态构建 NSMenu,\n用完释放,锚点跟随图标。\n\n新增 MenuBarController.swift,删除 MenuBarView.swift。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 菜单栏从 SwiftUI MenuBarExtra 改为 AppKit NSStatusItem",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-25T12:32:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9a07ce9a125371f2b82497800b4330bf47531988",
          "body": "- supported_reasoning_levels 增加 ultra(智能协作)\n- reasoning_effort 完全透传 DeepSeek,不做额外映射\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: 模型目录新增 Ultra 推理等级,移除多余映射",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-25T12:13:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3382ebe857c77fec8dce685d8c28e5ac28421128",
          "body": "与 Codex 自家模型(gpt-5.5、gpt-5.4-mini)的默认行为对齐\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: DeepSeek 模型默认推理等级改为 medium",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-25T10:40:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d3b48c4ed053add313df3306cab83b78db44b99e",
          "body": "responsesToChatPayload 直接取 body['model'] 原始值,\n未经过 resolveModel 转换,导致 gpt-5.4-mini 等非\nDeepSeek 模型发往上游时被拒(400)。\n\n在 responsesToChatPayload 中用 Self.resolveModel()\n替换裸读 body['model'],与 handleResponses 的日志\n层对齐。\n\nbump v2.1.7\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: 模型重写未生效——payload 中 model 仍用原始名",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-25T10:23:04Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1bc38fdf2f06677178be15391929c9031ec6f677",
          "body": "Co-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 推理模式改为开启/关闭推理,菜单语义统一",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-25T09:40:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b302d777049209b57aceb92b5d0dd475ef55f10f",
          "body": "Co-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 集成→代理,与补丁解耦后语义更准确",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-25T09:36:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "920b5f4f75c5a5e1d2cf137a63c415ea2a04483b",
          "body": "- 集成开关不再自动打补丁,各自独立控制\n- 新增「开启补丁/关闭补丁」菜单项(含状态检测)\n- 操作前检测 App 管理权限,未授权弹窗引导\n- 更新 README 反映新菜单结构和操作流程\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: 补丁与集成完全解耦,独立菜单开关+权限前置检查",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-25T09:35:21Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "24f70d5294a5425c5affaec9e19c16c8dd5350b1",
          "body": "- RelayState 新增 activeRequestCount 追踪活跃请求数\n- RelayHandler 添加 onRequestActive/onRequestInactive 回调\n- 菜单栏图标用 SF Symbol 交替(circle.fill ⇄ circle)实现闪烁\n- 禁用状态使用 slash.circle.fill,无数据流时固定 circle.fill\n- 停止服务时自动归零请求计数\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: 菜单栏图标在有数据流时闪烁",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-24T06:36:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f98ec100092f2e5495835bbcd130acfc581bd781",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to 2.1.4",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T07:02:55Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7d36ec7cf6fe61ea41e525af9d8eb3e787b99b6f",
          "body": "- 移除模型切换相关描述\n- 使用步骤简化(开启集成 → 自动完成)\n- 架构图更新为当前菜单结构\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: 更新 README 反映菜单精简",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T07:02:33Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "76e3bf2cb8dcf92c4ef7ac2b095bc016b7f0b20c",
          "body": "Co-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: bump version to 2.1.3",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T07:00:55Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "34bfac77cd0eb931b0f9fbccafb282e9109885e6",
          "body": "ensurePatched() 先查 asar 状态:\n  已打补丁 → return true,不动备份\n  未打 → 删旧备份 → 备份原始 asar → 打补丁\n\n确保 restoreFromBackup() 还原的永远是原始版本。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: 仅首次打补丁时创建备份,已打好不动备份",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T06:50:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "24d5c867c72cb10690c72318663f4335ab38a3e1",
          "body": "ensurePatched() 先备份 app.asar → app.asar.bak,再打补丁。\n备份留在磁盘上:\n- enable 写配置失败 → restoreFromBackup() 还原\n- disable → restoreFromBackup() 还原 + 删备份 + 清配置\n\n备份文件不依赖内存,进程崩溃也能恢复。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: asar 回滚改为文件备份方式",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T06:48:48Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "149f25be0372323708cb11d8eb75d11bb390368e",
          "body": "disable():\n  ① 还原 asar(patched → original,反向等长替换)\n  ② 清 config.toml\n  ③ 删 model catalog\n\n每一步失败都中止,不回退上一步(但已做的事不影响下一轮)。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: 关闭集成时还原 asar,不留痕迹",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T06:46:06Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b46347999482cf94b261a29069c99762985fbb60",
          "body": "enable():\n  ① 缓存原始 asar\n  ② 打补丁 → 失败 → ❌(没改任何东西)\n  ③ 写配置 → 失败 → 🔄 写回原始 asar → ❌\n  ④ 成功 ✅\n\n回滚需要先读取 asar 权限,和打补丁一样——如果回滚写入也失败,\n至少比现在半残状态好(原版 asar 已有补丁 vs 配置没写)。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: 启用集成改为事务式,失败自动回滚",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T06:43:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "58e3cbe66335abb6e9a4ba7dda488af333a1236c",
          "body": "Button(\"中文\") 和 Text(\"中文\") 会被 Swift 6.3 -O\n当作 LocalizedStringKey 优化掉。改用 Text(verbatim:)\n显式指定 String 类型,绕过优化器。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: release 编译字符串被优化掉的问题",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T06:37:42Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "37ea0464125402921174d02c6c9b2b113d8f45e7",
          "body": "CodexAppPatcher 只剩 55 行:\n- applyPatch() 读→替换→写回\n- 失败弹窗引导授权\n\n没有守护线程、没有备份、没有探针写入、没有权限状态缓存。\n用户开启集成时检查权限,失败弹窗,成功后不管。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 彻底精简,删除 guard 轮询",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T06:33:24Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3d3a426d1d49e9120247ce371f79cd7795ccfad9",
          "body": "- 去掉备份/还原/探针写入等复杂逻辑\n- applyPatch() 只做一件事:读→替换→写→返回成败\n- 弹窗仅启动时用户主动开启集成时触发\n- init() 只启动服务器,不碰补丁\n- guard 60s 静默重试,处理 Codex 升级场景\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 精简 CodexAppPatcher + 启动不做多余事",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T06:32:19Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8d4820fb3be627df1d98ee7dc540c421ed7cdfb0",
          "body": "菜单精简为:\n  开启/关闭 Codex 集成\n  ─────\n  推理模式 ✓\n  ─────\n  设置密钥\n  打开日志\n  ─────\n  退出\n\ntoggleCodex() 自动设 model = deepseek-v4-pro\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 去掉模型选择菜单,开启集成默认 pro",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T06:17:29Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0c31311c6eabf7dcc13b448fb214514fe5cfd7a1",
          "body": "Image(systemName:) 在 MenuBarExtra 下可能不渲染,\n改用 Text(\"✓\") 确保始终可见\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: 菜单对勾改为文本符号",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T06:11:34Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3e1d19917da4240dd461b62d064c00d92bd45933",
          "body": "RelayState.init() 新增 syncCodexConfig() 调用,\n确保重启时补丁状态被检查,权限不通则阻断引导。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: App 重启后自动触发补丁检查",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:55:51Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6c823ce4338051eb07f67efcaa8671b32e95cdb0",
          "body": "ensurePatched() 遇到 EPERM → 阻塞主线程循环弹窗:\n  -「打开系统设置」→ 跳转 → 自动重试补丁\n  -「退出 iRelay」→ 终止 App\n  不授权别想用。\n\n启动成功后 guard 只 stat mtime + 重打补丁,不再涉及权限。\napplyPatch() 不再区分 notify,永远静默。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 启动时权限阻断,启动后不关心权限",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:52:47Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2412ce1ba10b7072ec7ce9f41e9abcb6a3c9d27c",
          "body": "applyPatch(notify:) 是唯一写 asar 的地方:\n- notify=true(首次):失败弹窗引导\n- notify=false(guard):静默重试,不下轮\n\n后台线程 stat → mtime 变了再走 applyPatch。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 精简补丁逻辑,统一核心方法",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:48:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4d080d0b31479c3c0895cdcf3633804077f08dbc",
          "body": "每 60 秒只 stat 一次 asar mtime(不读内容),\nmtime 没变(Codex 没升级)直接跳过,零磁盘 IO。\nmtime 变了才读 155MB asar 验补丁+重打。\n权限探测内联到确保补丁的写入步骤,不再单独 probe 写回。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "perf: guard 循环改为 stat 驱动",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:46:07Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "97a5c719e8cdea541a109dd1f241fb1661b85b38",
          "body": "每 10 秒依次做两件事,各自独立互不影响:\n\n1. checkPermission() — 轻量写入探测 App 管理权限\n   缺权限时弹 NSAlert(防重复),引导用户打开系统设置\n   点「打开系统设置」跳转隐私→App 管理面板\n\n2. ensurePatchIntact() — 读 asar 验证补丁完整性\n   补丁丢了(Codex 升级)→ 自动重打\n\n与 iVox 的权限轮询模式一致。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: guard 循环改为 10 秒双检查",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:38:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6aa2a3acb81d858df076109bb5c7540e80a38e39",
          "body": "补丁写入被系统拒绝时(EPERM/EACCES)弹出 NSAlert:\n- 标题:「需要 App 管理权限」\n- 正文:引导前往 系统设置 → 隐私与安全性 → App 管理\n- 按钮:「打开系统设置」→ 跳转对应面板\n- 按钮:「稍后」→ 关闭,guard 后台继续等\n\n仅初始 ensurePatched() 弹一次,guard 循环静默重试。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: 权限不足时弹窗引导用户",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:34:44Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d31e98a6cdcd37b9e4b2886d953ce8a2cf1e77ac",
          "body": "启用:打补丁→写配置,写配置失败时还原 asar\n关闭:还原 asar→清配置,清配置失败时重打补丁\n任一失败均回滚到操作前状态,不产生半残状态\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 启用/关闭全链路回滚",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:31:03Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a2d30533fc0dd06761071f8e2aaab2c50a2d676f",
          "body": "启用:先打补丁(权限检查)→ 成功后才写配置 → 全做完\n关闭:先还原补丁(权限检查)→ 成功后才清配置 → 全做完\n\n任一前置步骤失败则中止,不产生半应用状态。\nguard 线程生命周期由 enable/disable 显式管理。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor: 启用/关闭流程改为事务式",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:29:58Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3a2e6e146fd9daaa79d5befc169f8b077ebd2ab6",
          "body": "ensurePatched() 无论成败都启动 guard 线程,每 60 秒检查\n一次 asar 补丁完整性。Codex 升级后 asar 被还原时,guard\n能在下一轮检测到并自动重打补丁。\n\n同时替代了之前的权限轮询逻辑(职责合并)。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: 后台守护线程持续验证 Codex 补丁",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:24:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f767ef6d51e72644ee139f76cfde81875df67856",
          "body": "仿 iVox 模式,Codex App 补丁写入失败时(EPERM/EACCES),\n每 5 秒轮询重试,权限就绪后自动打补丁。\n解决 Codex 每次升级后补丁失效的问题。\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: 添加 App 管理权限轮询机制",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:21:25Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d0ce2accde21eec4a3b164c8123660710e161036",
          "body": "ad-hoc 签名下 entitlements 不生效,删掉保持简洁\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: 移除无实际约束的 entitlements",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:14:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d7def4152b04efe3df56ed7660aecc590768dbfd",
          "body": "Co-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: 签名简化为纯 ad-hoc",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:12:35Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ac8d9f6b319de741018a36560afd5f043e681677",
          "body": "- 新增 Resources/iRelay.entitlements,显式声明 network.server/client、\n  files.user-selected 权限,适配 Hardened Runtime\n- build.sh:自动查找有效签名证书(不再硬编码已吊销的证书)、\n  启用 Hardened Runtime(--options runtime)、使用 entitlements 文件签名\n- Info.plist 版本号同步至 2.1.3\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: 完善权限配置与签名流程",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:11:27Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "86799df796e57998848de6ec66d1dfb52bd2f2a2",
          "body": "为 DeepSeek 编写更贴合代码助手场景的系统指令,涵盖\n1M 上下文窗口、推理等级、工具调用等关键能力描述\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: 升级 model catalog base_instructions",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:09:54Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7d65c2510a69d85849bacc79bbe827e667b1e961",
          "body": "- model catalog 新增 auto_compact_token_limit / web_search_tool_type /\n  xhigh 推理等级 / supports_reasoning_summaries / support_verbosity\n- app.asar 补丁重打(Codex v26.616 验证通过)\n- 修复 Swift 6.3 编译器访问控制变更导致的构建失败\n\nCo-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: 适配 Codex 最新升级",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-21T05:08:32Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "c303ddb2438bbc452dcaf312dd5eb3dab0ddf6a6",
          "body": "Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: 开发证书吊销时自动降级 ad-hoc 签名",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-19T14:08:15Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7a9e3a4ccd9431db193a81c16f907e99f1f42281",
          "body": "Co-Authored-By: Claude <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: 菜单栏按钮文案调整 '密钥设置...' → '设置密钥'",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T09:41:39Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1a210ee993641e49628d718152c160273eb1417a",
          "body": "- Codex 集成开关移至菜单顶部\n- 从 Git 追踪移除 iRelay.app(已在 .gitignore)",
          "is_bot": false,
          "headline": "chore: bump version to 2.1.2",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T07:11:07Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b4470f1d74a5b55050805eeace1d93a25e9e4856",
          "body": "- 菜单重构:模型平铺、推理模式改切换、密钥移出一级\n- 新增 toggleCodex():一键开关 Codex 集成\n- build.sh:改用开发者证书签名,自动安装+清除隔离属性",
          "is_bot": false,
          "headline": "chore: bump version to 2.1.1",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T07:06:30Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "acecbeda53e0e96636a17662b67d28f9d19c8f88",
          "body": null,
          "is_bot": false,
          "headline": "chore: bump version to 2.1.0",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:53:02Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "472e7f45fc9e2eecfc50b1d1bd7310e08a2b9c1d",
          "body": "- 更新 README.md:移除多提供商/端口配置,模型切换/思考/Chat 透传\n- 更新 ARCHITECTURE.md 到 v2.1.0:纯 DeepSeek + 固定端口 + Chat 透传\n- 新增 Doc/API.md:完整对外 API 文档(4 个端点/请求/响应/流式格式)\n- Logger: 消息日志显示 (N chars): preview\n- MenuBarView: 文字精简",
          "is_bot": false,
          "headline": "doc: 更新文档并补充 API 文档",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:51:25Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b438681e3faf6f09ec9f98e6e2cf5086eaba7f0e",
          "body": null,
          "is_bot": false,
          "headline": "chore: 移除端口配置,固定 8787",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:40:42Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "a5d104e2afeec61c4d631a57fb8a12c9f7124ca4",
          "body": "删除 ProviderStore,RelayState 恢复直接持有 apiKey/model/thinking\nCodexConfigManager 恢复 enable(model:port:)\nMenuBarView/iRelayApp 去掉提供商管理,仅保留模型/模式/端口/Key\nsetThinking 通过更新 handler.provider.thinkingMode 生效",
          "is_bot": false,
          "headline": "refactor: 移除多提供商,回到纯 DeepSeek",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:38:41Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "17215e52e03e6b91bae0ac30e9960cd2ef26ccd8",
          "body": null,
          "is_bot": false,
          "headline": "chore: 移除 handleChatCompletions 未使用变量",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:29:22Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "b9f40e3972d1af98f9a8b98ef3383ea97310e92a",
          "body": "- 流式:标准 data: 格式 SSE 逐帧透传\n- 非流式:JSON 原样透传\n- HTTPServer 新增 sendSSEData 方法发送裸 data: 行\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat: 添加 POST /v1/chat/completions 透传接口",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:27:00Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "adaab9c0b883d3c0c98656840a3739115b1e1529",
          "body": null,
          "is_bot": false,
          "headline": "doc: 更新 ARCHITECTURE.md 到 v2.0.0 — 多提供商 / 协议矩阵 / 测试覆盖 / 适配历史",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:20:58Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "99e9596d75f58be13b54fa9110b78ac70370896c",
          "body": null,
          "is_bot": false,
          "headline": "chore: add iRelay.zip to .gitignore",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:16:53Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "7a6bd41262ad7b015f4e6921e2e42282ec4f4138",
          "body": null,
          "is_bot": false,
          "headline": "chore: remove iRelay.zip from tracking",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:16:40Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "3ee5864ad0bfaf3c373fb18cf6bfe884b1499ba7",
          "body": "- usage 补 input_tokens_details(cached_tokens) + output_tokens_details(reasoning_tokens)\n- 流开始发 response.metadata SSE 事件(含 x-codex-turn-state / openai-model)\n- reasoning.effort 透传到 Chat API 的 reasoning_effort 字段\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "补: 三个协议补丁 — usage 明细 / response.metadata / reasoning.effort",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:16:37Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "398483753ec7ac7525a6de13ca03f2d96e090663",
          "body": null,
          "is_bot": false,
          "headline": "remove accidental iRelay.zip from tracking",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:13:20Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "ae7f3620f4886d95fc84fbcb49ac4c94ac5c2e0d",
          "body": "- 拆 iRelayCore library target,iRelay 可执行 target 依赖 iRelayCore\n- 新增 iRelayTests test target\n- 26 个测试覆盖:responsesToChatPayload、chatCompletionToResponse、\n  collectFunctionCalls(验证修过的 bug)、parseInput、contentToText、\n  convertTools、ensureToolAfterAssistant、ProviderConfig 配置\n- 修复 iRelayApp.swift 未使用变量 warning\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "test: 拆 target 结构 + 26 个协议转换单元测试",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:13:17Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9b349a488ddfd06e478dea46b27b1632987768ad",
          "body": "- 新增 ProviderConfig 数据模型,支持任意 OpenAI Chat API 兼容提供商\n- 新增 ProviderStore 多提供商持久化 + v1 自动迁移\n- 重命名 DeepSeekClient → ChatClient,通用 Chat API 客户端\n- RelayHandler 注入 ProviderConfig:thinking/reasoning 字段动态化\n- 添加 end_turn output_item,补全 Responses API 协议\n- 端口可配置(菜单栏 UI)\n- 提供商切换 UI + 管理窗口\n- README / ARCHITECTURE.md 同步更新,版本号 2.0.0\n\n保留 v1 向后兼容:旧 UserDefaults 键在首次启动时自动迁移\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "v2.0.0: 多提供商通用化改造",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T06:03:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8015478217594b59aac5fc9292c73f7e6a9f31c0",
          "body": "Responses API 的 function_call item 中 name/arguments 在顶层,\n之前按 Chat API 嵌套 function.name 读导致工具名传空。\n\n同步更新 ARCHITECTURE.md,补充协议映射表、SSE 事件对比、适配历史。\n\nCo-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix: 修复 collectFunctionCalls 字段路径 — 读 item.name 而非 item.function.name",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-15T05:53:36Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4efc1610a6e5627fbfc9caaa2d6976b509cb7d4f",
          "body": null,
          "is_bot": false,
          "headline": "init: iRelay — Codex ↔ DeepSeek 本机中转服务,macOS 菜单栏原生 App",
          "author_name": "David",
          "author_login": null,
          "committed_at": "2026-06-14T13:43:24Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 1,
      "commits_last_year": 62,
      "latest_release_at": "2026-07-20T11:18:37Z",
      "latest_release_tag": "v2.2.0",
      "releases_from_tags": false,
      "days_since_last_push": 1,
      "active_weeks_last_year": 6,
      "days_since_latest_release": 1,
      "mean_days_between_releases": null
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "has_description": true,
      "has_contributing": false,
      "health_percentage": 28,
      "has_issue_template": false,
      "has_code_of_conduct": false,
      "has_pull_request_template": false
    },
    "ecosystem": {
      "packages": []
    },
    "popularity": {
      "forks": 0,
      "stars": 0,
      "watchers": 0,
      "fork_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_forks": 0
      },
      "star_history": {
        "days": [],
        "complete": true,
        "collected": 0,
        "total_stars": 0
      },
      "open_issues_and_prs": 0
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [],
      "largest_source_bytes": 36857,
      "source_files_sampled": 14,
      "oversized_source_files": 0,
      "agent_instruction_files": [],
      "agent_instruction_max_bytes": null
    },
    "dependencies": {
      "manifests": [],
      "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": [],
      "dependencies": [],
      "all_dependencies": {
        "error": "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository",
        "source": null,
        "packages": [],
        "collected": false,
        "truncated": false,
        "total_count": null,
        "direct_count": null,
        "indirect_count": null
      }
    },
    "maintainership": {
      "issues": {
        "open_prs": 0,
        "merged_prs": 0,
        "open_issues": 0,
        "closed_ratio": null,
        "closed_issues": 0,
        "closed_unmerged_prs": 1
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "xdfnet",
          "commits": 3,
          "avatar_url": "https://avatars.githubusercontent.com/u/68147460?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": true,
      "has_tests": true,
      "ci_workflows": [
        "build.yml"
      ],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [],
      "scorecard": {
        "checks": [
          {
            "name": "Binary-Artifacts",
            "score": 10,
            "reason": "no binaries found in the repo",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#binary-artifacts"
          },
          {
            "name": "Branch-Protection",
            "score": 0,
            "reason": "branch protection not enabled on development/release branches",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#branch-protection"
          },
          {
            "name": "CI-Tests",
            "score": null,
            "reason": "no pull request found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#ci-tests"
          },
          {
            "name": "CII-Best-Practices",
            "score": 0,
            "reason": "no effort to earn an OpenSSF best practices badge detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#cii-best-practices"
          },
          {
            "name": "Code-Review",
            "score": 0,
            "reason": "Found 0/30 approved changesets -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#code-review"
          },
          {
            "name": "Contributors",
            "score": 0,
            "reason": "project has 0 contributing companies or organizations -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": 10,
            "reason": "no dangerous workflow patterns detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 0,
            "reason": "license file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 0,
            "reason": "project was created within the last 90 days. Please review its contents carefully",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#maintained"
          },
          {
            "name": "Packaging",
            "score": null,
            "reason": "packaging workflow not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#packaging"
          },
          {
            "name": "Pinned-Dependencies",
            "score": 0,
            "reason": "dependency not pinned by hash detected -- score normalized to 0",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": 0,
            "reason": "Project has not signed or included provenance with any releases.",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": 0,
            "reason": "detected GitHub workflow tokens with excessive permissions",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 10,
            "reason": "0 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "e653d5cf8a92cd2c87843d188aae1e8586d9e5da",
        "ran_at": "2026-07-22T07:23:46Z",
        "aggregate_score": 2.6,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "ci_last_run_at": "2026-07-20T16:44:37Z",
      "oldest_open_prs": [],
      "last_merged_pr_at": null,
      "ci_last_conclusion": "SUCCESS",
      "oldest_open_issues": []
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/xdfnet/iRelay",
    "host": "github.com",
    "name": "iRelay",
    "owner": "xdfnet"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "at_risk",
      "name": "Overall health",
      "note": null,
      "notes": [],
      "value": 38,
      "inputs": {
        "security": 26,
        "vitality": 64,
        "community": 12,
        "governance": 18,
        "engineering": 66
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "moderate",
        "name": "Vitality",
        "value": 64,
        "weight": 0.22,
        "metrics": [
          {
            "key": "development_activity",
            "band": "moderate",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 56,
            "inputs": {
              "commits_last_year": 62,
              "human_commit_share": 1,
              "days_since_last_push": 1,
              "active_weeks_last_year": 6
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "6/52 weeks with commits",
                "points": 4.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 6
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "62 commits in the last year",
                "points": 16.2,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 62
                    }
                  }
                ],
                "max_points": 18
              },
              {
                "key": "openssf_scorecard_maintained",
                "name": "OpenSSF Scorecard: Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "release_discipline",
            "band": "good",
            "name": "Release discipline",
            "note": null,
            "notes": [],
            "value": 76,
            "inputs": {
              "releases_count": 1,
              "latest_release_tag": "v2.2.0",
              "releases_from_tags": false,
              "days_since_latest_release": 1,
              "mean_days_between_releases": null
            },
            "components": [
              {
                "key": "ships_releases",
                "name": "Ships releases",
                "detail": "1 releases published",
                "points": 27,
                "status": "met",
                "details": [
                  {
                    "code": "releases_published",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 27
              },
              {
                "key": "release_recency",
                "name": "Release recency",
                "detail": "latest release 1 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "release_cadence",
                "name": "Release cadence",
                "detail": "cadence unknown (single release)",
                "points": 12.6,
                "status": "partial",
                "details": [
                  {
                    "code": "release_cadence_unknown",
                    "params": {}
                  }
                ],
                "max_points": 27
              },
              {
                "key": "openssf_scorecard_signed_releases",
                "name": "OpenSSF Scorecard: Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "excellent",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 12,
        "weight": 0.18,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 1,
            "inputs": {
              "forks": 0,
              "stars": 0,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "0 stars",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "0 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "critical",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 25,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "has_pull_request_template": false
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 22.5,
                "status": "met",
                "details": [],
                "max_points": 22.5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "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": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "code_of_conduct",
                "name": "Code of conduct",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 13.5
              },
              {
                "key": "issue_template",
                "name": "Issue template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.2
              },
              {
                "key": "pr_template",
                "name": "PR template",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.3
              }
            ]
          }
        ],
        "description": "Does the project have users, downloads, attention, and a welcoming setup for contributors?"
      },
      {
        "key": "governance",
        "band": "critical",
        "name": "Sustainability & Governance",
        "value": 18,
        "weight": 0.24,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "bus_factor": 1,
              "contributors_sampled": 1,
              "top_contributor_share": 1
            },
            "components": [
              {
                "key": "bus_factor",
                "name": "Bus factor",
                "detail": "1 contributor(s) cover half of all commits",
                "points": 9,
                "status": "partial",
                "details": [
                  {
                    "code": "bus_factor",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 54
              },
              {
                "key": "commit_distribution",
                "name": "Commit distribution",
                "detail": "top contributor authored 100% of commits",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "top_contributor_share",
                    "params": {
                      "share": 100
                    }
                  }
                ],
                "max_points": 22.5
              },
              {
                "key": "contributor_breadth",
                "name": "Contributor breadth",
                "detail": "1 contributors",
                "points": 1.4,
                "status": "partial",
                "details": [
                  {
                    "code": "contributors_sampled",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 13.5
              },
              {
                "key": "openssf_scorecard_contributors",
                "name": "OpenSSF Scorecard: Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): Issue resolution. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "issue_resolution"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "merged_prs": 0,
              "open_issues": 0,
              "closed_issues": 0,
              "issue_closed_ratio": null,
              "closed_unmerged_prs": 1
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "no issues or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_issues_or_data",
                    "params": {}
                  }
                ],
                "max_points": 46.75
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "0/1 decided PRs merged",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "decided_prs_merged",
                    "params": {
                      "merged": 0,
                      "decided": 1
                    }
                  }
                ],
                "max_points": 38.25
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "at_risk",
            "name": "Ownership & stewardship",
            "note": "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": 46,
            "inputs": {
              "followers": 10,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "xdfnet",
              "public_repos": 9,
              "account_age_days": 2201
            },
            "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": "10 followers of xdfnet",
                "points": 7.5,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 10,
                      "login": "xdfnet"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "9 public repos, account ~6 yr old",
                "points": 19.3,
                "status": "partial",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 9
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 6
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 66,
        "weight": 0.2,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "moderate",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 60,
            "inputs": {
              "has_ci": true,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": "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": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 16
              },
              {
                "key": "pre_commit_hooks",
                "name": "Pre-commit hooks",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 9.6
              },
              {
                "key": "editorconfig",
                "name": ".editorconfig",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 6.4
              },
              {
                "key": "openssf_scorecard_ci_tests",
                "name": "OpenSSF Scorecard: CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          },
          {
            "key": "documentation",
            "band": "good",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 75,
            "inputs": {
              "topics": [],
              "has_wiki": true,
              "homepage": null,
              "has_readme": true,
              "has_docs_dir": true,
              "has_description": true
            },
            "components": [
              {
                "key": "readme",
                "name": "README",
                "detail": null,
                "points": 30,
                "status": "met",
                "details": [],
                "max_points": 30
              },
              {
                "key": "documentation_directory",
                "name": "Documentation directory",
                "detail": null,
                "points": 25,
                "status": "met",
                "details": [],
                "max_points": 25
              },
              {
                "key": "documentation_homepage_site",
                "name": "Documentation / homepage site",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "critical",
        "name": "Security",
        "value": 26,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "critical",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Packaging. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "packaging"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 26,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 16,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 2,
              "scorecard_aggregate": 2.6
            },
            "components": [
              {
                "key": "binary_artifacts",
                "name": "Binary-Artifacts",
                "detail": "no binaries found in the repo",
                "points": 7.5,
                "status": "met",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "branch_protection",
                "name": "Branch-Protection",
                "detail": "branch protection not enabled on development/release branches",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "ci_tests",
                "name": "CI-Tests",
                "detail": "no pull request found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 2.5
              },
              {
                "key": "cii_best_practices",
                "name": "CII-Best-Practices",
                "detail": "no effort to earn an OpenSSF best practices badge detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "code_review",
                "name": "Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "contributors",
                "name": "Contributors",
                "detail": "project has 0 contributing companies or organizations -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no dangerous workflow patterns detected",
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "project was created within the last 90 days. Please review its contents carefully",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "packaging",
                "name": "Packaging",
                "detail": "packaging workflow not detected",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "pinned_dependencies",
                "name": "Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "Project has not signed or included provenance with any releases.",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "detected GitHub workflow tokens with excessive permissions",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "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": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "moderate",
        "name": "AI Readiness",
        "value": 52,
        "weight": 0,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "at_risk",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 40,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.984,
              "agent_instruction_files": [],
              "agent_instruction_max_bytes": null
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "no CLAUDE.md / AGENTS.md / editor rules",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_agent_instructions",
                    "params": {}
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "61 of 62 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 61,
                      "sampled": 62
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "at_risk",
            "name": "Verify loop (build / test / typecheck)",
            "note": null,
            "notes": [],
            "value": 43,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.758,
              "toolchain_manifests": [],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 18
              },
              {
                "key": "automated_tests",
                "name": "Automated tests",
                "detail": null,
                "points": 22,
                "status": "met",
                "details": [],
                "max_points": 22
              },
              {
                "key": "lint_format_config",
                "name": "Lint / format config",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 11
              },
              {
                "key": "static_type_checking",
                "name": "Static type checking",
                "detail": "Swift (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Swift"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "47 of the last 62 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 47,
                      "sampled": 62
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "dependency not pinned by hash detected -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "excellent",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Swift",
              "largest_source_bytes": 36857,
              "source_files_sampled": 14,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Swift (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Swift"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/14 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 14,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? An independent, experimental badge — weight 0.0, so it is surfaced on its own and does not affect the overall health score."
      }
    ],
    "metrics_version": "1.13.0"
  },
  "warnings": [
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-07-22T07:23:50.998871Z",
  "schema_version": "0.26.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/x/xdfnet/iRelay.svg",
  "full_name": "xdfnet/iRelay",
  "license_state": "absent",
  "license_spdx": null
}

Bewertungen sind Signale, keine Garantien. Sie spiegeln öffentlich sichtbare Praxis auf GitHub wider — kein Code-Audit und keine Sicherheitsgarantie.

Fehlende Daten werden ausgeschlossen und die Gewichte neu normiert, nie als null bewertet. Die Methodik ist versioniert und offen: Metriken v1.13.0, Schema v0.26.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte Statistiken.