Skip to content

chameleon 3.0.0

Choose a tag to compare

@github-actions github-actions released this 11 Jul 10:44

Added (2026-07-11)

  • .chameleon/conventions.md — the CLAUDE.md-channel mirror. Bootstrap,
    refresh, and teach/unteach now maintain a rendered conventions file for the
    repo to wire into Claude's memory channel. Measured motive: the identical
    rules were followed 100% via this channel vs 40% as a hook advisory (see
    tests/effectiveness/results-published/migration-ab-2026-07-11.md).
    /chameleon-init offers three consent-gated wirings, none of which edit an
    existing file by default: a one-line .claude/rules/chameleon-conventions.md
    (auto-loads for the whole team), CLAUDE.local.md (personal), or a
    CLAUDE.md import on explicit preference. Kill switch
    CHAMELEON_CONVENTIONS_MD=0. A refresh repairs a missing mirror
    (_profile_needs_rederive), and any engine upgrade already forces the full
    re-derive that writes it — existing profiles gain the file on their first
    refresh after upgrading.
  • Multi-convention effectiveness campaign published (30 tasks x TS/Ruby/
    Python x 4 arms x 2 models, deterministic scorer, the repo's own
    cluster-bootstrap bar): chameleon 1.00 conformance on every task, every
    language, both models; bar MET vs no-plugin on both models; MET vs
    stale-CLAUDE.md on haiku; ceiling-tie vs perfectly-maintained CLAUDE.md.
    Instruments committed (tests/study_*.py); all results in
    tests/effectiveness/results-published/ (including the null dogfood
    retrospective and the unfavorable single-convention run, per policy).
  • Judge-panel calibration gate computed: kappa 1.000 on the 13-pair golden
    set (Fable-reference labels, provenance in
    tests/effectiveness/golden/LABELS_PROVENANCE.md — not human labels).

