Releases: BGMLAI/gate.cat
Release list
0.4.9 — two live-caught fixes: RM_RF filename FP; block outranks warn
Fixed
- RM_RF no longer false-blocks filenames that look like flags. Caught live during the 0.4.8 release:
rm /tmp/pypirc-freshwas vetoed because the old whole-line lookahead read-freinside the filename as an-frflag. Flags are now matched as tokens (rm "-rf" /still blocks) and the match stays inside one command segment (rm x && tar -rf a.tar yis no longer blamed onrm). All dangerous spellings stay caught:-rf,-fr,-Rf,-rfv,-vrf,-Rfi, split-r -f/-f -r. - Block-level policy outranks warn-level in attribution, order-independent. Caught live productizing the policy packs: attribution was first-match-in-list-order, so the core generic net
HTTP_API_DELETE_GENERIC(warn) silently downgraded a hard danger an operator pack's block rule also matched —GATECAT_EXTRA_POLICIESappends packs after the built-ins. Attribution is now two-pass (block first, then warn): a hard match is never degraded by list order; a warn-only match still warns.
Full suite: 1005 passed, 27 skipped. Bypass suite: 70/70 dangers, benign corpus grown by the filename-substring class.
0.4.8 — policy packs plug into the hook; 28 core defaults
Added
GATECAT_EXTRA_POLICIESloader — operator policy packs now reach the hook and the proxy. Previously the Claude Code hook and the proxy hard-coded the built-in defaults, so an installed pack only worked through the SDK — never in the strongest enforcement point (the PreToolUse block that runs before the command executes). Set a comma-separated module list (GATECAT_EXTRA_POLICIES=gatecat_packs.fintech,mycompany.policies); each module'sPOLICIESlist and every*_PACKattribute are folded in after the built-ins. Fail-closed: an unimportable module, a non-Policy object, or a named-but-empty module blocks the hook (exit 2, even in shadow mode) and refuses to start the proxy — a security tool must never run without a policy the operator believes is enforced. 19 tests incl. subprocess end-to-end.- Coverage-audit promotion: 5 new core default policies (
DOGFOOD_DEFAULTS23 → 28). The 2026-07-09 audit of 448 real destructive commands found three universal + catastrophic classes passing the default gate (non-delete verb shapes):IAM_PRIVILEGE_ESCALATION(block) +IAM_IDENTITY_TAMPER(warn),BACKUP_DESTROY(block — restic/borg forget/prune, zfs destroy, cloud snapshot delete),HTTP_API_IDENTITY_DNS_DESTROY(block —curl -X DELETEto identity/DNS/registrar APIs) +HTTP_API_DELETE_GENERIC(warn). Bypass suite 65/65 → 70/70; benign twins verified passing. gate.cat report [YYYY-MM]— free local monthly report (Markdown, counts-only, nothing leaves the machine).gatecat/cloud_reporter.py— optional cloud client: OFF unlessGATECAT_CLOUD_API_KEYis set, hash-by-default, never in the gate's execution path.
Full suite: 1001 passed, 27 skipped. Wheel verified in a clean venv (hook e2e from the installed package).
0.4.7 — positioning fix: the veto is model-agnostic
"Built for cheap/local model agents" was inaccurate. The action-veto is deterministic and model-agnostic — it inspects the tool call at the boundary, so it protects any agent the same way, and the flagship integration is a Claude Code hook (a frontier model). Reframed the description, GitHub About, README, and llms.txt to "for any tool-using agent, from a Claude Code hook to local LLMs". The 7-30B strength is real but belongs to the uncertainty signal (a secondary feature) — now scoped there, not applied to the whole product. No code change. FACTS F9 → 0.4.7.
0.4.6 — cache-path entry points honor the zero-dep-core contract
A plain pip install gate-cat gives a zero-dependency veto. This release makes the cache-side tools degrade as gracefully as the core already promised.
gatecat-clino longer crashes with a rawModuleNotFoundError: numpy— it printsinstall gate-cat[cache]and exits cleanly. Bonus:gatecat-cli audit(which runs against your endpoint, not the cache) now works without the cache stack.from gatecat import CachedOpenAI/CachedAnthropicwithout the deps now name the right extra (missing numpy →[cache], missingopenai→[openai]), not a raw traceback.- +6 regression tests. The veto path was already clean and is unchanged.
FACTS F9 → 0.4.6.
0.4.5 — the hook gets a home on the landing page
The Claude Code hook is the #1 pitch (enforcement outside the model's control flow), but the landing README only mentioned it. This release gives it a copy-paste home.
- README 'The hook — the strongest mode' section — the ready-to-paste
.claude/settings.jsonPreToolUse block, right after Install, with a working first-run test. - Dashboard empty-state fixed — was pointing
pip installusers atexamples/(not shipped in the wheel); now names the actionable steps and links the README hook section. - README proxy: 20 → 21 deny policies (FACTS F10).
All doc claims verified this session against the live hook subprocess, proxy /health, CLI dashboard (empty + populated + why), and both demo casts. Tests 907/27/0.
0.4.4 — adapter examples degrade cleanly; Beta + Security on PyPI
Polish pass on the first-run experience and PyPI discoverability. No engine change.
- Adapter examples stop crashing without the framework.
veto_crewai.pyandveto_langgraph.pymoved their framework import intomain()behind a try/except — apip install gate-catuser running the example now gets a one-line "installgate-cat[crewai]/[langgraph]to run this adapter demo; the gate itself needs none of it" instead of a rawModuleNotFoundError. Verified: both print the clean message with no framework installed. - Hook example README dropped the
>= 0.3.0note and the "fix the absolute path toveto_hook.py" step that contradictedsettings.example.json(it calls thegatecat-hookconsole script by name — nothing to edit). - PyPI metadata: Development Status Alpha → Beta, added
Topic :: SecurityandQuality Assuranceclassifiers + security keywords (verified live on the 0.4.4 JSON API). So the package shows up as the guardrail it is.
Clean-venv verified: pip install gate-cat==0.4.4 → hero snippet raises VETO [TERRAFORM_PROD]. Tests 907/27/0 local.
0.4.3 — recall harness + gh-release-asset fix
Two false-positive/UX fixes plus the recall measurement harness.
Fixed
gh release delete-assetno longer false-blocks — deleting a re-uploadable release asset isn't the same class as deleting a release/repo/secret. (This one false-blocked while cutting this very release, on the pre-0.4.3 hook — a real veto story.)scripts/recall_danger_axis.pyruns with a barepip install gate-cat— the shared danger catalog imported HuggingFacedatasetsat module top and crashed the dataset-free recall check withModuleNotFoundError. That import is now lazy.
Added — recall, measured two ways against the full 6-stage gate
python scripts/recall_danger_axis.py→ 43/43 known danger classes neutralized, 0 false-blocks on benign twins. Deterministic, no datasets, runs in seconds.- 1,085,159 unique real agent commands streamed from five public trajectory datasets → 0 real recall misses (the 4 catalog-flagged allows are disposable-artifact cleanups the gate correctly permits; the same shape blocks on a real target). Artifact:
results/million_recall_2026-07-08.json, method inRECALL.md, numbers inFACTS.md(F1a/F1b).
0.4.2 — git commit -F is not a force push
False-positive fix, shipped the same day it was found (while dogfooding the 0.4.1 release — see #4 and discussion #5).
GIT_FORCE_PUSHno longer false-blocksgit commit -F filefollowed by a push. The short force flag is now matched case-sensitively, so-F(message-from-file) is no longer read as the force flag. Verified in a clean venv against this PyPI release, all four directions:-Fallows · short force flag blocks · long force flag blocks ·--force-with-leaseallows.- CI green: 892 passed / 28 skipped / 0 failed on py3.11–3.13 (run); regression case added to the bypass suite's benign set.
- PyPI long description now carries the demo GIFs and the "Verify the numbers" section (they landed in the README after 0.4.1 was frozen — closes #3).
PyPI: https://pypi.org/project/gate.cat/0.4.2/ · Still open from the same dogfood batch: the multiline commit-message inert-literal gap (#4).
0.4.1 — one import, one exception, English veto reasons
The launch-blocker release: one import, one exception, English veto reasons.
from gatecat import check_actionworks (top-level export) — the hero snippet is 2 lines.- ONE
ActionVetoedclass package-wide (gatecat.exceptions):except gatecat.ActionVetoednow catches blocks raised bycheck_action. Previously the engine and the integrations layer raised two distinct classes of the same name. - Engine veto reasons Englishized, pure ASCII ("action matches denied pattern /…/", "all walls passed"). Wall ids (
policy-deny/koryto/human) unchanged — API, not prose. - CI: pytest on ubuntu, py3.11/3.12/3.13 — 892 passed / 28 skipped / 0 failed (run).
__version__was stale at 0.3.2 — now matches the distribution.
Verified against the built wheel in a clean venv before upload: bare pip install gate-cat → 0.4.1, the README snippet raises VETO [TERRAFORM_PROD], and echo 'rm -rf /' > notes.md still allows (content is data, not action).
Full changelog: CHANGELOG.md · PyPI: https://pypi.org/project/gate.cat/0.4.1/
0.4.0 — Write/Edit content is data, not action
Changed
- The Claude Code hook no longer hard-blocks on Write/Edit FILE CONTENT.
Pre-0.4.0 the hook flattened the written content into the evaluated action,
so authoring a comment, docstring, test, or doc that merely MENTIONED a
dangerous command (rm -rf,DROP TABLE,gh repo delete, ...) was
vetoed -- writing "rm -rf /" into a Python comment executes nothing. It was
also inconsistent with the engine's own content-vs-command doctrine on the
Bash side, whereecho "rm -rf /" > notes.mdhas always been inert data
(tests/integrations/test_content_vs_command.py). The evaluated action for
Write/Edit is nowwrite <path>: the target path is still gated, the
content is not.GATECAT_HOOK_SCAN_FILE_CONTENT=1in the hook environment restores the
old paranoid behavior (opt-in).- Bash gating is unchanged -- enforcement lives at RUN time, and every
command a file's content may mention still blocks when actually executed
(pinned bytests/integrations/test_write_content_data.py). - Meta-note: this release's own regression tests had to be authored via a
bash heredoc, because the 0.3.x hook kept vetoing the Write calls that
mentioned the patterns under test. The bug blocked writing its own fix.
Added
AUTOEXEC_WRITE(warn) -- the one real risk content scanning used to
catch incidentally, now covered deliberately and on BOTH pathways (the
Write/Edit tool AND bash redirect/tee/cp): a write whose TARGET PATH is
executed later without any visible Bash step --.git/hooks/, shell rc
files,/etc/cron*//var/spool/cron, systemd units,
.claude/settings*.json(editing that one can disarm this very gate), and
crontab <file>. Warn, not block: authoring dotfiles and deploy units is
legitimate, so the ambiguous class surfaces to the human instead of
hard-stopping. This WIDENS coverage vs 0.3.x -- the bash-redirect variant
(echo ... >> ~/.bashrc) was previously a silent allow.