Skip to content

Releases: stawils/coding-guardrails

v0.14.0

Choose a tag to compare

@stawils stawils released this 15 Jul 15:33

What's New

  • Multi-language lint gate — the lint rule 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
  • LinterSpec gains path_mode (file/dir/project) and findings_mode (exitcode/stdout) — needed because gofmt -l always exits 0 and reports unformatted files via non-empty stdout.
  • Fully configurable via lint.linters in guardrail-config.yaml. Project-mode supports cargo clippy / golangci-lint. Linters that aren't installed degrade gracefully (skipped, edit allowed).
  • Fix: .gitignore now 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...v0.14.0

v0.13.0

Choose a tag to compare

@stawils stawils released this 15 Jul 15:08

What's New

  • New guardrail rule lint (#13) — runs ruff on 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.nudge factory collided with the nudge fieldallow().nudge returned the function instead of None; factory moved outside the class body.
  • Removed dead has_tool_history in proxy/layer1.py.
  • Repo-wide ruff lint sweep (unused imports across rules/) + targeted fixes.
  • Enforcement injection (handler.py) now nudges a lint pass before finishing.
  • New read-tool aliases: sequencing uv, loop_detection View, prerequisites bat; 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...v0.13.0

v0.12.2

Choose a tag to compare

@stawils stawils released this 27 Jun 13:45

What's New

Fixed

  • Plumb loop_detection.stagnation_threshold through config. CodingGuardrails.from_config() was silently dropping stagnation_threshold from the YAML config (always fell back to the default of 14). Now passed through like its siblings nudge_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). See reports/2026-06-27_ornith-assessment.md.

Full Changelog

v0.12.1...v0.12.2

v0.12.1

Choose a tag to compare

@stawils stawils released this 26 Jun 13:47

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...v0.12.1

v0.12.0

Choose a tag to compare

@stawils stawils released this 26 Jun 13:40

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_content captured by SafeLlamafileClient). No MTP tensors.

Fixes

  • registry.find_model is 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_write is 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.3...v0.12.0

v0.11.1

Choose a tag to compare

@stawils stawils released this 13 Jun 20:41

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.yaml reference 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...v0.11.1

v0.11.0

Choose a tag to compare

@stawils stawils released this 13 Jun 20:30

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.pywrap_bare_acceptance_report() detects bare acceptance-report JSON in the model's text response and wraps it in the fenced acceptance-report block 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 in handler.py.
  • Acceptance prefill id-seedingSafeLlamafileClient._resolve_acceptance_prefill() now parses the contract's real criterion id from the finalization nudge and seeds it in the prefill, so the model's criteriaSatisfied id matches the contract (was copying the example's generic criterion-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...v0.11.0

v0.10.0

Choose a tag to compare

@stawils stawils released this 08 Jun 10:41

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...v0.10.0

v0.9.4

Choose a tag to compare

@stawils stawils released this 08 Jun 00:16

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 status

All 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...v0.9.4

v0.9.3

Choose a tag to compare

@stawils stawils released this 05 Jun 09:57

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 logic
  • test_scaffolding_many_distinct_files_allowed — F6 baseline regression
  • test_repeated_path_stagnation_blocked — ensures real loops still fire
  • test_mixed_some_repeats_allowed_at_threshold — borderline case
  • test_path_extraction_supports_file_path_arg — alternate arg name
  • test_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.

Full Changelog

v0.9.2...v0.9.3