This release includes breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Topics
+12 more
Affected surfaces
Summary
AI summaryUpdates P1, str, and nonexistent across a mixed release.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Bugfix | Medium |
Daemon proxy now respects CHAMELEON_TRUST_REVALIDATE=1 and runs revalidate check in-process. Daemon proxy now respects CHAMELEON_TRUST_REVALIDATE=1 and runs revalidate check in-process. Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Medium |
PR‑review auto‑pass now detects removed but still imported exports as contract breaks. PR‑review auto‑pass now detects removed but still imported exports as contract breaks. Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Medium |
bootstrap_repo(force=True) refuses to downgrade/destroy profiles written by newer chameleon engine. bootstrap_repo(force=True) refuses to downgrade/destroy profiles written by newer chameleon engine. Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Medium |
`.chameleon/conventions.md` added to merge‑driver routing and tested in gitattributes checks. `.chameleon/conventions.md` added to merge‑driver routing and tested in gitattributes checks. Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Medium |
Method, class, and constant naming conventions now surface in all convention delivery channels. Method, class, and constant naming conventions now surface in all convention delivery channels. Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Medium |
refresh_repo forces re‑derive of corrupted or stale artifacts (profile.summary.md, profile.json schema version, reverse_index.json, exports_index.json). refresh_repo forces re‑derive of corrupted or stale artifacts (profile.summary.md, profile.json schema version, reverse_index.json, exports_index.json). Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Medium |
detect_repo and get_pattern_context consistently report profile_corrupted when profile.json is missing but core artifacts exist. detect_repo and get_pattern_context consistently report profile_corrupted when profile.json is missing but core artifacts exist. Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Medium |
detect_repo and get_pattern_context reject non‑absolute file_path values with a validation error. detect_repo and get_pattern_context reject non‑absolute file_path values with a validation error. Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Medium |
preflight-and-advise guards against non‑string session_id to avoid crash. preflight-and-advise guards against non‑string session_id to avoid crash. Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Medium |
The idiom‑review off‑switch no longer silences the independent “no passing test run” reminder. The idiom‑review off‑switch no longer silences the independent “no passing test run” reminder. Source: llm_adapter@2026-07-13 Confidence: high |
— |
| Bugfix | Low |
multi_lens_review now includes route reason in both "ran" and "skipped" events for auditability. multi_lens_review now includes route reason in both "ran" and "skipped" events for auditability. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
detect_repo correctly walks up to top-level config to report monorepo workspace's production-ref lock after init. detect_repo correctly walks up to top-level config to report monorepo workspace's production-ref lock after init. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
Idiom teaching with source= no longer renders corrupted gist due to improved metadata-line regex. Idiom teaching with source= no longer renders corrupted gist due to improved metadata-line regex. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
lint_file's node-kind-mismatch violation now caps unbounded repr() output like sibling violations. lint_file's node-kind-mismatch violation now caps unbounded repr() output like sibling violations. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
python -m chameleon_mcp.daemon without start subcommand now writes a pidfile for proper daemon status reporting. python -m chameleon_mcp.daemon without start subcommand now writes a pidfile for proper daemon status reporting. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
Intent capture regex broadened to match slash-delimited paths and single-digit numerals as constants. Intent capture regex broadened to match slash-delimited paths and single-digit numerals as constants. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
Python async/await signals are now surfaced in search_codebase and get_pattern_context outputs. Python async/await signals are now surfaced in search_codebase and get_pattern_context outputs. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
search_codebase correctly labels stale calls and symbol indexes as "stale" rather than mislabeling them as corrupt. search_codebase correctly labels stale calls and symbol indexes as "stale" rather than mislabeling them as corrupt. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
_profile_needs_rederive now validates constant_index.json schema_version alongside other index files. _profile_needs_rederive now validates constant_index.json schema_version alongside other index files. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
Orphaned merge-driver temporary file sweep now runs on both full bootstrap and partial refresh paths. Orphaned merge-driver temporary file sweep now runs on both full bootstrap and partial refresh paths. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
/chameleon-doctor's recent-hook-errors check no longer misattributes benign banners as errors, preserving real timestamps. /chameleon-doctor's recent-hook-errors check no longer misattributes benign banners as errors, preserving real timestamps. Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
| Bugfix | Low |
using-chameleon/SKILL.md corrected documentation: idiom_judge default is on (matches code). using-chameleon/SKILL.md corrected documentation: idiom_judge default is on (matches code). Source: granite4.1:30b@2026-07-14-audit Confidence: low |
— |
Full changelog
Whole-plugin from-scratch real-invocation QA campaign: 36 parallel testers
exercised every hook, skill, and MCP tool against the real profiled repos
across TypeScript/Ruby/Python and every supported framework, weighted toward
the freshest v3.1.0/v3.1.1 memory-channel code. 26 findings confirmed (each
independently adversarially re-verified) and fixed. The fix wave itself went
through two further verification passes before shipping: a per-fix adversarial
re-check (which caught and repaired a fix-introduced test regression, see
"Fixed" below) and a second independent review of the cumulative diff (which
caught a fix-introduced false-positive bug in the PR-review auto-pass fix
itself, plus two smaller parity gaps — all repaired, see "Fixed").
Fixed
- Daemon proxy silently defeated
CHAMELEON_TRUST_REVALIDATE=1(P1). The
long-lived chameleon-mcp daemon's environment is frozen at spawn time, so
preflight-and-adviseproxyingget_pattern_contextto it never observed a
per-call revalidate override — a profile that genuinely diverged from its
trust grant kept reading astrustedinstead ofstalewhenever a daemon
spawned without the flag was already running, the default steady-state
condition.CHAMELEON_TRUST_REVALIDATE=1now bypasses the daemon proxy and
runs the check in-process.hook_helper.py. - PR-review auto-pass missed a removed-but-still-imported export (P1).
get_autopass_verdict's blast-radius fact only counted a file's CURRENT
importers, so deleting an export five other files still imported could
scoreauto_pass_eligible=true/risk=lowwith no mention of the break —
the exact defect class the safety net exists to catch. It now folds
query_symbol_importers's "broken" entries into the verdict as a real
contract break, scoped to names that were actually exported at the diff's
ownold_ref(an independent review of this same fix caught that the first
version compared only against the CURRENT export set with no notion of
old_ref, so a file touched for an unrelated reason with a pre-existing
dangling import — present at bothold_refandHEAD— would have been
misattributed to the diff under review; both directions are now covered by
a real two-scenario regression test).tools.py. bootstrap_repo(force=True)had no too-new-schema guard. It would
silently downgrade/destroy a profile written by a newer chameleon engine —
the exact caserefresh_repoalready refuses even underforce. Bootstrap
now applies the same refusal.tools.py..chameleon/conventions.mdwas missing from the merge-driver routing.
Absent from.gitattributes-template, a real two-branch merge with
divergent taught idioms left raw git conflict markers embedded in the
mirror instead of the driver ever running. Routed alongside
COMMITTED/principles.md/profile.summary.md(decline-cleanly,
refresh-repairs), and added totest_gitattributes_template.py's tested
sets.- Method/class/constant naming conventions never reached the model.
method_casing/class_casing/constant_casingwere derived and stored in
conventions.jsonbut rendered into none of the three convention-delivery
channels (SessionStart, the conventions.md mirror, the Tier-1 PreToolUse
echo) — a model could be flagged for violating a naming rule it was never
shown. All three now surface it, mirroring how file-naming already does.
conventions.py. refresh_repounder-repaired corrupted/stale artifacts. A corrupted
(non-empty garbage)profile.summary.mdpassed the repair guard's
emptiness-only check and stayed corrupt indefinitely; an old-but-readable
profile.jsonschema_version noop'd instead of re-deriving; a stale
reverse_index.json/exports_index.jsonschema_version was never
validated. All three now force a re-derive like their sibling artifacts do.
tools.py.detect_repo/get_pattern_contextmisreported a torn-down profile.
Whenprofile.jsonwas missing but core artifacts remained, both reported
a cleanno_profileinstead ofprofile_corrupted— inconsistent with
get_statuson the identical directory, contradicting the code's own
stated invariant. Both now call the same corruption check regardless of
whetherprofile.jsonitself exists.tools.py.detect_repo/get_pattern_contextsilently resolved a relative
file_pathagainst the MCP server's own CWD, contrary to their
documented absolute-path contract (the siblingget_archetypealready
guards against this exact failure mode). Both now reject a non-absolute
path with a validation-error envelope instead of disclosing whatever repo
happens to sit at the resolved location.tools.py.preflight-and-advisecrashed on a non-stringsession_id. The one
call site (of ~11 in the file) without anisinstance(str)guard let a
malformed payload reachstr.encode()and raise an unhandled
AttributeErrorpast the hook's own try/except. Guarded to match every
other call site.hook_helper.py.- The idiom-review off-switch silenced an unrelated reminder.
enforcement.idiom_review: falsealso killed the independent "no passing
test run this turn" reminder, because both were computed inside the same
gate function. The reminder now fires independently of the idiom-review
switch.hook_helper.py. multi_lens_review's "ran" check event dropped its route reason, unlike
the "skipped" branch — no way to audit after the fact whether a turn's
judge spawn was intent-forced. The reason now rides in both.hook_helper.py.detect_repomisreported a monorepo workspace's production-ref lock
immediately after init, reading only the workspace's own (nonexistent)
config instead of walking up to the toplevel's lock the wayrefresh_repo
already does.tools.py.- An idiom taught with
source=rendered a corrupted gist — the
citation text leaked into the directive because_summarize_idiom_block's
metadata-line regex didn't recognizeSource:, unlike the sibling parser
inidiom_coverage.py.tools.py. lint_file's node-kind-mismatch violation embedded an unbounded
repr()of every top-level node kind, with no cap unlike sibling
violation classes in the same module.lint_engine.py.- A bare
python -m chameleon_mcp.daemon(nostartsubcommand) never
wrote a pidfile, sodaemon_status()/stop_daemon()reported a live,
request-serving daemon as not-running.daemon.py. - Intent capture missed realistic checkable constants — the identifier
regex never matched slash-delimited paths, and the numeral regex required
2+ digits. Broadened both.intent_capture.py. - Python's async/await signal was computed but never surfaced in
search_codebase/get_pattern_context— an async FastAPI endpoint
rendered indistinguishably from a sync one.symbol_signatures.py. search_codebasemislabeled a stale calls index as(corrupt)
instead of the sharedcalls-index-stalereason sibling tools already use.
A review pass on this fix found the identical(corrupt)mislabel three
lines above for a stale symbol index, missed in the same edit — fixed too,
now distinguishingsymbol-index-stalefrom genuine corruption.tools.py._profile_needs_rederivevalidatedconstant_index.json(Ruby's
cross-file existence index) for JSON-parseability only, not schema_version,
unlike the exports/reverse index check right above it — currently latent
(the format has only ever shipped schema_version 1) but would have silently
survived every refresh once a newer schema ships. Now validated the same way
its siblings are; found and fixed during the same review pass as the two
items above.tools.py.- The orphaned merge-driver tmp-file sweep only ran on full bootstrap,
not the partial-refresh path/chameleon-refreshtakes for small diffs.
tools.py. /chameleon-doctor's recent-hook-errors check could misattribute a
benign banner as the error, dropping the real timestamped line that
pulled it into the surfaced tail.tools.py.using-chameleon/SKILL.mdmisdocumentedidiom_judge's default as
"opt-in, default off"; the code default is on, matching every other doc
that states it.
Full unit suite green (5545 passed, 3 skipped), ruff clean.
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
About Chameleon
All releases →Beta — feedback welcome: [email protected]