Skip to content

Concepts

cogpin rests on one rule, enforced at parse time:

severity = "block" REQUIRES kind = "fact"

A fact is something the gated agent cannot author: added/removed diff lines, per-file A/M/D status, the command string, the current branch, PR/commit metadata, reviewer approvals. Only facts may hard-block. Anything that needs judgment — an LLM-judge, a self-attestation the agent ticks — is advisory: it warns or nudges, never blocks.

This one rule is the whole guarantee — what we mean by cogpin’s “moat.” A forgetful or over-confident agent can’t pass a block it didn’t actually satisfy, because it never wrote the evidence the block reads. And the boundary can’t silently erode, because validate rejects any block that isn’t a fact. The honest flip side: anything genuinely semantic (did the test meaningfully exercise the change? is this refactor safe?) stays advisory — cogpin surfaces it, a human decides.

The agent layer and the change layer enforce the same config twice
Text version of the diagram

Two enforcement points, one config: the agent layer (Claude Code PreToolUse / Stop, live as the agent works, bypassable) and the change layer (git pre-push + CI, authoritative, base-pinned, ignores the bypass). The table below is the full breakdown.

Layer Fires at Authority
agent Claude Code PreToolUse / Stop hook real-time friction: denies --no-verify, commit/push on a protected branch, and an un-DoD’d push/merge; Stop blocks turn-end on unticked attestation. Bypassable (and logged)
change git pre-push hook + CI authoritative — base-pinned, ignores the bypass

The agent layer catches the cut the moment the agent reaches for it and mirrors what CI will enforce, so you fix it before you push. The change layer is the final word — a red CI check no env var can turn green.

A fact block is only ungameable if the agent can’t edit the gate in the same diff it’s being gated on.

Base-pinning: the gate is read from the base ref, not the PR head
Text version of the diagram

cogpin reads cogpin.toml from the base ref, not the PR head. So a diff that relaxes a check is judged against the old policy — the secret it adds is still blocked even if the PR’s own config has zero blocks left. The diff can’t loosen the gate that gates it.

  • Base-pinningcogpin.toml (and your gate-defining files) are read from the pinned base ref, never the PR head. A same-PR edit that relaxes a check is evaluated against the old policy, so it can’t disarm itself.
  • protected_path — changing those gate-defining files needs an independent approval.
  • Isolated run — invoke tools isolated (ruff --isolated, a pinned pytest -c …) so head-side config can’t defang the teeth.

The primitive library isn’t a guess. Its fact-kind rules were derived two ways: a first-principles pass over how agents cut corners, then an empirical mining of real AI-authored history — a 30-agent sweep over nine corpora (the Claude Code issue tracker, public CLAUDE.md/AGENTS.md repos, AI-authored reverts, a real review ledger, competitor rule sets) that produced 95 findings, 19 candidate gaps, and six adversarially-verified fact-kind gaps.

corner-cut primitive evidence
Scope creep (edit outside the task) scope_lock the #1 reported class — 10+ issues incl. one titled “SCOPE LOCK violation”
Smuggle a verb past a prefix rule (git -C p push) forbid_command{deny} a tracker issue ships the exact repro table
Lower a coverage threshold / raise retries numeric_floor 20+ real commits in ~6 weeks (85→75, →19%, →5%)
Commit a multi-MB binary (zero diff lines) max_added_file_bytes invisible to every line-based rule; mirrors pre-commit’s most-installed hook
[skip ci] to disarm the host forbid_in_message one token disarms the change layer’s own CI
Approve-then-push games (stale / self / bot) approval_policy the gameable shape behind a bare approval check

The eight semantic-weakening classes a fact can’t prove — assertion-loosening, fake implementation, regex relaxing, guard removal, silent fallback, tautological test, scope drift, comment rot — can’t hard-block (that would block on a judgment the agent authors), so they ship as the advisory judge library. The full matrix, with every citation, is in docs/coverage-map.md.

cogpin guarantees the forcing function, not omniscience. A fact block can’t be talked past — that’s the strong claim, and it holds. But secret_scan is best-effort pattern matching (pair it with gitleaks via a run block); forbid_removal/forbid_pattern are presence-ungameable but value-gameable (assert(true) satisfies a naive “has an assert”); attest/judge are advisory by construction; and a human with repo-admin rights can always change the base policy through review. The line cogpin draws: anything an agent can do mid-task to cut a corner, it stops; anything that needs human judgment stays advisory and visible.

This isn’t hypothetical. Two reports in Claude Code’s own tracker name the gap exactly: #32198 (“skips mandatory rules in CLAUDE.md — Definition of Done”) and #40117 (“bypasses git pre-commit hooks using --no-verify despite explicit deny rules”). A prose rule asks; cogpin makes the unwanted outcome a non-event.