Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Validator cache no longer freezes transient engine failures.** `rector-mcp`'s warm daemon intermittently trips rector's own `System error: "ClassReflection must be resolved for class X"` reflection bug on test classes — warm-process-state dependent, not file dependent (a clean re-run and plain `rector` CLI pass the same file). That failure was cached keyed on file content and replayed on every later run, including its frozen `duration_ms`; 2100 entries were poisoned this way across a test suite. Two-layer fix: (1) `validators/rector-mcp/rector-mcp.py` drops `System error:` results at the source — an engine glitch is not a code finding; (2) the validator cache now excludes non-deterministic engine failures (MCP transport errors, non-zero exits, `System error:` messages) from being written. Real findings (PHPStan types, `rector.refactor`) stay cached.
- **`git-merge` now fetches before merging a local branch — no more silent stale merges.** The docstring promised "fetch + merge" but there was no fetch: `git-merge master` merged the *local* `master` ref, which is stale the moment origin moves ahead. Real-world bite: a fix landed on origin/master, but merging `master` into a feature branch silently used the lagging local ref and the fix "wasn't there" — the failing job kept failing. Now `_fresh_merge_ref()` resolves the ref's upstream, fetches it, and if the local branch is behind, redirects the merge to the upstream (e.g. `origin/master`) with a loud note: `local master was N behind origin/master — merging origin/master (latest) instead`. Offline / fetch-fail / no-upstream cases warn and fall back to the local ref (no hard failure). Remote-tracking refs like `origin/master` are refreshed directly.

### Changed

- **`rector-mcp`'s `System error:` suppression is now defense-in-depth, not load-bearing.** The root cause behind the warm `ClassReflection must be resolved for class X` failures ([#273](https://github.com/Digital-Process-Tools/claude-supertool/issues/273)) is fixed upstream in `dpt/mcp-rector-warm` 0.4.0: the warm daemon reused one Rector container and never reset Rector's `DynamicSourceLocatorProvider`, which caches its source locator for every non-PHPUnit run — so the second file in a warm session was analysed with a locator that only knew the *first* file. The daemon now resets reflection state per call (matching `AbstractRectorTestCase`), so this branch should no longer fire. The adapter comment was updated to reflect that it remains only to absorb any future non-deterministic engine glitch. **Requires `dpt/mcp-rector-warm` ≥ 0.4.0** (`composer global update dpt/mcp-rector-warm`).

## [0.14.0] — 2026-05-23

### Added
Expand Down
13 changes: 8 additions & 5 deletions validators/rector-mcp/rector-mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,14 @@ def format_response(file_path: str, mcp_resp: dict, duration_ms: int) -> dict:
if errors:
for e in errors:
msg = e.get("message", str(e)) if isinstance(e, dict) else str(e)
# Rector's warm in-process engine intermittently fails to resolve a
# BetterReflection for the analyzed class and emits
# "System error: ... must be resolved". It's an engine/reflection
# failure, NOT a code finding — plain rector CLI runs the same file
# clean — so suppress it: don't fail, don't print, don't get cached.
# Defense-in-depth (root cause fixed upstream in mcp-rector-warm
# 0.4.0, claude-supertool#273): the warm daemon used to serve a stale
# reflection source-locator across files and emit
# "System error: ClassReflection must be resolved for class X" on a
# later file that a cold rector CLI handled clean. mcp-rector-warm now
# resets that state per call, so this branch should no longer fire —
# it stays only to keep any future non-deterministic engine glitch
# (NOT a code finding) from failing/printing/caching.
if msg.startswith("System error:"):
continue
base["ok"] = False
Expand Down
Loading