Changed (2026-07-11)

  • SessionStart injection reorders: the <chameleon-conventions> block now
    leads the context (before the skill text) and carries explicit
    anti-majority framing ("existing files may be mid-migration; never infer a
    convention from sibling-file majority against a rule here").
  • The // chameleon-ignore escape hatch is scoped to human-approved
    exceptions in both the import-preference deny reason and the
    using-chameleon skill: the model must not self-approve an override because
    existing files still use the blocked pattern.
  • pr-review gains a mechanical dependency demotion sweep before verdict
    rendering (a new-dependency's name alone can never be a BLOCK/FIX).

Fixed (2026-07-11)

  • Journey act 12b phase-41 checker read the raw stream-json transcript, so
    line-based assertions saw escaped \n — a structural false positive that
    failed the dependency-ACK check on every run. Both historical "failures"
    re-adjudicate as passes; live re-run green.

Breaking (v3)

  • MCP surface folded from 48 tools to 19. The 16 comprehension/conformance
    tools stay top-level (detect_repo, get_pattern_context, get_archetype,
    get_canonical_excerpt, get_rules, lint_file, search_codebase,
    describe_codebase, get_callers, get_callees, get_blast_radius,
    query_symbol_importers, get_crossfile_context, get_contract_breaks,
    get_duplication_candidates, explain_edit); the remaining 32 operator
    tools become actions on three dispatchers, called as
    <dispatcher>(action="<old tool name>", params={...original arguments, names and values unchanged...}):

    Old top-level tool New dispatcher / action
    bootstrap_repo chameleon_lifecycle(action="bootstrap_repo")
    refresh_repo chameleon_lifecycle(action="refresh_repo")
    trust_profile chameleon_lifecycle(action="trust_profile")
    list_profiles chameleon_lifecycle(action="list_profiles")
    merge_profiles chameleon_lifecycle(action="merge_profiles")
    teach_profile chameleon_lifecycle(action="teach_profile")
    teach_profile_structured chameleon_lifecycle(action="teach_profile_structured")
    teach_competing_import chameleon_lifecycle(action="teach_competing_import")
    unteach_competing_import chameleon_lifecycle(action="unteach_competing_import")
    propose_archetype_renames chameleon_lifecycle(action="propose_archetype_renames")
    apply_archetype_renames chameleon_lifecycle(action="apply_archetype_renames")
    disable_session chameleon_lifecycle(action="disable_session")
    pause_session chameleon_lifecycle(action="pause_session")
    get_autopass_verdict chameleon_review(action="get_autopass_verdict")
    refute_finding chameleon_review(action="refute_finding")
    record_review_verdict chameleon_review(action="record_review_verdict")
    record_finding_fate chameleon_review(action="record_finding_fate")
    get_review_history chameleon_review(action="get_review_history")
    scan_dependency_changes chameleon_review(action="scan_dependency_changes")
    dep_audit chameleon_review(action="dep_audit")
    get_status chameleon_telemetry(action="get_status")
    get_drift_status chameleon_telemetry(action="get_drift_status")
    get_drift_antipatterns chameleon_telemetry(action="get_drift_antipatterns")
    get_shadow_report chameleon_telemetry(action="get_shadow_report")
    get_override_audit chameleon_telemetry(action="get_override_audit")
    get_longitudinal_signals chameleon_telemetry(action="get_longitudinal_signals")
    get_finding_fate_stats chameleon_telemetry(action="get_finding_fate_stats")
    get_idiom_coverage chameleon_telemetry(action="get_idiom_coverage")
    check_idiom_candidates chameleon_telemetry(action="check_idiom_candidates")
    get_prose_rule_candidates chameleon_telemetry(action="get_prose_rule_candidates")
    daemon_status chameleon_telemetry(action="daemon_status")
    doctor chameleon_telemetry(action="doctor")

    Rationale: a context-lean tool surface — a session now loads 19 tool schemas
    instead of 48; the underlying Python functions keep their names and
    signatures, so direct imports (tests, QA batteries) are unaffected.

Changed

  • Repository restructured around an installable plugin/ dir. The
    marketplace source now points at ./plugin (plugin.json, .mcp.json, hooks/,
    skills/, agents/, bin/, mcp/, and the runtime scripts ts_dump.mjs,
    prism_dump.rb, libcst_dump.py, chameleon-merge-driver.sh, setup.sh), so a
    marketplace install copies only the runtime surface instead of the whole
    repo (previously ~4.9MB of tests/ and docs/ shipped with every install).
    tests/, docs/, and dev tooling (bump-version.sh, prune-plugin-cache.sh, ...)
    stay outside the installed plugin; the release tarball likewise now packs
    plugin/ + README/LICENSE/CHANGELOG only. No runtime behavior change —
    everything in-plugin resolves via CLAUDE_PLUGIN_ROOT as before.
  • Interpreter resolution is cached and the per-edit ladder is bounded. The
    resolved interpreter argv persists to a version-keyed cache (validated on
    read), and per-edit hooks cap the uv probe at 5s — bounded even where
    timeout(1) is absent (Git Bash, coreutils-less macOS), previously uncapped.
    Kill switch CHAMELEON_INTERP_CACHE=0.
  • pr-review skill split for progressive disclosure: a lean SKILL.md plus
    lazy references/*.md, and the fixed reviewer/scout roles are now packaged
    agents/ (chameleon:pattern-reviewer, code-scout, web-researcher).

Fixed

  • The daemon now starts under deep plugin-data paths. AF_UNIX caps
    sun_path at ~104 bytes, so a deep CHAMELEON_PLUGIN_DATA made every bind
    fail and the latency daemon silently never engaged (hooks fell back
    in-process forever). The socket moved to a short user-private
    <tmpdir>/chameleon-<uid>/d-<hash>.sock; pidfile and logs stay in the data
    dir.
  • Python test files no longer bucket into production role archetypes.
    python_role_for_path routed tests/api/routes/test_x.py to route, so the
    per-edit hook injected a production route canonical when editing a test; it now
    gates on the canonical test-path detector first.
  • Python linter config is read from sub-project dirs (a monorepo backend/ pyproject.toml), matching the TypeScript workspace-config fallback.
  • Skill-surface fixes: the refresh skill's re-lock call now passes the
    required path; receiving-code-review gained an argument-hint; the
    pr-review fan-out claim about reviewer tool grants is now an enforced in-agent
    directive rather than an unenforceable grant statement.