Öffentliches Register
Software-GesundheitsberichtSchema 0.31.0 · Metriken 2.5.0 · 2026-08-05 09:20 UTC

bigwhite / cc-session-migrate

Cross-node session migration and S3 backup for Claude Code.

GoKeine Lizenz erkannt★ 5 Sterne⑂ 1 Forkseit Juli 2026Auf GitHub ansehen ↗
ArtKommandozeilenwerkzeugwie das ermittelt wird

bigwhite/cc-session-migrate erreicht einen Gesundheitsindex von 39 von 100 und liegt damit im Bereich Schwach. Am stärksten schneidet es bei AI Readiness (85/100) ab, am schwächsten bei Community & Adoption (17/100). Zuletzt vor 15 Tagen aktualisiert. Ein einzelner Mitwirkender trägt den Großteil der jüngsten Arbeit.

39
gesamt / 100
Schwach

Software-Gesundheitsindex

Metriken werden auf einer standardisierten Skala von 1–100 in gewichtete Kategorien gruppiert. Der Gesamtwert beginnt als ihr gewichtetes Mittel, kalibriert auf die Verteilung des öffentlichen Registers, sodass die Stufen Perzentilbedeutung tragen; sobald öffentliche Evidenz die Richtlinie für Hochrisikojurisdiktionen auslöst, wird die Bewertung angepasst und erhält die Obergrenze Gefährdet von 34.

39
Außergewöhnlich93-100Die Spitzengruppe des Registers (≈ obere 5 %); erfüllt im Wesentlichen alle geprüften Kriterien
Exzellent80-92Durchgehend stark; geringfügige Lücken
Gut65-79Gesund; Lücken sind begrenzt und beherrschbar
Mittel50-64Akzeptabel mit deutlichen Lücken; Überprüfung empfohlen
Schwach35-49Wesentliche Schwächen in mehreren Bereichen
Gefährdet20-34Erhebliche Schwächen; eine Übernahme erfordert Vorsicht
Kritisch1-19Schwerwiegende 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.

Der gewichtete Gesamtwert 43 wird auf der veröffentlichten Indexskala auf 39 kalibriert (Register-Kalibrierung 2026-08-02).

Eigentümerschaft

Tony BaiPersönliches Konto
1.898 Follower74 öffentliche Reposseit Sept. 2010reachauto

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.

Paket-Ökosysteme

RegistryPaketVersionDownloads / MonatVersionenZuletzt veröffentlicht
Gogithub.com/bigwhite/cc-session-migratev0.1.1-2vor 16 Tagen

Metriken nach Kategorie

Vitalität

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

62Mittel · 21 % des Gesamtindex
Wie die Bewertung erfolgt
28.8/36Push-Aktualität — letzter Push vor 15 Tagen
0.7/36Commit-Rhythmus — 1/52 Wochen mit Commits
17.3/18Commit-Volumen — 83 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_year83
human_commit_share1
days_since_last_push15
active_weeks_last_year1
Wie die Bewertung erfolgt
27/27Liefert Releases aus — 1 Releases veröffentlicht
36/36Release-Aktualität — letztes Release vor 15 Tagen
12.6/27Release-Rhythmus — Rhythmus unbekannt (nur ein Release)
0/10OpenSSF Scorecard: Signed-Releases — keine Daten
Verwendete Eingangsdaten
releases_count1
latest_release_tagv0.1.1
releases_from_tagsnein
days_since_latest_release15
mean_days_between_releases
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: Signed-Releases. Die verbleibenden Gewichte wurden renormalisiert.

Community & Verbreitung

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

17Kritisch · 17 % des Gesamtindex
Wie die Bewertung erfolgt
9.8/60Stars — 5 Stars
0/25Forks — 1 Forks
0/15Watcher — 0 Watcher
Verwendete Eingangsdaten
forks1
stars5
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
readme_badges1
has_contributingnein
has_issue_templatenein
has_code_of_conductnein
readme_badge_servicesshields.io
has_pull_request_templatenein

Nachhaltigkeit & Governance

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

41Schwach · 23 % 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
3/10OpenSSF Scorecard: Contributors — project has 1 contributing companies or organizations -- score normalized to 3
Verwendete Eingangsdaten
bus_factor1
contributors_sampled1
top_contributor_share1
Wie die Bewertung erfolgt
0/42Issue-Lösungsquote — 0 % der Issues geschlossen
0/30PR-Annahme — keine entschiedenen Pull Requests oder keine Daten
0/13Newcomer PR acceptance — kein PR eines Erstbeitragenden in 30 Tagen entschieden
0/15OpenSSF Scorecard: Code-Review — Found 0/30 approved changesets -- score normalized to 0
Verwendete Eingangsdaten
merged_prs0
open_issues1
closed_issues0
prs_merged_7d0
prs_decided_7d0
prs_merged_30d0
prs_decided_30d0
issue_closed_ratio0
closed_unmerged_prs0
first_time_authors_30d0
first_time_prs_merged_30d0
first_time_prs_decided_30d0
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): PR-Annahme, newcomer_pr_acceptance. 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
23.6/25Reichweite des Inhabers — 1.898 Follower von bigwhite
25/25Kontohistorie — 74 öffentliche Repos, Kontoalter ca. 15 Jahre
Verwendete Eingangsdaten
followers1.898
owner_typeUser
is_verified
owner_loginbigwhite
public_repos74
account_age_days5.789
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): Verifizierte Domain. Die verbleibenden Gewichte wurden renormalisiert.

Paketpflege

92Exzellent
Wie die Bewertung erfolgt
25/25Veröffentlicht & auflösbar — 1 Paket(e) auf go
35/35Veröffentlichungsaktualität — letzte Veröffentlichung vor 16 Tagen
12/20Versionshistorie — 2 veröffentlichte Versionen
20/20Nicht veraltet — aktiv, nicht veraltet oder zurückgezogen
Verwendete Eingangsdaten
packagesgithub.com/bigwhite/cc-session-migrate
ecosystemsgo
any_deprecatednein
min_days_since_publish16

Engineering-Qualität

Sind grundlegende Engineering- und Dokumentationspraktiken vorhanden?

54Mittel · 19 % des Gesamtindex
Wie die Bewertung erfolgt
0/24CI-Workflows
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_cinein
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.

Dokumentation

90Exzellent
Wie die Bewertung erfolgt
30/30README
25/25Dokumentationsverzeichnis
15/15Dokumentations-/Homepage-Site — http://tonybai.com
10/10Repository-Beschreibung
10/10Topics — 9 Topics
0/10Wiki
Verwendete Eingangsdaten
topicsclaude-code, cli-tool, dev-tools, distributed-systems, golang, hub-and-spoke, s3-backup, session-migration, websocket
has_wikinein
homepagehttp://tonybai.com
has_readmeja
has_docs_dirja
has_descriptionja

Sicherheit

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

22Gefährdet · 16 % des Gesamtindex

Sicherheitslage

22Gefährdet
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.8/2.5Contributors — project has 1 contributing companies or organizations -- score normalized to 3
0/10Dangerous-Workflow — keine Daten
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 — keine Daten
0/5SAST — no SAST tool detected
0/5Security-Policy — security policy file not detected
0/7.5Signed-Releases — keine Daten
0/7.5Token-Permissions — keine Daten
6.8/7.5Vulnerabilities — 1 existing vulnerabilities detected
Verwendete Eingangsdaten
sourceopenssf_scorecard
checks_evaluated12
scorecard_versionv5.5.0
checks_inconclusive6
scorecard_aggregate2,2
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): ci_tests, dangerous_workflow, packaging, pinned_dependencies, signed_releases, token_permissions. Die verbleibenden Gewichte wurden renormalisiert.

AI Readiness

Wie gut ist das Repository dafür ausgestattet, mit KI-Coding-Agenten entwickelt und gepflegt zu werden? Trägt ein bewusst kleines Gewicht (4 %): Agenten-Tooling ist ein echtes Pflegesignal, doch ein Repository ohne jedes Signal kann weiterhin 100/100 erreichen.

85Exzellent · 4 % des Gesamtindex
Wie die Bewertung erfolgt
45/45Agentenanweisungen — CLAUDE.md
0/15Maschinenlesbare Doku (llms.txt)
40/40Lesbare Commit-Historie — 82 von 83 menschlichen Commits benennen ihre Absicht (strukturierter Betreff oder erläuternder Text)
Verwendete Eingangsdaten
has_llms_txtnein
legible_history_share0,988
agent_instruction_filesCLAUDE.md
agent_instruction_max_bytes303
Wie die Bewertung erfolgt
18/18Bootstrap mit einem Befehl — Makefile
22/22Automatisierte Tests
0/11Lint-/Format-Konfiguration
11/11Statische Typprüfung — Go (statisch typisiert)
10/10Reproduzierbare Umgebung — lockfile
10/10Belegte Agentenpraxis — 81 der letzten 83 Commits von Agenten verfasst oder ihnen zugeschrieben
0/8Automatisierte Wartung — keine automatisierten Abhängigkeits-Updates beobachtet
0/10OpenSSF Scorecard: Pinned-Dependencies — keine Daten
Verwendete Eingangsdaten
has_nixnein
has_testsja
lockfilesgo.sum
has_dockerfilenein
typed_languageja
bootstrap_filesMakefile
has_devcontainernein
has_linter_confignein
typecheck_configs
agent_commit_share0,976
toolchain_manifestsgo.mod
dependency_bot_commit_share0
Von der Bewertung ausgeschlossen (keine Daten oder nicht anwendbar): OpenSSF Scorecard: Pinned-Dependencies. Die verbleibenden Gewichte wurden renormalisiert.
Wie die Bewertung erfolgt
45/45Typprüfbarer Code — Go (statisch typisiert)
55/55Handhabbare Dateigrößen — 0/47 Quelldateien über 60 KB
Verwendete Eingangsdaten
primary_languageGo
largest_source_bytes16.162
source_files_sampled47
oversized_source_files0

