Skip to content

Chameleon

v2.14.1 Breaking

This release includes breaking changes for platform teams planning a safe upgrade.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

ai-coding-assistant archetype ast-analysis claude-code claude-plugin code-conventions
+12 more
code-review code-style developer-tools javascript linter mcp mcp-server prompt-engineering python ruby rails typescript

Summary

AI summary

Fixed multi‑lens review timeout exceeding stop hook cap.

Full changelog

Remediation of the QA-30 full-surface campaign: a complete plugin inventory plus a five-lane hostile QA pass (failure/recovery, language depth, enforcement, upgrade/migration, regression) over the real bootstrapped repos. No P0/P1 survived independent verification — the calibration demotion, dual ignore-layers, init-skill sparse handling, and git-committed artifacts each downgraded a claimed P1 to P2 — but eight real defects ship fixed, each regression-pinned. Full unit suite 3,622 passing.

Fixed

  • Multi-lens turn-end review could exceed the Stop hook's wall-clock cap. When enforcement.multi_lens_review is on, the correctness and duplication lenses ran sequentially, each spawning a reviewer with its own ~45s budget — a worst case of ~90s that the 55s stop-backstop timeout would SIGKILL, losing the review while the per-session budget was already spent. run_lenses now runs the lenses concurrently, so the pass costs the slowest single lens (~45s), staying under the cap; per-lens fail-open and lens-ordered synthesis are preserved.
  • Ignore directives using the full rule name did not silence the advisory for naming / file-naming / inheritance violations. The lint-engine gates checked only the short token (naming-convention) while the emitted rule — and the name the violation message tells users to copy — is the long form (naming-convention-violation); only import-preference accepted both. The block was already overridable (the block path matches the long name), but the advisory kept firing. All four gates now accept both forms, matching import-preference.
  • Inheritance-convention check flagged classes that ARE an established base. A class whose own name is one of the archetype's known bases (e.g. BaseController told to inherit Api::V1::BaseController — itself), or a Rails application root (ApplicationController/ApplicationRecord/ApplicationJob/ApplicationMailer), is now exempt. On a real Rails repo this removed 5 false positives, lowering a calibration fp_rate that had demoted the rule; a genuinely wrong base still flags.
  • A leading UTF-8 BOM skewed the runtime dimension snapshot. The regex lint extractors (_extract_typescript / _extract_ruby) missed a first-line declaration when the file began with U+FEFF, producing spurious dimension-mismatch advisories on BOM-prefixed files (the dumper bootstrap path was already immune). Both extractors now strip a single leading BOM.
  • %(...) percent-literals with a nested paren were not blanked. A Ruby %(eval(x)) string literal leaked its eval( into the dangerous-sink scan because the bracket-pair delimiter arms were non-nesting, risking an eval-call false positive. The four bracket-pair arms now accept one level of balanced nesting (x % (a + b) modulo is still correctly left alone).
  • Refreshing after idioms.md was deleted silently emptied it. A corrupt idioms.md warned and was preserved, but a deleted one wrote the empty template with no warning — surprising for the one user-authored artifact. Re-deriving over an existing profile with idioms.md absent now warns to restore from git before the empty template is committed.
  • bundle exec minitest (and a bare minitest) was not classified as a test command, so the Stop-gate test nudge could fire after a passing minitest run. Added a standalone minitest runner pattern alongside the ruby -Itest form.
  • profile.summary.md reported "0 rule(s)" for the TypeScript config. count_config_rules only counted a nested rules sub-key; the tsconfig/typescript block stores its settings (strict, target, ...) at the top level, so it now counts those minus the wrapper keys.

Documentation

  • Documented CHAMELEON_JUDGE_MODEL (the model the turn-end reviewers spawn; default sonnet) in CLAUDE.md, and corrected a stale "20 tools" docstring in tools.py (the surface is 37 tools).

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track Chameleon

Get notified when new releases ship.

Sign up free

About Chameleon

All releases →

Related context

Earlier breaking changes

  • v3.0.0 MCP surface folded from 48 tools to 19; remaining 32 operator tools become actions on three dispatchers.

Beta — feedback welcome: [email protected]