From 6171e3ad5bbfe234ad651edea9f489aab7a1068f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 01:40:46 +0000 Subject: [PATCH 1/2] fix(ci): don't feed an empty latest.json to the registry monitor The first run crashed with JSONDecodeError: the restore step's '>' redirect created an empty latest.json before 'git show' ran, and on a cold start (no data branch yet) that 0-byte file reached SnapshotStore.load_latest(). Guard with 'git cat-file -e' *before* the redirect so the baseline file is only written when it actually exists on the data branch, and 'rm -f' any stray baseline first so an empty file can never reach the monitor. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01DNoTXU8k3pfSBzR7aJubqL --- .github/workflows/registry-monitor.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/registry-monitor.yml b/.github/workflows/registry-monitor.yml index bd458ce..1def7ef 100644 --- a/.github/workflows/registry-monitor.yml +++ b/.github/workflows/registry-monitor.yml @@ -54,13 +54,17 @@ jobs: - name: Restore snapshot baseline from data branch run: | mkdir -p data/registry-snapshots - if git fetch origin registry-monitor 2>/dev/null; then + # Start clean so a stale/empty baseline can never reach the monitor. + rm -f data/registry-snapshots/latest.json + # Only write the baseline when the data branch AND the file both exist + # (checked before the redirect, so we never create an empty file). + if git fetch origin registry-monitor 2>/dev/null \ + && git cat-file -e origin/registry-monitor:data/registry-snapshots/latest.json 2>/dev/null; then git show origin/registry-monitor:data/registry-snapshots/latest.json \ - > data/registry-snapshots/latest.json 2>/dev/null \ - && echo "Restored baseline from registry-monitor branch." \ - || echo "Data branch exists but has no baseline yet." + > data/registry-snapshots/latest.json + echo "Restored baseline from registry-monitor branch." else - echo "No data branch yet — this is the first run." + echo "No baseline yet — first run (cold start, diff against nothing)." fi - name: Sweep registry and diff against baseline From 40449b79aaf3dce7b7aec426df71fba5dffef4a7 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 01:43:55 +0000 Subject: [PATCH 2/2] ci: use dedicated 'registry-snapshots' data branch for the monitor The name 'registry-monitor' was already taken by an old feature branch (full codebase copy) from the initial monitor development. Point the daily sweep at a distinct 'registry-snapshots' branch instead so the snapshot history is clean and doesn't pile on top of stale code. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01DNoTXU8k3pfSBzR7aJubqL --- .github/workflows/registry-monitor.yml | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/registry-monitor.yml b/.github/workflows/registry-monitor.yml index 1def7ef..38eaeaf 100644 --- a/.github/workflows/registry-monitor.yml +++ b/.github/workflows/registry-monitor.yml @@ -2,14 +2,14 @@ # # Runs `malwar crawl monitor` once a day: crawls the whole registry, fast-scans # every skill (escalating flagged ones to the LLM), diffs against the previous -# snapshot, and commits the new snapshot + diff to the `registry-monitor` branch -# so `git log -p registry-monitor` is a permanent, auditable record of what -# changed day over day. +# snapshot, and commits the new snapshot + diff to the `registry-snapshots` +# branch so `git log -p registry-snapshots` is a permanent, auditable record of +# what changed day over day. # # Why a dedicated branch and not `main`? `main` is protected (PR + required # checks), so a scheduled bot cannot push to it. The snapshot history therefore -# lives on its own long-running `registry-monitor` branch, created automatically -# on the first run. +# lives on its own long-running `registry-snapshots` branch, created +# automatically on the first run. # # The LLM escalation needs an Anthropic API key. Add it as a *repository* secret # named MALWAR_ANTHROPIC_API_KEY (Settings -> Secrets and variables -> Actions -> @@ -29,7 +29,7 @@ concurrency: cancel-in-progress: false permissions: - contents: write # push snapshots to the registry-monitor branch + contents: write # push snapshots to the registry-snapshots branch jobs: monitor: @@ -58,11 +58,11 @@ jobs: rm -f data/registry-snapshots/latest.json # Only write the baseline when the data branch AND the file both exist # (checked before the redirect, so we never create an empty file). - if git fetch origin registry-monitor 2>/dev/null \ - && git cat-file -e origin/registry-monitor:data/registry-snapshots/latest.json 2>/dev/null; then - git show origin/registry-monitor:data/registry-snapshots/latest.json \ + if git fetch origin registry-snapshots 2>/dev/null \ + && git cat-file -e origin/registry-snapshots:data/registry-snapshots/latest.json 2>/dev/null; then + git show origin/registry-snapshots:data/registry-snapshots/latest.json \ > data/registry-snapshots/latest.json - echo "Restored baseline from registry-monitor branch." + echo "Restored baseline from registry-snapshots branch." else echo "No baseline yet — first run (cold start, diff against nothing)." fi @@ -86,10 +86,10 @@ jobs: cp -a data/registry-snapshots/. "$tmp/" # Move onto the data branch (create an orphan branch on the first run). - if git rev-parse --verify origin/registry-monitor >/dev/null 2>&1; then - git checkout -B registry-monitor origin/registry-monitor + if git rev-parse --verify origin/registry-snapshots >/dev/null 2>&1; then + git checkout -B registry-snapshots origin/registry-snapshots else - git checkout --orphan registry-monitor + git checkout --orphan registry-snapshots git reset # unstage main's tree; commit only the snapshots below fi @@ -102,5 +102,5 @@ jobs: echo "No registry changes today — nothing to commit." else git commit -m "chore(monitor): registry snapshot $(date -u +%Y-%m-%d)" - git push origin registry-monitor + git push origin registry-snapshots fi