chameleon 2.14.1
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_reviewis on, the correctness and duplication lenses ran sequentially, each spawning a reviewer with its own ~45s budget — a worst case of ~90s that the 55sstop-backstoptimeoutwould SIGKILL, losing the review while the per-session budget was already spent.run_lensesnow 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); onlyimport-preferenceaccepted 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, matchingimport-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.
BaseControllertold to inheritApi::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 itseval(into the dangerous-sink scan because the bracket-pair delimiter arms were non-nesting, risking aneval-callfalse 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.mdwas 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 bareminitest) was not classified as a test command, so the Stop-gate test nudge could fire after a passing minitest run. Added a standaloneminitestrunner pattern alongside theruby -Itestform.profile.summary.mdreported "0 rule(s)" for the TypeScript config.count_config_rulesonly counted a nestedrulessub-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; defaultsonnet) in CLAUDE.md, and corrected a stale "20 tools" docstring intools.py(the surface is 37 tools).