Releases: stawils/coding-guardrails
Release list
v0.14.0
What's New
- Multi-language lint gate — the
lintrule now maps each edited file's extension to the right linter instead of being Python-only:- Python (
.py) →ruff check --select=F,E9 - JS/TS (
.js .jsx .mjs .cjs .ts .tsx .mts .cts) →biome check - Go (
.go) →gofmt -l
- Python (
LinterSpecgainspath_mode(file/dir/project) andfindings_mode(exitcode/stdout) — needed becausegofmt -lalways exits 0 and reports unformatted files via non-empty stdout.- Fully configurable via
lint.lintersin guardrail-config.yaml. Project-mode supportscargo clippy/golangci-lint. Linters that aren't installed degrade gracefully (skipped, edit allowed). - Fix:
.gitignorenow actually ignores.pi-subagents/(the earlier add was lost during the v0.13.0 staging). - +8 unit tests (24 total for the rule).
Full Changelog
v0.13.0
What's New
- New guardrail rule
lint(#13) — runsruffon files the agent edits and nudges or blocks on findings. Offloads defect-noticing to a deterministic tool so local models can't silently ship or touch lint defects. - Fix:
RuleResult.nudgefactory collided with thenudgefield —allow().nudgereturned the function instead ofNone; factory moved outside the class body. - Removed dead
has_tool_historyinproxy/layer1.py. - Repo-wide
rufflint sweep (unused imports acrossrules/) + targeted fixes. - Enforcement injection (
handler.py) now nudges a lint pass before finishing. - New read-tool aliases: sequencing
uv, loop_detectionView, prerequisitesbat; tool_resolution error indicators; +unit tests.
Notes
- History rewritten to purge a mistakenly-tracked
.pi/scratch-pad.json;.pi-subagents/now gitignored. - 13 rules, 538 tests.
Full Changelog
v0.12.2
What's New
Fixed
- Plumb
loop_detection.stagnation_thresholdthrough config.CodingGuardrails.from_config()was silently droppingstagnation_thresholdfrom the YAML config (always fell back to the default of 14). Now passed through like its siblingsnudge_threshold/block_threshold. Adds one focused unit test.
Docs
- Ornith-1.0-9B local assessment: 140/150 (93%) on the Forge eval = parity with the Qwen3.5-9B baseline. Its only failures are terminal-tool commitment (answers in prose instead of calling
respond()), which is Ornith-specific (Qwen base passes 15/15). Seereports/2026-06-27_ornith-assessment.md.
Full Changelog
v0.12.1
What's New
Patch release to refresh the PyPI-rendered README.
- README model table trimmed to the recommended pair: Qwen3.5-9B (default) and Ornith-1.0-9B (reasoning alternative). Removed Gemma 4 12B, Gemma 4 26B-A4B QAT, and Qwen3.6-27B — they were not good enough yet for recommendation.
- The 0.12.0 wheel had been baked with the older 5-row table; PyPI rejects re-uploading an existing version, so this patch ships the trimmed README as a new version.
No code changes since v0.12.0.
Full Changelog
v0.12.0
What's New
- New guardrail rule:
dup_write— detects identical-content duplicate writes (a common finalization-loop signature). Nudges at the 2nd identical write, blocks at the 3rd. Stateful:check()is read-only,record()owns the per-path counter. 15 new unit tests. - New model profile: Ornith-1.0-9B (Q8_0) — DeepReinforce RL post-train on Qwen3.5-9B. Reasoning model (
reasoning_contentcaptured by SafeLlamafileClient). No MTP tensors.
Fixes
registry.find_modelis now source-aware — fixes discovery for models whose upstream GGUF filename differs in casing from the profile name (Ornith ships lowercase files).- Bump pinned llama.cpp to latest master (
5a6a0dd7e) for recent linear-attention and tool-call-parse fixes.
Docs
- Rules count 11 → 12 (
dup_writeis rule #8). README model table trimmed to the recommended pair: Qwen3.5-9B (default) and Ornith-1.0-9B (reasoning alternative).
Full Changelog
v0.11.1
What's New
Docs-only release. Reworked the README / PyPI home page:
- Trimmed from 252 to ~95 lines — scannable in seconds, not minutes.
- Removed the 30-row eval results table (it belonged in a benchmark doc, not the landing page).
- Removed the inline
guardrail-config.yamlreference block (link to docs instead). - Fixed the stale "421 tests" count — now 436.
- Tightened the supported-models table (dropped the "Legacy" row).
No code changes. 436 unit tests pass.
Full Changelog
v0.11.0
What's New
Fixes the long-standing "Acceptance rejected: Structured acceptance report not found" failure for pi-subagents delegation through the proxy. Local models (Qwen3.5-9B) were emitting the acceptance report as bare JSON; Pi's runtime only accepts fenced code blocks, so every delegated run was rejected — even when the work was correct.
- New
proxy/acceptance.py—wrap_bare_acceptance_report()detects bare acceptance-report JSON in the model's text response and wraps it in the fencedacceptance-reportblock Pi parses. Mirrors Pi's own field set and balanced-JSON extraction, so it only fences objects Pi will accept. Wired into both text-return paths inhandler.py. - Acceptance prefill id-seeding —
SafeLlamafileClient._resolve_acceptance_prefill()now parses the contract's real criterion id from the finalization nudge and seeds it in the prefill, so the model'scriteriaSatisfiedid matches the contract (was copying the example's genericcriterion-1→ "Required criterion X was not reported"). - Verified end-to-end: delegation through the proxy now returns a clean ACCEPT.
Tests: 436 unit tests (+15 new: test_acceptance_wrap.py ×12, test_acceptance_prefill.py ×3).
Full Changelog
v0.10.0
What's New
- Acceptance finalization prefill (F9 fix): injects a JSON prefix on pi-subagents acceptance-finalization turns so Gemma 4 completes structured reports instead of narrating prose
- 11 rules (was 10): added thoroughness rule docs — detects premature terminal submission
- Loop detection now tracks unique tool+path combos, not just tool names (v0.9.3 improvement documented)
- Gemma 4 26B A4B QAT is now the default model everywhere (CLI help, profiles, agent examples, docs)
- cg server module added to architecture docs
Full Changelog
v0.9.4
What's New
🔧 cg-owned llama.cpp server stack (decouples from LM Studio)
coding-guardrails now ships its own llama.cpp build, so every user
runs the same reproducible inference stack — no LM Studio, no manual flag
guessing. The pin (afcda09d1, build 9284) is chosen to include critical
fixes, notably the Gemma 4 tool-call grammar fix (llama.cpp #21680)
that older bundled binaries lack.
coding-guardrails server build # one-time
coding-guardrails server download gemma-4-26B-A4B-it-qat-UD-Q4_K_XL
coding-guardrails server start --model gemma-4-26B-A4B-it-qat-UD-Q4_K_XL
coding-guardrails server statusAll artifacts live under ~/.local/share/coding-guardrails/ (XDG-aware). See docs/server.md.
🐛 Delegation reliability fix (root cause)
Subagents through the proxy previously hit a failure where the model
reported a write "done" but the file was unchanged — and retried in a
loop. Root cause was not pi or our config: it was a llama.cpp Gemma 4
bug that corrupted complex/nested JSON tool-call arguments (a path
value cut at a brace inside code). The cg-owned build includes the fix.
🐛 Proxy: max_tokens 8192 → 16384
The default output cap was calibrated for the 9B and was too small for
verbose models (Gemma 4 26B) writing multi-KB files: truncated JSON args
failed validation, the agent retried, same cap truncated again → loop.
16384 fits typical file writes + JSON overhead. pi can still override
per-request.
🔄 Model registry decoupled
The registry now searches cg's own cache first; LM Studio and
HuggingFace caches are read-only fallbacks. A clean cg user never needs
LM Studio.
🧪 24 new tests (390 → 414)
Full coverage of the new server/ module — paths, version pinning, build
clone/configure flow, launcher lifecycle (start/stop/status/double-start),
registry decoupling (cg-cache-wins + fallback), argv assembly, and source
mapping.
Full Changelog
v0.9.3
What's New
🐛 Stagnation rule now tracks unique paths, not just tools (F6)
The loop detection rule's stagnation check used to count unique TOOL
names only. This blocked legitimate batch work — e.g. scaffolding 10
files where the agent only uses write+bash would trip the
stagnation block after 14 calls.
The check now tracks the distinct-paths ratio of recent calls. If
≥70% of calls touch distinct paths, the call is allowed (it's batch
progress, not a loop).
Behavior matrix
| Pattern | Action |
|---|---|
| 14 write() calls, 14 distinct files | ✅ ALLOW (scaffolding) |
| 14 write() calls, all to same file | ❌ BLOCK (real stagnation) |
| 10 calls, 8 unique paths + 2 repeats | ✅ ALLOW (borderline batch) |
| 10 calls, 3 unique paths | ❌ BLOCK (genuine loop) |
Path identity is extracted from path / file_path / cwd /
first arg — handles all common tool dialects.
🧪 5 new regression tests
TestStagnationBatchWorkRefinement— covers the new distinct-paths logictest_scaffolding_many_distinct_files_allowed— F6 baseline regressiontest_repeated_path_stagnation_blocked— ensures real loops still firetest_mixed_some_repeats_allowed_at_threshold— borderline casetest_path_extraction_supports_file_path_arg— alternate arg nametest_call_history_does_not_leak_between_rules— isolation
🛠️ Integration test script
Added tests/integration-subagent-smoke.sh for end-to-end verification
spawning a real subagent through the proxy.