Why CI enforcement matters

  • Generation-time hooks cover interactive and agentic Claude Code sessions
  • Code can also arrive from manual edits, other tools, or agents without hook coverage
  • CI enforcement is the backstop — every commit checked regardless of how it was produced
  • Positions governance at three layers: generation time → PR review → CI gate

How it works

  • mneme check validates a file or diff against the decision corpus in .mneme/project_memory.json
  • Run against changed files in a PR to surface any architectural violations
  • Exit code 2 = violation found → CI step fails → PR blocked
  • Exit code 0 = no violations → CI step passes

Example workflow

# .github/workflows/mneme-governance.yml
name: Architectural Governance

on:
  pull_request:
    branches: [main]

jobs:
  governance:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - run: pip install mneme-hq
      - name: Check changed files
        run: |
          git diff --name-only origin/main...HEAD | \
            xargs -I{} mneme check {}

Status

  • CI enforcement gate is Phase 1 current focus — see the roadmap
  • The mneme check command is available today via pip install mneme-hq
  • The GitHub Actions workflow above is the reference integration pattern
  • Managed GitHub Actions workflow artifact coming in Q3 2026

Layered governance model

Layer 1: Generation-time enforcement via Claude Code hooks
Layer 2: PR review (human + AI)
Layer 3: CI gate via Mneme in GitHub Actions

What the gate actually checks

The CI step runs mneme check --mode strict against the PR diff and the project's decision corpus. The check returns a structured verdict per touched file, with three possible outcomes:

  • PASS — the diff respects the relevant decisions. Exit code 0, CI green.
  • WARN — the diff introduces something the corpus flags as policy-bordering (an unapproved dependency, a scope-boundary edge case). Exit code 0 in default mode, surfaces a structured comment via the action's PR-comment step.
  • FAIL — the diff violates a hard architectural decision. Exit code 2 in strict mode, fails the workflow, blocks the PR until resolved or explicitly overridden.

Override events are themselves tracked: an override is a decision record with a rationale, scope, and expiry, committed as part of the same PR. Weakening a constraint costs the same as introducing one — a structured edit reviewers can see, not a quiet bypass.

FAQ

Should we run this on every PR or only on main?
Every PR. The point of CI enforcement is to surface violations at PR time when the cost of fixing is lowest. Running only on main means failures land after merge, which defeats the gating purpose. The check is fast (deterministic keyword scoring, no embedding model) so per-PR cost is negligible.
What if a PR needs to override a decision intentionally?
Add an override record to project_memory.json as part of the same PR — with rationale, scope, and expiry. The check picks it up automatically. The override is reviewable in the PR diff like any other change, so weakening a constraint is a visible decision rather than a silent merge.
How does this compare to running CodeRabbit or a custom linter in CI?
Different layers. Linters check syntax and style; CodeRabbit reviews PRs for correctness and security; Mneme enforces architectural decisions against the project's own decision corpus. They compose: the typical CI sequence is lint → mneme check → tests → CodeRabbit review. See the CodeRabbit comparison for the detail.