chameleon 2.54.0
A real-usage hardening round on the two review skills (/chameleon-pr-review,
/chameleon-receiving-code-review), driving every engine tool the skills depend
on against live-bootstrapped TypeScript, Ruby, and Python repos and cross-checking
each field/enum the skill reads against the tool's actual return. Five contract-drift
gaps (three of which silently no-oped a review pass) were corrected, and one
supply-chain-scanner evasion was closed at the engine.
Fixed
-
get_duplication_candidatesshape drift silently disabled the duplication
pass. pr-review Step 2.9b and receiving Step 3 told the model to read the
returned "candidates" and cite each candidate'ssymbol/path/excerpt. The
tool actually returns{found, file, matches}— the pairs are under
data.matches(there is NO top-levelcandidates), each match is
{function, candidates}, and a candidate's fields arename/file/body_excerpt
(neversymbol/path/excerpt). A model following the old wording read the
wrong keys, got nothing, and never raised a duplication finding. Both skills now
name the exact shape. (skills/chameleon-pr-review/SKILL.md,
skills/chameleon-receiving-code-review/SKILL.md) -
typecheckwas documented as a scalar but is a dict, mis-keying the auto-pass
routing. pr-review Step 3h wrote the state astypecheck: unavailableand
renderedTypecheck: N changed file(s) with type errors. The engine returns
typecheckas{status: "unavailable"|"clean"|"errors", ...}(unavailable adds
reason, errors addsfilesanddiagnostics). The skill now reads
typecheck.status/typecheck.reason/typecheck.diagnostics/typecheck.files
and the example output matches the render instruction. (skills/chameleon-pr-review/SKILL.md) -
scan_dependency_changesfinding fields were unnamed, inviting a wrong-key
read. Step 2.5 routed findings by their check type but never named the field;
a model assuminglint_file'srule/lineshape would read nothing. The finding
is{check, severity, path, evidence, message, detail}— the type ischeck
(notrule), the cited line isevidence(notline), and severity is the
literal"FIX"/"NIT". Also documents thatmanifests_changed/summaryare
absent on a degraded/failed scan anduncovered_manifestsappears only when
non-empty. (skills/chameleon-pr-review/SKILL.md) -
get_callersgrade set was stale. Step 2.9d listed the deterministic grades
as a closedsame_file/import/constant_receiverset, but the calls index now
also recordstyped_property(TypeScript dependency-injection edges, v2.49) and
module_attribute(Python module-attribute calls, v2.50). The skill now lists the
full set, treats it as open, and names the caller-site fields (caller, not
name). (skills/chameleon-pr-review/SKILL.md) -
Cross-file finding field names were left implicit. Step 2.9c
(get_crossfile_context) and Step 2.9e (get_contract_breaks) described the
citation semantically without naming the fields; the crossfile importer file:line
in particular lives underfinding.sites({path, line}), not a flat
file/line, and a contract break's symbol isnamewith
old_required_positional/new_required_positional. Both are now named exactly.
(skills/chameleon-pr-review/SKILL.md) -
A partially-packed dependency object evaded the supply-chain scanner without
tripping the minified-manifest guard.scan_dependency_changes's per-key
scanners are line-oriented, and theminified-manifestguard fired only when the
WHOLE manifest was a single{...}line. Apackage.jsondiff that packs a
dependency/scripts container onto one physical line —
"dependencies": { "evil": "git+ssh://…", "left-pad": "^1.0.0" }— while the file
stayed multi-line defeated the install-script/non-registry-source/new-dependency
checks AND slipped past the guard, reading as a silent clean add. The guard now
also flags such packed-container lines (detail.reasonpacked-container-line),
scoped to dependency/pin/scripts containers so a legitimately-inline
"repository": {...}/"engines": {...}never false-fires. The scope also covers
npmoverridesand yarnresolutions— they pin a TRANSITIVE dependency to an
arbitrary version or source, so a packed"overrides": { "lib": "git+ssh://evil" }
is the same non-registry-source evasion (the unpacked form was already caught
line-by-line; the packed form slipped both scanners). Verified with real packed
and one-per-line diffs across the false-positive and evasion cases.
(mcp/chameleon_mcp/dep_diff.py,skills/chameleon-pr-review/SKILL.md)