Eckdaten

5GitHub-Sterne
1Mitwirkende
83Commits, letzte 12 Monate
15Tage seit letztem Push
1Releases
1Bus-Faktor
1offene Issues
GoPaket-Ökosysteme

Warnungen zur Datenerhebung

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

Weitere Details

OpenSSF Scorecard 2.2 / 10
2.2Gesamtwert

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-08-05 09:20 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
3Contributorsproject has 1 contributing companies or organizations -- score normalized to 3
k. A.Dangerous-Workflowno workflows found
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
k. A.Pinned-Dependenciesno dependencies found
0SASTno SAST tool detected
0Security-Policysecurity policy file not detected
k. A.Signed-Releasesno releases found
k. A.Token-PermissionsNo tokens found
9Vulnerabilities1 existing vulnerabilities detected
Direkte Abhängigkeiten 7
RegistryPaketVersionsvorgabeManifest
Gogithub.com/aws/aws-sdk-go-v2v1.42.1go.mod
Gogithub.com/aws/aws-sdk-go-v2/credentialsv1.19.29go.mod
Gogithub.com/aws/aws-sdk-go-v2/service/s3v1.105.2go.mod
Gogithub.com/robfig/cron/v3v3.0.1go.mod
Gogithub.com/schollz/progressbar/v3v3.19.1go.mod
Gogithub.com/spf13/cobrav1.10.2go.mod
Gogithub.com/spf13/viperv1.21.0go.mod
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": {
    "icon": {
      "bytes": 5394,
      "width": 180,
      "height": 180,
      "rejected": [],
      "collected": true,
      "media_type": "image/png",
      "source_url": "https://tonybai.com/apple-touch-icon.png",
      "source_type": "homepage",
      "content_hash": "faa930f38af93aff4e96f7735923c62a440effa8e0463c0434c839ea308d2acb",
      "candidates_considered": 1
    },
    "repo": {
      "topics": [
        "claude-code",
        "cli-tool",
        "dev-tools",
        "distributed-systems",
        "golang",
        "hub-and-spoke",
        "s3-backup",
        "session-migration",
        "websocket"
      ],
      "is_fork": false,
      "size_kb": 10248,
      "has_wiki": false,
      "homepage": "http://tonybai.com",
      "languages": {
        "Go": 201965,
        "Shell": 6036,
        "Makefile": 819
      },
      "pushed_at": "2026-07-20T09:23:12Z",
      "created_at": "2026-07-13T03:08:31Z",
      "owner_type": "User",
      "updated_at": "2026-07-25T18:06:28Z",
      "description": "Cross-node session migration and S3 backup for Claude Code. ",
      "is_archived": false,
      "is_disabled": false,
      "license_spdx": null,
      "default_branch": "main",
      "license_spdx_raw": null,
      "primary_language": "Go",
      "significant_languages": [
        "Go"
      ]
    },
    "owner": {
      "blog": "https://tonybai.com",
      "name": "Tony Bai",
      "type": "User",
      "login": "bigwhite",
      "company": "reachauto",
      "location": "P.R. China",
      "followers": 1898,
      "avatar_url": "https://avatars.githubusercontent.com/u/419088?v=4",
      "created_at": "2010-09-28T12:20:24Z",
      "is_verified": null,
      "public_repos": 74,
      "account_age_days": 5789
    },
    "license": {
      "state": "absent",
      "spdx_id": null,
      "raw_spdx": null,
      "file_present": false,
      "scorecard_found": false,
      "profile_has_license": false
    },
    "activity": {
      "releases": [
        {
          "tag": "v0.1.1",
          "kind": "patch",
          "published_at": "2026-07-20T09:26:31Z"
        }
      ],
      "recent_commits": [
        {
          "oid": "4a11405e3aa29153165472432cbeb7006ef23511",
          "body": "…dination\n\nReadLoop dispatched JSON headers and released readMu, then immediately\nlooped back to read the next frame — racing with Request() or\nStreamRequestWithHeader() which needed readMu to consume the binary\nframe. If ReadLoop won, it read binary data as JSON, producing\n\"invalid json frame\" erro\n[…]\nfinishes\nreading the binary frame. All error paths (timeout, write failure,\nconnection close) properly signal to prevent ReadLoop from hanging.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ws): resolve ReadLoop/binary-consumer race via streamPending coor…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-20T09:13:03Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "01a230ab511c684f4773105d2b8a528fe1aa64eb",
          "body": "The previous fix introduced a deadlock: ReadLoop held readMu while\nreading the binary frame (for DataSize > 0 responses), which blocked\nStreamRequestWithHeader from ever acquiring readMu to stream the data.\n\nRoot cause: ReadLoop and StreamRequestWithHeader both need to read\nthe binary frame, but the\n[…]\n io.Copy (streaming path)\n- For unmatched responses with binary data, ReadLoop discards the\n  binary frame via NextReader + io.Copy(io.Discard)\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ws): eliminate readMu deadlock in ReadLoop binary frame handling",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-20T08:51:14Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "1366537b88f0d64e210c1ecc715104d07ad218b5",
          "body": "ReadLoop and StreamRequestWithHeader were both reading from the same\nWebSocket connection simultaneously, violating gorilla/websocket's\n\"one concurrent reader\" constraint. This caused protocol errors\n(RSV1/RSV3 set, bad opcode, bad MASK) during pull relay operations.\n\nFix: add readMu mutex to Conn, \n[…]\nore dispatching to pending channels. StreamRequestWithHeader\nacquires readMu during NextReader+io.Copy to consume the binary frame\nexclusively.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(ws): resolve concurrent reader race in StreamRequestWithHeader",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-20T08:25:41Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "576cacf0f6f4f519c6525e371cd1c52216544460",
          "body": "- client.go: log HTTP request/response with timing for pull and push\n- hub.go: log Request/StreamRequestWithHeader lifecycle and Close pending count\n- server.go: log local pack/unpack paths and session ID resolution\n- cmd/session.go: log operation-level events for pull/push CLI commands\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(logging): add structured logging for pull/push relay flow",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-20T08:04:38Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "59cedc50610b90101352a65e435cfe70634254f8",
          "body": "- Add real-time progress bars for session pull/push operations (single and batch)\n- Fix push progress bug: use progressReader for streaming upload progress\n- Make relay request timeout configurable via cluster.request_timeout (default 15m)\n- Increase default timeouts from 5min to 15min for large session transfers\n- Set Content-Length in pull relay response using StreamRequestWithHeader\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(session): add progress bar for pull/push and configurable timeout",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-20T07:32:01Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8b32b09131b445feb56475a473258da5c7412e27",
          "body": "go install produces a binary named cc-session-migrate, but all\nexamples use csm. Add alias setup steps for zsh/bash and PowerShell.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): add csm alias instructions for macOS/Windows install",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:35:46Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "8ff7bccdb961566793b4dfa96381b263eb39c0a2",
          "body": "Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): add donation section with PayPal, WeChat Pay and Alipay",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:23:20Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2997c0e1f974a810c5b750bd0e25d2b57267dd0d",
          "body": "Agent Ctrl+C took up to 90s to exit because ReadMessage() blocked\nuntil PongTimeout. Add AgentClient.Stop() to close the connection\nimmediately, unblocking the read loop. Node.Stop() now closes the\nWebSocket before cancelling context.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(agent): close WebSocket on shutdown to fix slow Ctrl+C exit",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0074eb51a16590bf2290a5198ffea2372e4068c0",
          "body": "`csm` supports ID prefix matching (minimum 8 chars), but Claude Code's\n`--resume` flag requires the complete UUID. Added a note and a full ID\nexample to prevent confusion.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): note that claude --resume requires full session ID",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9a80c5a82689d0af20c340bd2ea727b354355dc1",
          "body": "Three fixes for post-pull issues:\n\n1. Unpack --force now removes stale copies of the same session ID from\n   other project directories before unpacking, preventing duplicate\n   entries in session list.\n\n2. history.jsonl entries now use Claude Code's expected format:\n   \"project\" instead of \"cwd\", pl\n[…]\nupdate.\n\n3. Scan deduplicates sessions by ID, keeping only the most recently\n   modified copy when the same ID appears in multiple directories.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(session): clean stale copies, align history.jsonl format, dedup scan",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e823a8a81f6db18d6d0fa6f5feb0cd310c215380",
          "body": "Two bugs caused \"claude -r\" to fail after pulling a session:\n\n1. Unpack did not rename the source project's encoded directory to\n   match the target path. Files landed in projects/<source-encoded>/\n   but Claude Code looks in projects/<target-encoded>/.\n\n2. Remote pull relay did not set the X-Source\n[…]\ngithub/com\").\n\nresolveRemoteSession now returns *SessionMeta instead of just the ID,\nenabling handlePull to set HdrSourcePath for remote relay.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(session): rename project directory on unpack to match target path",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "f5a6be88fc38b261f57a64967da4b59bd31fcb59",
          "body": "…ture\n\nReplace peer-to-peer HTTP with hub-and-spoke WebSocket relay through the\nLeader server. Agents now maintain outbound WebSocket connections only,\neliminating NAT traversal issues.\n\nPhase 2: Rewrite agent node to use ws.AgentClient with message handler\nPhase 3: Add Leader relay handlers for /v1\n[…]\nlay\nPhase 5: Remove heartbeat, migration package, and stale API types\nPhase 6: Update README architecture diagram, mark old specs as superseded\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(arch): migrate from mesh to hub-and-spoke WebSocket architec…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "3439bb644bb442ef5b9aa5ccc88e8a6c9f9ebbdd",
          "body": "New internal/ws/ package implementing the hub-and-spoke communication\nlayer between the cluster leader and agent nodes:\n\n- protocol.go: message type constants, DataHeader struct, SessionInfo\n- hub.go: Hub (connection registry) + Conn (request-response correlation\n  with UUID ids, StreamRequest for z\n[…]\n loop + exponential\n  backoff reconnect), MessageHandler interface for local operations\n\nAdds github.com/gorilla/websocket v1.5.3 dependency.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(ws): add WebSocket hub-and-spoke infrastructure (Phase 1)",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "38bc7eb6ca59e3aba55ccb8e3d9a2b6850c1c4bc",
          "body": "… plan\n\nThe current mesh topology (peer-to-peer HTTP) fails when agents are\nbehind NAT (e.g. MacBook on home network). The new design replaces\nit with a hub-and-spoke model where:\n\n- Agents establish persistent WebSocket connections to the leader\n  (outbound, NAT-friendly)\n- All cross-node session o\n[…]\nto run HTTP servers or expose ports\n\nFiles added:\n- doc/spec/008-hub-spoke-architecture/spec.md\n- doc/plan/008-hub-spoke-architecture/plan.md\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(architecture): add hub-and-spoke WebSocket architecture spec and…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e60707ea2b6b61a67ff0b7283fb30454bf95e182",
          "body": "When nodes bind to 0.0.0.0 (the default), the wildcard address was\nregistered as the advertise address in the cluster topology. Other\nnodes trying to reach it via \"http://0.0.0.0:9827\" end up connecting\nto themselves, breaking cross-node session list/pull/push.\n\nTwo fixes:\n- api/server.go handleJoin\n[…]\nerver node's own\n  self-registration\n\nIf users bind to a specific address (e.g. --bind 10.0.0.5:9827), it\nis used as-is without substitution.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(cluster): replace wildcard 0.0.0.0 with real IP in node topology",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "45576da258ca4a7bce0c66b307c545efc5615863",
          "body": "cluster join was redundant with csm agent --server-addr --auth-token,\nwhich now handles both registration and daemon startup. Each operation\nshould have exactly one entry point.\n\nFinal cluster subcommand set:\n- leave: deregister node and clear local credentials (use after daemon stops)\n- list:  view cluster topology\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(cmd): remove cluster join subcommand",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "77e530c23ebd487d5fc0fac71f8709878c43a57a",
          "body": "Before: macOS users needed two commands (cluster join + agent), and\nrunning agent after join would fail with HTTP 409 since the node was\nalready registered as \"online\" by the join command.\n\nAfter: a single command does it all:\n  csm agent --server-addr <addr> --auth-token <token> --name my-macbook\n\n\n[…]\n join now prints \"Run 'csm agent' to start\n  the daemon\" after success\n- README.md / README_zh.md: macOS/Windows section shows single command\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(agent): auto-join on startup, single-command macOS setup",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "328cafff1259a6de67b2079c3680a6493449a462",
          "body": "When running under systemd without User= directive, os.UserHomeDir()\nreturns \"\" because $HOME is not set. This caused DefaultConfigPath()\nto return a relative path \".csm/config.yaml\" instead of the absolute\n\"~/.csm/config.yaml\", making the server read/write a wrong config file\n(e.g. /.csm/config.yam\n[…]\nwas the root cause of the auth token mismatch: the server was\nusing /.csm/config.yaml while the operator was checking /root/.csm/config.yaml.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(config): handle missing HOME env var in systemd context",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "e3c3f183f68c054da412146a7129bae690510441",
          "body": "Add auth token prefix (first 8 chars) and length to server startup\nlogs to help diagnose token mismatch during cluster join. Log in both\ninitCluster() (when generated or loaded) and Start() summary.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(agent): log auth token prefix at server startup",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "79ac3aa3dcafc77531d0826db14b88c7900e6cc8",
          "body": "Show expected and received token lengths in the 401 error message\nand log prefix comparison at debug level to diagnose auth failures.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "debug(api): add auth token length logging to join handler",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0a032dffb2c92fa55c7bce5a74d85bdaa4c23b1c",
          "body": null,
          "is_bot": false,
          "headline": "chore: go1.27rc1 -> go1.25.0 in go.mod",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": false
        },
        {
          "oid": "8f6a01da963e947fab7dce96ca34d6dccc55ff62",
          "body": "The server node is not just a cluster manager — it's a full agent\nthat also participates in session migration. Redraw the diagram\nto show all nodes as peers with bidirectional migration arrows,\nand annotate the server's additional cluster management role.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): update architecture diagram to show server as full agent",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7c04c66e2b5b841c2111fd4e86b172a64b73d108",
          "body": "- Add tip recommending running the server (leader) on a Linux server\n- Merge macOS/Windows instructions (both use go install + manual run)\n- Add Windows to platform support table\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): recommend Linux for server node, add Windows support",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "a8ddd3d9ff8525dd260152555a70ac744f642c41",
          "body": "Move macOS install and cluster setup instructions from the\nPlatform Support section into the Install and Set Up a Cluster\nsections, so users see both Linux and macOS options side by side\nat each step. Simplify Platform Support to a table only.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): add macOS instructions to each Quick Start step",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2fd1498c3ad3bfa4c63be1ac335c9c6d5d90b84f",
          "body": "Replace the multi-option installation section with a single\nrecommended method (install script). Replace the standalone\n`csm agent --server` command with the systemctl-based workflow\nthat matches actual Linux deployment. Move macOS/manual usage\nto the Platform Support section as a secondary option.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(readme): simplify Quick Start to one recommended path",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "246804478dfd71c16d34e3119d5ada9d8062163e",
          "body": "config.Load() previously returned an error when ~/.csm/config.yaml\ndid not exist, causing root.go to fall back to DefaultConfig()\nwhich bypassed all CSM_ environment variables. This meant systemd\nservices using /etc/cc-session-migrate/env with CSM_AGENT_ROLE=server\nwould still start in agent mode.\n\n\n[…]\nr\nstill applies defaults + env vars even without a config file.\nSimplify root.go accordingly (remove the fallback branch and\nhelper functions).\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "fix(config): apply env vars when config file is missing",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "95792a08f1a6a92d3d1db21ff84712628d08b88e",
          "body": "Update T502-T508 interface signatures and prd.md directory tree\nto reflect the HTTP API migration.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: fix remaining gRPC references in tasks.md and prd.md",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "19831c5380c6f9308eba700a6b7e7d8cd6637718",
          "body": "Remove all gRPC/protobuf dependencies and replace with a lightweight\nJSON over HTTP API using Go standard library net/http. This enables\n`go install` without requiring buf/protoc toolchain.\n\nChanges:\n- Delete proto/, gen/, buf.yaml, buf.gen.yaml\n- Add internal/api/ package (types, server, client)\n- \n[…]\n dependencies\n- Update Makefile (remove proto/lint/breaking/buf-setup targets)\n- Update all docs (specs, plan, tasks, prd, READMEs, install.sh)\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "refactor(api): replace gRPC with JSON over HTTP",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "756b8ccdf920993222abc6923b9067963d7e9e2c",
          "body": "Replace raw protoc with buf.build's buf CLI for protobuf code\ngeneration. Add buf.yaml and buf.gen.yaml with BASIC lint and\nFILE-level breaking change detection. Add make lint/breaking/buf-setup\ntargets. Generated files are functionally identical.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "build(proto): migrate from protoc to buf CLI",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "63b49f3b8af03c17167d0961416936684cfb331d",
          "body": "…_zh.md\n\nEnglish README is now the main documentation with a link to the\nChinese version. Both versions cover the same content: architecture,\nquick start, CLI reference, configuration, and development guide.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add English README as primary, rename Chinese version to README…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "467b9f386b76d05a2655966dc8ec0163e33d3a7c",
          "body": "Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs: add Chinese README with full project documentation",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "f0453b2202b72d1e9dfcf0d12b6038fbeeb9d8a0",
          "body": "Update tasks.md to reflect completion of all 7 phases (49 tasks),\nadding real commit hashes for Phase 5-7 and updating the statistics\ntable to show 100% completion.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(tasks): mark all 49 tasks complete with commit references",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "72a2ff6bb306105a41e2d66772c0aee9b0d6c816",
          "body": "Both Server and Node now start the backup Scheduler on boot when\nconfig.backup.auto_enabled is true and S3 is configured. The scheduler\nruns incremental backups (mtime-based) on the configured cron interval\nand cleans expired entries on each run. Scheduler is stopped gracefully\non shutdown.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T706): integrate automatic backup scheduler into server and agent",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "3243f7be3675f0fa4b2d392a3b4f1f2feb4499ff",
          "body": "backup create [--session <id>] backs up one or all sessions to S3,\nprinting a batch report for multi-session runs.\n\nbackup list [--node <name>] [--session <id>] [--format json] queries S3\nand displays backup entries sorted by timestamp descending.\n\nbackup restore --node <name> --session <id> [--time\n[…]\n(or specified) backup.\n\nAll commands validate S3 config upfront with a clear error message\npointing to `csm backup config` when not configured.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T705): implement backup create/list/restore CLI commands",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "be8ba88d25e11a221d0e801edae8e7c35a3d3341",
          "body": "Scheduler uses robfig/cron for periodic backups. Only sessions whose\nmtime changed since the last run are backed up (incremental). Expired\nbackups (older than retention_days, default 30) are cleaned up, with\na minimum of 3 backups retained per session.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T704): implement automatic backup scheduler with expiration cleanup",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ff345c1f30b5581504eab259deb2d4f83a575ce3",
          "body": "RestoreBackup downloads a backup archive from S3, auto-selects the\nlatest if no timestamp is specified, extracts the source project path\nfrom the embedded manifest, and unpacks locally with optional path\nremapping. Also exports ReadManifestFromTar for external use.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T703): implement backup restore with S3 download and unpack",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2bce640704ea44e03fe4dc89e90c5ff1d050895c",
          "body": "ListBackups queries S3 with an optional node/session prefix filter,\nparses tar.gz keys into BackupInfo structs (node, session, timestamp,\nsize), and sorts by timestamp descending. Malformed keys are silently\nskipped.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T702): implement backup listing with S3 key parsing",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4384a493c17c4b794ec7e70375aba3acd45813a2",
          "body": "CreateBackup packs a single session and uploads the tar.gz archive\nand manifest.json to S3 under key structure:\n  backups/{node}/{session-id}/{timestamp}.tar.gz\n  backups/{node}/{session-id}/{timestamp}.manifest.json\n\nCreateAllBackups scans all local sessions and backs them up sequentially.\nA single failure does not abort the batch; results are collected in\nBackupReport.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T701): implement backup creation with S3 upload",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "aff96d02732def085212b4a5566b3a45897750bd",
          "body": "`csm backup config --endpoint <url> --bucket <name> [--access-key ...]\n[--secret-key ...] [--region auto]` saves S3 credentials to the config\nfile after verifying connectivity via HeadBucket. Fails early if the\nbucket is unreachable or credentials are invalid.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T602): implement backup config command with connection verification",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fd814b38007cf6effd46c2ffc5213e5328da8f55",
          "body": "S3Client wraps aws-sdk-go-v2 with bucket-aware operations:\nVerifyConnection (HeadBucket), Upload (PutObject), Download (GetObject),\nList (ListObjectsV2 with pagination), Delete, and DeletePrefix.\n\nUses BaseEndpoint for R2/MinIO/custom S3-compatible endpoints with\npath-style addressing. Region defaults to us-east-1 if not specified.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T601): implement S3 client with custom endpoint support (R2/MinIO)",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "df50e4164c2bd96c0c593cec8e46e350a51b5cc9",
          "body": "The --node flag on `csm session list` now queries a remote node's\nMigrationService via gRPC ListSessions, converts the response to\nSessionMeta, and formats it with the same table/JSON output used\nfor local listing. Node resolution supports both name (topology\nlookup) and host:port address.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T509): implement session list --node for remote session queries",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5e77641cc6a4c22f7508df99eccec1a37e12c1ff",
          "body": "session pull --from <node> <session-id> streams a session from a remote\nnode, verifies checksum, and unpacks locally. session push --to <node>\n<session-id> packs locally and streams to the remote node.\n\nBoth commands support:\n- Node reference by name (topology lookup) or host:port address\n- Session \n[…]\nllAll/PushAll\n- --force to overwrite existing sessions\n- --project to remap project paths\n- Progress bar (TTY) or text percentage (pipe) output\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T508): implement session pull/push CLI commands with progress bar",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "95e22ec007c109c098d9fc3c5067559686c73daf",
          "body": "…orting\n\nPullAll lists sessions from a remote node and pulls each one sequentially.\nPushAll lists local sessions and pushes each to the remote node. A single\nsession failure is recorded in BatchReport.Details and does not abort\nthe remaining sessions. Context cancellation stops the batch early.\n\nTests cover multi-session pull/push and empty node edge case.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T507): implement batch PullAll/PushAll with failure-tolerant rep…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "709c41ace7752418f03f71d57b0201be8648aa86",
          "body": "NewProgressWriter returns a schollz/progressbar when stderr is a TTY,\nor a plain text percentage reporter when piped. Pull and Push now\naccept an optional io.Writer for progress tracking (nil to disable).\n\nTests updated to pass nil progress writer.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T506): add progress bar for session transfers (TTY-aware)",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "956b73e1de3764c9f83453cdc050f457fdf7648f",
          "body": "…ion tests\n\nPush packs a local session, opens an UnpackSession client stream to the\nremote node, sends metadata in the first chunk, streams 64KB data chunks\nwith SHA-256 checksum in the last chunk, and waits for the remote\nunpack confirmation.\n\nTests cover: successful push, push with project path remapping, and\npush of a non-existent local session.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T505): implement session Push with streaming upload and integrat…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2f4b8ab04e233fcabb252a8c19bab76c841ea4fb",
          "body": "…egration tests\n\nPull connects to a remote node's MigrationService, streams the packed\nsession archive back in 64KB chunks, verifies the SHA-256 checksum,\nand unpacks into the local data directory with optional path remapping.\n\nTests use bufconn for in-memory gRPC, covering:\n- Successful pull with source path preserved\n- Pull with explicit target project path remapping\n- Pull of non-existent session returns error\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T504): implement session Pull with checksum verification and int…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "fea250c8b79707643cb6b295204166c890bc96b4",
          "body": "…ndpoints\n\nThe MigrationService is now registered in server.Start() and node.Start()\nso that every cluster node (leader and agents alike) can accept inbound\nListSessions / PackSession / UnpackSession RPCs from peer nodes.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T503): register MigrationService on both server and agent gRPC e…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "7a1d343948b26253619f0cf2fe85443f4f55534d",
          "body": "…treaming\n\nMigrationServer.ListSessions scans local sessions via the session package.\nPackSession packs a session and streams it as 64KB DataChunk messages with\nmetadata in the first chunk and checksum in the last. UnpackSession\nreceives the stream, reassembles the tar.gz, and delegates to session.Unpack.\nTests cover listing, packing, unpack round-trip, and error cases.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T502): implement MigrationService gRPC server with pack/unpack s…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "965a8a39c683d0ec74f35e7d6a34a43d01441346",
          "body": "…ession\n\nPackSession streams packed session data as 64KB DataChunk messages.\nFirst chunk carries metadata (total_size, session_id, source_path).\nLast chunk carries SHA256 checksum. UnpackSession receives a stream\nof DataChunks and returns success/failure response.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T501): extend MigrationService protobuf with PackSession/UnpackS…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9850096a7ce37fa3b8e4ff3784bd4ba7d743b1e2",
          "body": "…tations)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: remove cluster doc.go placeholder (superseded by real implemen…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "398693898feeba79953a4f839bf368a8ca61f167",
          "body": "csm session list scans ~/.claude/projects/ for session JSONL files,\nsorts by last modified (descending), and outputs as table (default)\nor JSON (--format json). Includes human-readable relative times and\nfile sizes. Remote mode (--node) returns a helpful not-yet-implemented\nmessage.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T407): implement session list command with local scanning",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2cd76408fb1e30bdfe57759b22b03deeb2d5af32",
          "body": "MigrationService.ListSessions returns all sessions on a node with\nsession_id, project_path, data_size, last_modified, and file_count.\nPackSession/UnpackSession streaming RPCs will be added in Phase 5.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T406): define MigrationService protobuf with ListSessions RPC",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "4c346d582f43b8a5c0478e554e95b9c8154de139",
          "body": "…pping\n\nUnpack() extracts tar.gz to a staging directory, verifies SHA256 checksum,\napplies path remapping if source/target paths differ, atomically moves\nfiles to final locations, and updates history.jsonl. Supports --force\nto overwrite existing files. Includes path traversal protection.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T404): implement session unpack with staging, checksum, and rema…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b43ea0430b3bcf4da9219febff1ec907a86c5ee0",
          "body": "RemapPaths replaces source project path with target path in session\nJSONL files and subagent data. UpdateHistoryJSON appends or force-updates\na session entry in history.jsonl with the new project path.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T405): implement path remapping for JSONL files and history.jsonl",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6b01f1cbce59b609d114e64ceb66351a310050ce",
          "body": "Pack() collects all session files, creates a tar.gz archive with a\nmanifest.json at the root containing session metadata, file list,\nand SHA256 checksum. readManifestFromTar() extracts the manifest\nfor verification during unpack.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T403): implement session packer with tar.gz and manifest",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "73140b89864955912df9d1213c8add308f0a83fb",
          "body": "MatchSessionID supports minimum 8-character prefix matching with\ncase-insensitive comparison. Returns ErrPrefixTooShort, ErrNotFound,\nor ErrAmbiguous (wrapping count) for respective error conditions.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T402): implement session ID prefix matching (git-style)",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "cd82a805bb278679ccb64dfd78e5e2d984c29070",
          "body": "Scan() discovers all sessions under ~/.claude/ by traversing projects/\ndirectories, matching .jsonl files, and collecting associated files from\nsession-env/, tasks/, and subagent directories. decodeProjectPath() maps\ndirectory names back to filesystem paths (lossy: - → /).\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T401): implement session scanner with project path decoding",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "21617210c7a9b9c438111204df305cd28795f957",
          "body": "cluster join: connects to server via gRPC, sends Join RPC, saves cluster\nconfig (ID, token, server addr), outputs node list.\ncluster leave: sends Leave RPC to server, clears cluster config. Supports\n--force for unreachable servers.\ncluster list: subscribes to TopologyStream for initial snapshot, outputs\nas table (default) or JSON (--format json).\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T304-T306): implement cluster join/leave/list commands",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "14e1ce57353b38bc5ec7d4900fd42cbff9fd8ba0",
          "body": "StartTopologySync subscribes to the server's TopologyStream RPC and\napplies incremental updates (join/leave/status_change) to the local\ntopology. Full snapshots replace all nodes. Handles non-existent node\nedge cases safely.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T303): implement topology sync client for agent-side streaming",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "6288eed48ddb6e8e3f15f887fea926ab6dae3dbf",
          "body": "… streaming\n\nServer.Join now rejects duplicate online node names. Server.Leave broadcasts\ndeparture events. Added TopologyStream server-side streaming RPC: sends\ninitial snapshot then pushes join/leave/status_change events to all active\nsubscribers via buffered channels. Extracted topologyToProtoNodes helper.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T301+T302): enhance Join/Leave with duplicate check and topology…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ab0d440ad04a6868492ab52238fe7a2eb7544fcb",
          "body": "Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: add .gitignore and remove binary from tracking",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0bdad40da6161237157bf8c4366f1261a0beac44",
          "body": "…tions)\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore: remove agent doc.go placeholder (superseded by real implementa…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "64fbad7dcdaaa38bc45ba8a5820438968379e241",
          "body": "cmd/agent.go now dispatches to Server.Start() (server mode) or\nNode.Start() (agent mode) based on --server flag or config role.\nFlag values override config. Signal handler triggers graceful stop.\nServer implements Join/Leave RPC handlers; Node sends Leave RPC\non shutdown before closing the gRPC connection.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T207): wire agent sub-command to server/node lifecycle",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "0f89b0097fe45c2a8ac911e81826e94cc67a164c",
          "body": "SetupSignalHandler registers OS signal listeners that invoke the provided\nstopFn (Server.Stop or Node.Stop), allowing the gRPC server to drain\ngracefully before process exit.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T206): implement graceful shutdown via SIGINT/SIGTERM handler",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "b4c53d9ea5f4555408625dcf3c516a07bee40f49",
          "body": "Node sends Heartbeat RPC every 30s with node name, timestamp, and uptime.\nServer handles Heartbeat RPC by updating topology. Server-side checker\nruns every 60s and marks nodes offline after 5min without heartbeat.\nServer node itself is excluded from offline marking.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T205): implement heartbeat mechanism for agent-server liveness",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ca737143bf33999239666998976f7bec9eedc61c",
          "body": "Node struct connects to server via Join RPC, populates local topology\nwith returned node list, and starts a local gRPC listener for inbound\nmigration requests. Includes integration test with in-process mock\nserver validating the full join flow and auth token rejection.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T204): implement agent node mode with cluster join via gRPC",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "37198cfe3e0b197fb8d7383a16d2f7c4b8c8ae06",
          "body": "Server struct embeds UnimplementedClusterServiceServer and holds config,\ntopology, and gRPC server. initCluster() generates a UUID v4 cluster-id\nand 32-byte random auth token on first boot, persisting to config.yaml\nwith 0600 permissions. Existing values are preserved on subsequent boots.\nStart() binds gRPC listener and blocks until context cancellation.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T203): implement server mode with cluster identity generation",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ef3e5649645b5717c138819e1a38edd5e43e391f",
          "body": "…-safe access\n\nTopology manages cluster membership as a thread-safe map with RWMutex.\nSupports AddNode, GetNode, RemoveNode, UpdateHeartbeat, MarkOffline,\nand sorted ListNodes (server-first, then alphabetical by name).\nTests cover CRUD, sorting, 50-goroutine concurrency, and edge cases.\n\nCo-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T202): implement cluster topology data structure with concurrent…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "9e95f24a6a9fd4da6ac1284b449054423deeea52",
          "body": "- proto/cluster.proto: ClusterService with Join, Leave, Heartbeat,\n  TopologyStream RPCs; NodeInfo, JoinRequest/Response, LeaveRequest/Response,\n  HeartbeatRequest/Response, TopologyRequest, TopologyUpdate messages\n- gen/cluster.pb.go: generated protobuf Go code\n- gen/cluster_grpc.pb.go: generated gRPC service stubs\n- Installed protoc + protoc-gen-go + protoc-gen-go-grpc\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T201): add ClusterService protobuf definition and generated code",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "bd50f11a466de883619e2194de21bdea6b91f15b",
          "body": "T111 - scripts/cc-session-migrate.service:\n  - systemd unit file with EnvironmentFile, Restart=on-failure, RestartSec=5\n  - StandardOutput/Error to journal for journald integration\n\nT112 - scripts/install.sh:\n  - Detect OS/Arch (linux/darwin, amd64/arm64)\n  - Install binary to /usr/local/bin/\n  - Ad\n[…]\nm/config.yaml with 0600 permissions\n  - Print platform-specific next steps\n\nPhase 1 complete. All CLI commands and infrastructure are in place.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(T111+T112): add systemd service file and install script",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "527a982533b7333874e8ddb62ea94a708c36a32e",
          "body": "- cmd/root.go: root command with --config and --verbose global flags,\n  PersistentPreRunE for log init and config loading\n- cmd/version.go: version output with ldflags-injected build info\n- cmd/agent.go: agent command skeleton (--server, --server-addr, --auth-token,\n  --bind, --name, --data-dir flag\n[…]\nestore sub-commands with S3 flags\n- main.go: entry point using cmd.NewRootCmd()\n\nAll commands output correct --help matching PRD §6 CLI design.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T105-T110): implement CLI framework with all sub-command skeletons",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "4ab0f992a77f1dc7f82f8b83f6fc54ec927f4c41",
          "body": "- Config struct with Node, Agent, Cluster, S3, Backup sections\n- Load(): YAML file + CSM_ env var overrides (env takes precedence)\n- Save(): persist to YAML with 0600 permissions (secrets protection)\n- DefaultConfig(): sensible defaults (hostname, ~/.claude, port 9827)\n- EnsureConfigDir(): create ~/.csm/ directory\n- 6 tests: defaults, save/load round-trip, env override,\n  non-existent file, config dir creation, default path\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T104): implement configuration management with viper",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "d286ee20cdb44230f44297547620aa08b900d437",
          "body": "- Init(verbose, daemon): CLI mode (text→stderr) or daemon mode (JSON→stdout)\n- Info/Debug/Error/Warn: convenience wrappers around slog\n- Verbose flag controls debug vs info level\n- 6 tests covering: verbose/non-verbose filtering, all log levels,\n  key-value args, CLI and daemon mode initialization\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "feat(T103): implement structured logging module with slog wrapper",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "5a5c4748ccc44d6de0fd6f3b1f1cb16f7a6bba19",
          "body": "- build: compile with ldflags injection (version, buildTime, goVersion)\n- proto: protoc command for .proto → Go code generation\n- test: go test -v ./...\n- clean: remove bin/ directory\n- install: install binary to /usr/local/bin\n- help: display available targets\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(T102): add Makefile with build, proto, test, clean targets",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "e4a999ce2d14f774253537aea1b8ce9e8112e8b5",
          "body": "- go mod init github.com/bigwhite/cc-session-migrate\n- Create directory tree: cmd/, internal/{agent,cluster,session,\n  migration,store,backup,config,log}/, proto/, gen/, scripts/\n- Add placeholder doc.go in each package for build verification\n- Add minimal main.go entry point\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "chore(T101): initialize Go module and project directory structure",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "2650d40229b3e70d2a18dac31f32924ce0d7e112",
          "body": "Break down implementation plan into 49 atomic tasks:\n- Phase 1 (T101-T112): CLI framework, config, Makefile, install script\n- Phase 2 (T201-T207): Agent daemon, protobuf, heartbeat, graceful shutdown\n- Phase 3 (T301-T306): Cluster join/leave/list, topology sync\n- Phase 4 (T401-T407): Session scanner\n[…]\n06): Backup create/list/restore, scheduler, agent integration\n\nEach task includes: goal, files, interfaces, key points, and verification steps.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(plan): add atomic task list with 49 tasks across 7 phases",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "b1876f63f1c14b19c50c5c7aadf1a9a0242fadb4",
          "body": "7-phase implementation plan based on feature specs:\n- Phase 1: CLI framework + config (007)\n- Phase 2: Agent daemon core (001)\n- Phase 3: Cluster management (002)\n- Phase 4: Session scan & pack (003)\n- Phase 5: Session migration (004)\n- Phase 6: S3 config (005)\n- Phase 7: Backup & restore (006)\n\nEach phase includes: step-by-step tasks, key files, Go interfaces,\nprotobuf definitions, verification steps, and testing strategy.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(plan): add technical implementation plan",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "1b1fa353dd8ff2836dad4a091c31ed50e9a3effd",
          "body": "Break down PRD into 7 feature specs:\n- 001-agent-daemon: server/agent modes, heartbeat, systemd, macOS foreground\n- 002-cluster-management: join/leave/list commands, topology sync\n- 003-session-scan-pack: session scanning, tar.gz packing/unpacking, path mapping\n- 004-session-migration: pull/push com\n[…]\nlias setup\n\nEach spec includes: scope, requirements, gRPC definitions (where applicable),\ndata structures, error handling, and output examples.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(spec): add feature specs for all 7 modules",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": true,
          "is_coding_agent": true
        },
        {
          "oid": "2f5f31e09eea50a9c6296478bc3f31fc44ad214f",
          "body": "macOS has no systemd. Update PRD to reflect:\n- Linux nodes: managed by systemd (both server and agent)\n- macOS nodes: foreground `csm agent` (optionally with tmux)\n- Remove launchd from Phase 4 milestone\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(prd): clarify macOS uses foreground mode instead of systemd",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "305ef82ac86d368b4c61cd8068126cf1107b8832",
          "body": "…3 config\n\n- Add explicit migration scope constraint: only local<->remote, no\n  third-party relay between two remote nodes\n- Unify systemd lifecycle management for all nodes (both server and agent)\n- Make S3 configuration independent per node (no server distribution)\n- Add both server and agent env file examples\n- Update cluster setup flow to show unified systemd-based workflow\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(prd): clarify migration scope, systemd for all nodes, per-node S…",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "ac1be05362ec184ee2bc54308266e0d2f2aa3ea6",
          "body": "Key changes from v0.1:\n- Rename tool to cc-session-migrate (alias csm)\n- Switch from S3-based registry to Consul-style cluster (server/agent)\n- Remove session viewing/search (avoid coupling with Claude Code data format)\n- Simplify security (no mTLS, no AES encryption)\n- Replace observability stack with structured logging via slog/journald\n- Use systemd for agent lifecycle management\n- Add complete CLI -h output design for all commands\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(prd): rewrite PRD with focused scope and Consul-style cluster model",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "40621ab482c69dda19c8c3f8408f166a63e2463d",
          "body": "Define product requirements for a CLI tool that enables cross-node\nsession visibility, bidirectional session migration, and S3 backup/restore\nfor Claude Code sessions across multiple development machines.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>",
          "is_bot": false,
          "headline": "docs(prd): add PRD for ccsm (Claude Code Session Manager)",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:43Z",
          "body_truncated": false,
          "is_coding_agent": true
        },
        {
          "oid": "022c3be0a64c196a5f583885476ecc758b02d6df",
          "body": null,
          "is_bot": false,
          "headline": "add doc",
          "author_name": "Tony Bai",
          "author_login": "bigwhite",
          "committed_at": "2026-07-19T13:05:21Z",
          "body_truncated": false,
          "is_coding_agent": false
        }
      ],
      "releases_count": 1,
      "commits_last_year": 83,
      "latest_release_at": "2026-07-20T09:26:31Z",
      "latest_release_tag": "v0.1.1",
      "releases_from_tags": false,
      "days_since_last_push": 15,
      "active_weeks_last_year": 1,
      "days_since_latest_release": 15,
      "mean_days_between_releases": null
    },
    "artifacts": {
      "collected": true,
      "structure": [
        "tree.go_main"
      ],
      "declarations": []
    },
    "community": {
      "has_readme": true,
      "has_license": false,
      "readme_badges": {
        "hosts": [
          "shields.io"
        ],
        "total": 1,
        "header": 0,
        "collected": true,
        "has_inspect_badge": 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": [
        {
          "name": "github.com/bigwhite/cc-session-migrate",
          "exists": true,
          "license": null,
          "keywords": [],
          "ecosystem": "go",
          "categories": [],
          "matches_repo": true,
          "registry_url": "https://pkg.go.dev/github.com/bigwhite/cc-session-migrate",
          "declared_type": null,
          "is_deprecated": false,
          "latest_version": "v0.1.1",
          "repository_url": "https://github.com/bigwhite/cc-session-migrate",
          "versions_count": 2,
          "total_downloads": null,
          "dependents_count": null,
          "deprecation_note": null,
          "maintainers_count": null,
          "monthly_downloads": null,
          "first_published_at": null,
          "latest_published_at": "2026-07-20T09:13:03Z",
          "latest_version_yanked": null,
          "days_since_latest_publish": 16
        }
      ]
    },
    "popularity": {
      "forks": 1,
      "stars": 5,
      "watchers": 0,
      "fork_history": {
        "days": [
          {
            "date": "2026-07-24",
            "count": 1
          }
        ],
        "complete": true,
        "collected": 1,
        "total_forks": 1
      },
      "star_history": null,
      "open_issues_and_prs": 1
    },
    "ai_readiness": {
      "has_nix": false,
      "example_dirs": [],
      "has_llms_txt": false,
      "has_dockerfile": false,
      "has_mcp_signal": false,
      "bootstrap_files": [
        "Makefile"
      ],
      "api_schema_files": [],
      "has_devcontainer": false,
      "typecheck_configs": [],
      "toolchain_manifests": [
        "go.mod"
      ],
      "largest_source_bytes": 16162,
      "source_files_sampled": 47,
      "oversized_source_files": 0,
      "agent_instruction_files": [
        "CLAUDE.md"
      ],
      "agent_instruction_max_bytes": 303
    },
    "dependencies": {
      "manifests": [
        "go.mod"
      ],
      "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": [
        "go"
      ],
      "dependencies": [
        {
          "name": "github.com/aws/aws-sdk-go-v2",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.42.1"
        },
        {
          "name": "github.com/aws/aws-sdk-go-v2/credentials",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.19.29"
        },
        {
          "name": "github.com/aws/aws-sdk-go-v2/service/s3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.105.2"
        },
        {
          "name": "github.com/robfig/cron/v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.0.1"
        },
        {
          "name": "github.com/schollz/progressbar/v3",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v3.19.1"
        },
        {
          "name": "github.com/spf13/cobra",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.10.2"
        },
        {
          "name": "github.com/spf13/viper",
          "manifest": "go.mod",
          "ecosystem": "go",
          "version_constraint": "v1.21.0"
        }
      ],
      "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": 1,
        "closed_ratio": 0,
        "closed_issues": 0,
        "closed_unmerged_prs": 0
      },
      "bus_factor": 1,
      "bot_contributors": 0,
      "top_contributors": [
        {
          "type": "User",
          "login": "bigwhite",
          "commits": 83,
          "avatar_url": "https://avatars.githubusercontent.com/u/419088?v=4"
        }
      ],
      "contributors_sampled": 1,
      "top_contributor_share": 1
    },
    "quality_signals": {
      "has_ci": false,
      "has_tests": true,
      "ci_workflows": [],
      "has_docs_dir": true,
      "linter_configs": [],
      "has_editorconfig": false,
      "has_linter_config": false,
      "has_precommit_config": false
    },
    "security_signals": {
      "lockfiles": [
        "go.sum"
      ],
      "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": 3,
            "reason": "project has 1 contributing companies or organizations -- score normalized to 3",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#contributors"
          },
          {
            "name": "Dangerous-Workflow",
            "score": null,
            "reason": "no workflows found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dangerous-workflow"
          },
          {
            "name": "Dependency-Update-Tool",
            "score": 0,
            "reason": "no update tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#dependency-update-tool"
          },
          {
            "name": "Fuzzing",
            "score": 0,
            "reason": "project is not fuzzed",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#fuzzing"
          },
          {
            "name": "License",
            "score": 0,
            "reason": "license file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#license"
          },
          {
            "name": "Maintained",
            "score": 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": null,
            "reason": "no dependencies found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#pinned-dependencies"
          },
          {
            "name": "SAST",
            "score": 0,
            "reason": "no SAST tool detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#sast"
          },
          {
            "name": "Security-Policy",
            "score": 0,
            "reason": "security policy file not detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#security-policy"
          },
          {
            "name": "Signed-Releases",
            "score": null,
            "reason": "no releases found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#signed-releases"
          },
          {
            "name": "Token-Permissions",
            "score": null,
            "reason": "No tokens found",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#token-permissions"
          },
          {
            "name": "Vulnerabilities",
            "score": 9,
            "reason": "1 existing vulnerabilities detected",
            "documentation_url": "https://github.com/ossf/scorecard/blob/c395761df6afe1a69e476bc60a013a94bcbc153f/docs/checks.md#vulnerabilities"
          }
        ],
        "commit": "4a11405e3aa29153165472432cbeb7006ef23511",
        "ran_at": "2026-08-05T09:20:15Z",
        "aggregate_score": 2.2,
        "scorecard_version": "v5.5.0"
      },
      "has_codeql_workflow": false,
      "has_security_policy": false,
      "has_dependabot_config": false
    },
    "contribution_flow": {
      "collected": true,
      "recent_prs": {
        "merged_7d": 0,
        "decided_7d": 0,
        "merged_30d": 0,
        "authors_30d": 0,
        "decided_30d": 0,
        "sample_size": 0,
        "window_days": 30,
        "sample_exhausted": false,
        "authors_probed_30d": 0,
        "newcomer_merged_30d": 0,
        "bot_prs_excluded_30d": 0,
        "newcomer_authors_30d": 0,
        "newcomer_decided_30d": 0
      },
      "ci_last_run_at": null,
      "oldest_open_prs": [],
      "last_merged_pr_at": null,
      "ci_last_conclusion": null,
      "oldest_open_issues": [
        {
          "number": 1,
          "created_at": "2026-07-22T08:12:03Z",
          "last_comment_at": null,
          "last_comment_author": null
        }
      ]
    }
  },
  "config": {
    "disabled_metrics": [],
    "disabled_categories": [],
    "disabled_components": {}
  },
  "source": {
    "url": "https://github.com/bigwhite/cc-session-migrate",
    "host": "github.com",
    "name": "cc-session-migrate",
    "owner": "bigwhite"
  },
  "metrics": {
    "overall": {
      "key": "overall",
      "band": "weak",
      "name": "Overall health",
      "note": "The weighted overall 43 is calibrated to 39 on the published index scale (record calibration 2026-08-02).",
      "notes": [
        {
          "code": "overall_calibration",
          "params": {
            "raw": 43,
            "calibrated": 39,
            "calibration": "2026-08-02"
          }
        }
      ],
      "value": 39,
      "inputs": {
        "security": 22,
        "vitality": 62,
        "community": 17,
        "governance": 41,
        "calibration": "2026-08-02",
        "engineering": 54,
        "ai_readiness": 85,
        "weighted_overall_raw": 43
      },
      "components": []
    },
    "categories": [
      {
        "key": "vitality",
        "band": "moderate",
        "name": "Vitality",
        "value": 62,
        "weight": 0.21,
        "metrics": [
          {
            "key": "development_activity",
            "band": "weak",
            "name": "Development activity",
            "note": null,
            "notes": [],
            "value": 47,
            "inputs": {
              "commits_last_year": 83,
              "human_commit_share": 1,
              "days_since_last_push": 15,
              "active_weeks_last_year": 1
            },
            "components": [
              {
                "key": "push_recency",
                "name": "Push recency",
                "detail": "last push 15 days ago",
                "points": 28.8,
                "status": "partial",
                "details": [
                  {
                    "code": "push_recency",
                    "params": {
                      "days": 15
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_cadence",
                "name": "Commit cadence",
                "detail": "1/52 weeks with commits",
                "points": 0.7,
                "status": "partial",
                "details": [
                  {
                    "code": "commit_cadence_weeks",
                    "params": {
                      "weeks": 1
                    }
                  }
                ],
                "max_points": 36
              },
              {
                "key": "commit_volume",
                "name": "Commit volume",
                "detail": "83 commits in the last year",
                "points": 17.3,
                "status": "partial",
                "details": [
                  {
                    "code": "commits_last_year",
                    "params": {
                      "count": 83
                    }
                  }
                ],
                "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": "excellent",
            "name": "Release discipline",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Signed-Releases. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_signed_releases"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 84,
            "inputs": {
              "releases_count": 1,
              "latest_release_tag": "v0.1.1",
              "releases_from_tags": false,
              "days_since_latest_release": 15,
              "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 15 days ago",
                "points": 36,
                "status": "met",
                "details": [
                  {
                    "code": "release_recency",
                    "params": {
                      "days": 15
                    }
                  }
                ],
                "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": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "abandonment",
            "band": "exceptional",
            "name": "Abandonment",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "cap": null,
              "state": "unverified",
              "guards": [],
              "signals": [],
              "red_flag": false,
              "multiplier_pct": 100,
              "declared_reason": null,
              "unverified_reason": "repository_too_young",
              "unanswered_open_prs": null,
              "unanswered_open_issues": null,
              "days_since_last_merged_pr": null,
              "days_since_last_human_commit": null,
              "days_since_last_human_commit_is_floor": false
            },
            "components": [
              {
                "key": "project_is_still_maintained",
                "name": "Project is still maintained",
                "detail": "maintenance record not established from the collected data",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "abandonment_unverified",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Is the project alive — is code being written and are releases shipping?"
      },
      {
        "key": "community",
        "band": "critical",
        "name": "Community & Adoption",
        "value": 17,
        "weight": 0.17,
        "metrics": [
          {
            "key": "popularity",
            "band": "critical",
            "name": "Popularity & adoption",
            "note": null,
            "notes": [],
            "value": 10,
            "inputs": {
              "forks": 1,
              "stars": 5,
              "watchers": 0,
              "growth_state": "unverified",
              "growth_factor_pct": 100,
              "growth_unverified_reason": "no_history"
            },
            "components": [
              {
                "key": "stars",
                "name": "Stars",
                "detail": "5 stars",
                "points": 9.8,
                "status": "partial",
                "details": [
                  {
                    "code": "stars",
                    "params": {
                      "count": 5
                    }
                  }
                ],
                "max_points": 60
              },
              {
                "key": "forks",
                "name": "Forks",
                "detail": "1 forks",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "forks",
                    "params": {
                      "count": 1
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "watchers",
                "name": "Watchers",
                "detail": "0 watchers",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "watchers",
                    "params": {
                      "count": 0
                    }
                  }
                ],
                "max_points": 15
              }
            ]
          },
          {
            "key": "community_health",
            "band": "at_risk",
            "name": "Community health",
            "note": null,
            "notes": [],
            "value": 25,
            "inputs": {
              "has_readme": true,
              "has_license": false,
              "readme_badges": 1,
              "has_contributing": false,
              "has_issue_template": false,
              "has_code_of_conduct": false,
              "readme_badge_services": [
                "shields.io"
              ],
              "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": "weak",
        "name": "Sustainability & Governance",
        "value": 41,
        "weight": 0.23,
        "metrics": [
          {
            "key": "maintainer_resilience",
            "band": "critical",
            "name": "Maintainer resilience (bus factor)",
            "note": null,
            "notes": [],
            "value": 13,
            "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 1 contributing companies or organizations -- score normalized to 3",
                "points": 3,
                "status": "partial",
                "details": [],
                "max_points": 10
              }
            ]
          },
          {
            "key": "responsiveness",
            "band": "critical",
            "name": "Issue & PR responsiveness",
            "note": "Excluded from scoring (no data or not applicable): PR acceptance, Newcomer PR acceptance. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "pr_acceptance",
                    "newcomer_pr_acceptance"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 1,
            "inputs": {
              "merged_prs": 0,
              "open_issues": 1,
              "closed_issues": 0,
              "prs_merged_7d": 0,
              "prs_decided_7d": 0,
              "prs_merged_30d": 0,
              "prs_decided_30d": 0,
              "issue_closed_ratio": 0,
              "closed_unmerged_prs": 0,
              "first_time_authors_30d": 0,
              "first_time_prs_merged_30d": 0,
              "first_time_prs_decided_30d": 0
            },
            "components": [
              {
                "key": "issue_resolution",
                "name": "Issue resolution",
                "detail": "0% of issues closed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "issues_closed_share",
                    "params": {
                      "share": 0
                    }
                  }
                ],
                "max_points": 42
              },
              {
                "key": "pr_acceptance",
                "name": "PR acceptance",
                "detail": "no decided pull requests or no data",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_decided_prs_or_data",
                    "params": {}
                  }
                ],
                "max_points": 30
              },
              {
                "key": "newcomer_pr_acceptance",
                "name": "Newcomer PR acceptance",
                "detail": "no first-time contributor's PR decided in 30d",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_newcomer_prs",
                    "params": {
                      "days": 30
                    }
                  }
                ],
                "max_points": 13
              },
              {
                "key": "openssf_scorecard_code_review",
                "name": "OpenSSF Scorecard: Code-Review",
                "detail": "Found 0/30 approved changesets -- score normalized to 0",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              }
            ]
          },
          {
            "key": "stewardship",
            "band": "good",
            "name": "Ownership & stewardship",
            "note": "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": 73,
            "inputs": {
              "followers": 1898,
              "owner_type": "User",
              "is_verified": null,
              "owner_login": "bigwhite",
              "public_repos": 74,
              "account_age_days": 5789
            },
            "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": "1,898 followers of bigwhite",
                "points": 23.6,
                "status": "partial",
                "details": [
                  {
                    "code": "owner_followers",
                    "params": {
                      "count": 1898,
                      "login": "bigwhite"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "track_record",
                "name": "Track record",
                "detail": "74 public repos, account ~15 yr old",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "public_repos",
                    "params": {
                      "count": 74
                    }
                  },
                  {
                    "code": "account_age_years",
                    "params": {
                      "years": 15
                    }
                  }
                ],
                "max_points": 25
              }
            ]
          },
          {
            "key": "package_maintenance",
            "band": "excellent",
            "name": "Package maintenance",
            "note": null,
            "notes": [],
            "value": 92,
            "inputs": {
              "packages": [
                "github.com/bigwhite/cc-session-migrate"
              ],
              "ecosystems": "go",
              "any_deprecated": false,
              "min_days_since_publish": 16
            },
            "components": [
              {
                "key": "published_resolvable",
                "name": "Published & resolvable",
                "detail": "1 package(s) on go",
                "points": 25,
                "status": "met",
                "details": [
                  {
                    "code": "packages_published",
                    "params": {
                      "count": 1,
                      "ecosystems": "go"
                    }
                  }
                ],
                "max_points": 25
              },
              {
                "key": "publish_recency",
                "name": "Publish recency",
                "detail": "latest publish 16 days ago",
                "points": 35,
                "status": "met",
                "details": [
                  {
                    "code": "publish_recency",
                    "params": {
                      "days": 16
                    }
                  }
                ],
                "max_points": 35
              },
              {
                "key": "version_history",
                "name": "Version history",
                "detail": "2 published versions",
                "points": 12,
                "status": "partial",
                "details": [
                  {
                    "code": "published_versions",
                    "params": {
                      "count": 2
                    }
                  }
                ],
                "max_points": 20
              },
              {
                "key": "not_deprecated",
                "name": "Not deprecated",
                "detail": "active, not deprecated or yanked",
                "points": 20,
                "status": "met",
                "details": [
                  {
                    "code": "package_not_deprecated",
                    "params": {}
                  }
                ],
                "max_points": 20
              }
            ]
          }
        ],
        "description": "Will the project survive its people — bus factor, responsiveness, who backs it, and package upkeep?"
      },
      {
        "key": "engineering",
        "band": "moderate",
        "name": "Engineering Quality",
        "value": 54,
        "weight": 0.19,
        "metrics": [
          {
            "key": "engineering_practices",
            "band": "at_risk",
            "name": "Engineering practices",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: CI-Tests. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_ci_tests"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 30,
            "inputs": {
              "has_ci": false,
              "has_tests": true,
              "has_editorconfig": false,
              "has_linter_config": false,
              "has_precommit_config": false
            },
            "components": [
              {
                "key": "ci_workflows",
                "name": "CI workflows",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "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": "excellent",
            "name": "Documentation",
            "note": null,
            "notes": [],
            "value": 90,
            "inputs": {
              "topics": [
                "claude-code",
                "cli-tool",
                "dev-tools",
                "distributed-systems",
                "golang",
                "hub-and-spoke",
                "s3-backup",
                "session-migration",
                "websocket"
              ],
              "has_wiki": false,
              "homepage": "http://tonybai.com",
              "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": "http://tonybai.com",
                "points": 15,
                "status": "met",
                "details": [],
                "max_points": 15
              },
              {
                "key": "repository_description",
                "name": "Repository description",
                "detail": null,
                "points": 10,
                "status": "met",
                "details": [],
                "max_points": 10
              },
              {
                "key": "topics",
                "name": "Topics",
                "detail": "9 topics",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "topics_count",
                    "params": {
                      "count": 9
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "wiki",
                "name": "Wiki",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 10
              }
            ]
          }
        ],
        "description": "Are baseline engineering and documentation practices in place?"
      },
      {
        "key": "security",
        "band": "at_risk",
        "name": "Security",
        "value": 22,
        "weight": 0.16,
        "metrics": [
          {
            "key": "security_posture",
            "band": "at_risk",
            "name": "Security posture",
            "note": "Excluded from scoring (no data or not applicable): CI-Tests, Dangerous-Workflow, Packaging, Pinned-Dependencies, Signed-Releases, Token-Permissions. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "ci_tests",
                    "dangerous_workflow",
                    "packaging",
                    "pinned_dependencies",
                    "signed_releases",
                    "token_permissions"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 22,
            "inputs": {
              "source": "openssf_scorecard",
              "checks_evaluated": 12,
              "scorecard_version": "v5.5.0",
              "checks_inconclusive": 6,
              "scorecard_aggregate": 2.2
            },
            "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 1 contributing companies or organizations -- score normalized to 3",
                "points": 0.8,
                "status": "partial",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "dangerous_workflow",
                "name": "Dangerous-Workflow",
                "detail": "no workflows found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              },
              {
                "key": "dependency_update_tool",
                "name": "Dependency-Update-Tool",
                "detail": "no update tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 7.5
              },
              {
                "key": "fuzzing",
                "name": "Fuzzing",
                "detail": "project is not fuzzed",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "license",
                "name": "License",
                "detail": "license file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 2.5
              },
              {
                "key": "maintained",
                "name": "Maintained",
                "detail": "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": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 5
              },
              {
                "key": "sast",
                "name": "SAST",
                "detail": "no SAST tool detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "security_policy",
                "name": "Security-Policy",
                "detail": "security policy file not detected",
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 5
              },
              {
                "key": "signed_releases",
                "name": "Signed-Releases",
                "detail": "no releases found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "token_permissions",
                "name": "Token-Permissions",
                "detail": "No tokens found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 7.5
              },
              {
                "key": "vulnerabilities",
                "name": "Vulnerabilities",
                "detail": "1 existing vulnerabilities detected",
                "points": 6.8,
                "status": "partial",
                "details": [],
                "max_points": 7.5
              }
            ]
          },
          {
            "key": "high_risk_jurisdiction_exposure",
            "band": "exceptional",
            "name": "High-Risk Jurisdiction Exposure",
            "note": "Only high-confidence self-published location evidence affects this multiplier. Ambiguous matches are review-only; country evidence is not proof of nationality, citizenship, legal registration, malicious intent, or sanctions status.",
            "notes": [
              {
                "code": "jurisdiction_evidence_limits",
                "params": {}
              }
            ],
            "value": 100,
            "inputs": {
              "meaning": "self-published location evidence; not nationality or citizenship",
              "red_flag": false,
              "exposures": [],
              "policy_countries": [
                "Russia",
                "Iran",
                "North Korea"
              ],
              "commit_weight_rule": {
                "min_commits": 50,
                "min_commit_share": 0.1
              },
              "review_only_matches": 0,
              "below_threshold_exposures": [],
              "assessed_self_published_locations": 2
            },
            "components": [
              {
                "key": "policy_exposure_multiplier",
                "name": "Policy exposure multiplier",
                "detail": "no confirmed policy-scope location match",
                "points": 100,
                "status": "met",
                "details": [
                  {
                    "code": "jurisdiction_no_match",
                    "params": {}
                  }
                ],
                "max_points": 100
              }
            ]
          }
        ],
        "description": "Are visible security and supply-chain practices strong, with no malicious dependency and no unresolved high-risk jurisdiction exposure?"
      },
      {
        "key": "ai_readiness",
        "band": "excellent",
        "name": "AI Readiness",
        "value": 85,
        "weight": 0.04,
        "metrics": [
          {
            "key": "ai_agent_context",
            "band": "excellent",
            "name": "Agent context & guidance",
            "note": null,
            "notes": [],
            "value": 85,
            "inputs": {
              "has_llms_txt": false,
              "legible_history_share": 0.988,
              "agent_instruction_files": [
                "CLAUDE.md"
              ],
              "agent_instruction_max_bytes": 303
            },
            "components": [
              {
                "key": "agent_instructions",
                "name": "Agent instructions",
                "detail": "CLAUDE.md",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "CLAUDE.md"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "machine_readable_docs_llms_txt",
                "name": "Machine-readable docs (llms.txt)",
                "detail": null,
                "points": 0,
                "status": "missed",
                "details": [],
                "max_points": 15
              },
              {
                "key": "legible_commit_history",
                "name": "Legible commit history",
                "detail": "82 of 83 human commits state their intent (structured subject or explanatory body)",
                "points": 40,
                "status": "met",
                "details": [
                  {
                    "code": "legible_history",
                    "params": {
                      "legible": 82,
                      "sampled": 83
                    }
                  }
                ],
                "max_points": 40
              }
            ]
          },
          {
            "key": "ai_verify_loop",
            "band": "good",
            "name": "Verify loop (build / test / typecheck)",
            "note": "Excluded from scoring (no data or not applicable): OpenSSF Scorecard: Pinned-Dependencies. Remaining weights renormalized.",
            "notes": [
              {
                "code": "excluded_no_data",
                "params": {
                  "components": [
                    "openssf_scorecard_pinned_dependencies"
                  ]
                }
              },
              {
                "code": "weights_renormalized",
                "params": {}
              }
            ],
            "value": 79,
            "inputs": {
              "has_nix": false,
              "has_tests": true,
              "lockfiles": [
                "go.sum"
              ],
              "has_dockerfile": false,
              "typed_language": true,
              "bootstrap_files": [
                "Makefile"
              ],
              "has_devcontainer": false,
              "has_linter_config": false,
              "typecheck_configs": [],
              "agent_commit_share": 0.976,
              "toolchain_manifests": [
                "go.mod"
              ],
              "dependency_bot_commit_share": 0
            },
            "components": [
              {
                "key": "one_command_bootstrap",
                "name": "One-command bootstrap",
                "detail": "Makefile",
                "points": 18,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "Makefile"
                    }
                  }
                ],
                "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": "Go (statically typed)",
                "points": 11,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 11
              },
              {
                "key": "reproducible_environment",
                "name": "Reproducible environment",
                "detail": "lockfile",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "file_list",
                    "params": {
                      "files": "lockfile"
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "demonstrated_agent_practice",
                "name": "Demonstrated agent practice",
                "detail": "81 of the last 83 commits agent-authored or agent-credited",
                "points": 10,
                "status": "met",
                "details": [
                  {
                    "code": "agent_authored_commits",
                    "params": {
                      "count": 81,
                      "sampled": 83
                    }
                  }
                ],
                "max_points": 10
              },
              {
                "key": "automated_maintenance",
                "name": "Automated maintenance",
                "detail": "no automated dependency updates observed",
                "points": 0,
                "status": "missed",
                "details": [
                  {
                    "code": "no_dependency_automation",
                    "params": {}
                  }
                ],
                "max_points": 8
              },
              {
                "key": "openssf_scorecard_pinned_dependencies",
                "name": "OpenSSF Scorecard: Pinned-Dependencies",
                "detail": "no dependencies found",
                "points": 0,
                "status": "excluded",
                "details": [
                  {
                    "code": "no_data",
                    "params": {}
                  }
                ],
                "max_points": 10
              }
            ]
          },
          {
            "key": "ai_code_legibility",
            "band": "exceptional",
            "name": "Code legibility for models",
            "note": null,
            "notes": [],
            "value": 100,
            "inputs": {
              "primary_language": "Go",
              "largest_source_bytes": 16162,
              "source_files_sampled": 47,
              "oversized_source_files": 0
            },
            "components": [
              {
                "key": "type_checkable_code",
                "name": "Type-checkable code",
                "detail": "Go (statically typed)",
                "points": 45,
                "status": "met",
                "details": [
                  {
                    "code": "statically_typed_language",
                    "params": {
                      "language": "Go"
                    }
                  }
                ],
                "max_points": 45
              },
              {
                "key": "manageable_file_sizes",
                "name": "Manageable file sizes",
                "detail": "0/47 source files over 60KB",
                "points": 55,
                "status": "met",
                "details": [
                  {
                    "code": "oversized_source_files",
                    "params": {
                      "kb": 60,
                      "sampled": 47,
                      "oversized": 0
                    }
                  }
                ],
                "max_points": 55
              }
            ]
          }
        ],
        "description": "How well is the repo equipped to be developed and maintained with AI coding agents? Carries a deliberately small weight: agent tooling is a real maintenance signal, but its absence must never gate the top of the scale (calibration saturates at raw 91, so 100/100 remains reachable with AI Readiness at zero)."
      }
    ],
    "classification": {
      "top": [
        "application"
      ],
      "labels": [
        "cli"
      ],
      "scores": {
        "cli": 6,
        "library": 3,
        "application": 5
      },
      "primary": "cli",
      "evidence": [
        {
          "tier": "structure",
          "label": "application",
          "source": "tree.go_main",
          "weight": 5
        },
        {
          "tier": "dependencies",
          "label": "cli",
          "source": "dep:github.com/spf13/cobra",
          "weight": 4
        },
        {
          "tier": "distribution",
          "label": "library",
          "source": "registry:go",
          "weight": 3
        },
        {
          "tier": "tags",
          "label": "cli",
          "source": "tag:cli-tool",
          "weight": 2
        }
      ],
      "artifacts": [],
      "confidence": "medium",
      "host_extension": false,
      "runs_as_process": true,
      "consumed_by_code": false
    },
    "metrics_version": "2.5.0"
  },
  "warnings": [
    "Star history unavailable: GitHub GraphQL error: Resource not accessible by personal access token",
    "GitHub dependency-graph SBOM unavailable (404); the dependency graph may be disabled for this repository"
  ],
  "report_type": "repository",
  "generated_at": "2026-08-05T09:20:19.576205Z",
  "schema_version": "0.31.0",
  "badge_url": "https://raw.githubusercontent.com/inspect-software/badges/main/v1/b/bigwhite/cc-session-migrate.svg",
  "full_name": "bigwhite/cc-session-migrate",
  "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 v2.5.0, Schema v0.31.0 — vollständige Methodik · Metriken-Wiki.

Wie ein einzelnes Ergebnis im Gesamtregister steht: aggregierte StatistikenGo.