From cce3c8b8bef990449286d9b1eff7c1c6419d2a8f Mon Sep 17 00:00:00 2001 From: Ben Kearns <35475+bkearns@users.noreply.github.com> Date: Sat, 27 Jun 2026 13:50:12 -0700 Subject: [PATCH 1/3] ci: add GitHub Actions workflow for PRs Runs on pull_request into main: pre-commit (--all-files), a Python compile check, and a hermetic installer dry-run (stubs the ferrosa-memory turn-hook helper and writes to a temp dir). PR-only because pre-commit's no-commit-to-branch hook fails on main by design. --- .github/workflows/ci.yml | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..510a4f4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI + +# Runs on pull requests into main. Branch protection requires the `checks` +# job to pass before merge. Not run on push to main: pre-commit's +# no-commit-to-branch hook would fail there by design, and merges are gated +# at the PR instead. +on: + pull_request: + branches: [main] + +permissions: + contents: read + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true + +jobs: + checks: + name: checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: pip + + - name: Install pre-commit + run: python -m pip install --upgrade pip pre-commit + + - name: Run pre-commit (all files) + run: pre-commit run --all-files --show-diff-on-failure --color always + + - name: Compile Python + run: python -m compileall -q hooks plugin + + - name: Installer dry-run (hermetic) + run: | + # The turn-hook helper ships with ferrosa-memory, not this repo; stub + # it so the installer's existence check passes (the dry-run only checks + # it exists, never executes it). Write wrappers to a temp dir so the + # runner's real ~/.config is never touched. + mkdir -p scripts/hooks + printf '#!/usr/bin/env python3\n' > scripts/hooks/ferrosa-memory-turn-hook.py + python3 hooks/install-agent-hooks.py \ + --harness all --dry-run --no-apply-config --skip-auth-check \ + --install-dir "$RUNNER_TEMP/fmem-hooks" From 80d6077a579c414ae7e3a4532c7b24d7731cceb6 Mon Sep 17 00:00:00 2001 From: Ben Kearns <35475+bkearns@users.noreply.github.com> Date: Sat, 27 Jun 2026 13:51:14 -0700 Subject: [PATCH 2/3] ci: drop pip cache (no deps file), cache pre-commit envs instead --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 510a4f4..a5f393c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,12 @@ jobs: - uses: actions/setup-python@v5 with: python-version: "3.12" - cache: pip + + - name: Cache pre-commit environments + uses: actions/cache@v4 + with: + path: ~/.cache/pre-commit + key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - name: Install pre-commit run: python -m pip install --upgrade pip pre-commit From 77e14d5df6dc6fe4f6cecc9688954cc5e2d5e10f Mon Sep 17 00:00:00 2001 From: Ben Kearns <35475+bkearns@users.noreply.github.com> Date: Sat, 27 Jun 2026 13:54:29 -0700 Subject: [PATCH 3/3] ci: skip bandit checks for documented intentional patterns B310 (raw-urllib MCP client), B404/B603 (installer's fixed verification subprocess), B110 (fail-open config load) are intentional per CLAUDE.md. A stale local pre-commit venv masked these; pinning the skip list makes bandit deterministic in CI. --- .pre-commit-config.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2cbee45..72cbc78 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -71,7 +71,11 @@ repos: rev: 1.8.0 hooks: - id: bandit - args: [-r, --skip=B101] + # Skipped checks reflect intentional, documented design (see CLAUDE.md): + # B101 assert; B110 try/except/pass (fail-open config load); + # B310 urllib.urlopen (the raw-urllib MCP client, loopback endpoint); + # B404/B603 subprocess (installer's fixed verification commands). + args: [-r, "--skip", "B101,B110,B310,B404,B603"] files: ^(plugin|hooks)/.*\.py$ # ---------------------------------------------------------------------------