Concepts
Fact vs judgment — the moat
Section titled “Fact vs judgment — the moat”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.
Two layers, one config
Section titled “Two layers, one config”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.
Why it can’t loosen itself
Section titled “Why it can’t loosen itself”A fact block is only ungameable if the agent can’t edit the gate in the same diff it’s
being gated on.
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-pinning —
cogpin.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 pinnedpytest -c …) so head-side config can’t defang the teeth.
Coverage map
Section titled “Coverage map”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.
What it does and doesn’t claim
Section titled “What it does and doesn’t claim”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.