Rectify: Commit Guard Regression Heuristic — Content-Movement Immunity#3895
Merged
Trecek merged 9 commits intoJun 8, 2026
Merged
Conversation
…unity (#3887) The _check_regression heuristic in _cmd_rpc_guards.py fired on file splits because aggregate net-line-count comparison cannot distinguish content movement from content deletion. Replace the single-signal threshold with multi-signal classification: new-file accounting (subtract lines of nearby untracked destinations from regression_lines), empty-reverted-files guard (no per-file reversion evidence → CLEAR), and a _RegressionVerdict enum for informational classification. commit_guard now passes file_status XY codes to _check_regression via a new file_status dict built alongside files_to_add. Recipes that call commit_guard with base_branch must route regression_detected to an escalation step; the new commit-guard-regression-route-missing semantic rule enforces this and was added to all four bundled recipes. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…recipe steps Replace on_success with default route entry inside on_result for all four commit_guard steps (implementation, implementation-groups, remediation x2). Fix test_commit_guard_allows_intentional_reduction to assert regression_detected (correct behavior for bulk reduction without content redistribution). Update pyright suppression allowlist line number and recipe/rules file count. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pass VIRTUAL_ENV to subprocess env and derive it from sys.executable when not already set. This prevents fastmcp import failures when install-worktree rebuilds the venv before test execution under xdist. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The test_ci_dev_config::test_ruff_check_clean test calls `uv run ruff check` which triggers `uv sync`, replacing package files in the shared .venv while xdist workers run concurrently. When the import isolation subprocess starts during this window, fastmcp's package files are mid-swap, causing ImportError or PackageNotFoundError. Pin PYTHONPATH in the subprocess env to the parent's sys.path so module resolution uses the snapshot from process startup rather than the live (potentially mid-sync) venv filesystem. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Root cause: test_ci_dev_config::test_ruff_check_clean calls `uv run ruff check` which triggers `uv sync`, replacing .dist-info directories in the shared .venv while xdist workers run concurrently. When the import isolation subprocess starts during this window, fastmcp's __init__.py hits PackageNotFoundError or ModuleNotFoundError. Add _run_import_subprocess() wrapper that retries once after 1s on import-infrastructure errors (PackageNotFoundError, ModuleNotFoundError). The uv sync race window is typically < 1s, so the retry succeeds after the sync completes. Remove PYTHONPATH pinning (doesn't help since importlib.metadata resolves .dist-info from the same physical dir). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tely describe behavior The test name claimed the guard "allows" the reduction, but the assertion checks for regression_detected, indicating the guard does NOT allow it. Rename to test_commit_guard_detects_pure_reduction_as_regression to align the name with the assertion and docstring, which already correctly describe the detection behavior for a 50→20 line single-file reduction. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… enum members These members were never referenced in code expressions — the early-return paths use `return None` directly. Only POSSIBLE_REVERSION is used. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The function returns a verdict key but skill_contracts.yaml did not declare it, creating a contract validation gap. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enables Pyright to verify attribute access on the step parameter. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Trecek
force-pushed
the
commit-guard-regression-heuristic-is-fragile-false-positives/3887-2
branch
from
June 8, 2026 02:57
ac290c5 to
8294c3a
Compare
Trecek
deleted the
commit-guard-regression-heuristic-is-fragile-false-positives/3887-2
branch
June 8, 2026 03:08
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The
_check_regression()heuristic in_cmd_rpc_guards.pyuses aggregate net-line-count comparison (committed_net - wt_net > 10) to detect accidental reversion of implementation work. This false-positives on any file split, refactor, or dead-code removal because line-count deltas cannot distinguish content movement from content deletion. The architectural weakness is: a binary threshold over a single numeric proxy makes an irreversible decision (abort commit) with no corroborating evidence.The immunity approach replaces the single-signal threshold with a multi-signal classification that distinguishes content-movement from content-reversion, and gates the abort decision on corroborating evidence (git name-status metadata, new-file accounting, per-file balance analysis). The heuristic becomes structurally incapable of false-positiving on file splits because it explicitly detects and compensates for content movement between files.
Requirements
The heuristic either needs to be made substantially more robust or replaced with a mechanism that doesn't rely on line-count proxies. Options to evaluate:
Cross-file awareness: Before declaring regression, check if new/untracked files in the same directory contain the "missing" lines. If
regression_linesfrom file A can be accounted for bynew_linesin sibling files, it's a split, not a reversion.Content-based detection: Instead of counting lines, check if the working tree version has content overlap with the committed version. A reversion would show the working tree matching an older commit; a refactor would show novel organization of the same content.
Test-gated commit: If tests pass after the changes, the regression heuristic should yield. A true reversion of implementation work would likely cause test failures. The guard could be:
regression_lines > threshold AND tests_not_yet_passed.Semantic diffing: Compare the set of function/class definitions between committed and working tree. If the same symbols exist (just in different files), it's a reorganization.
Elimination: If the only scenario this guards against is "session accidentally checks out old file version," that can be detected more precisely by comparing the working tree against known old commits (
git diff --stat HEAD~Nmatching the dirty state exactly). If no old commit matches, it's not a reversion.The current threshold of 10 lines is also concerningly low for a heuristic with no escape valve — any non-trivial refactoring of a file that was modified in the implementation commits will trip it.
Implementation Plan
Plan file:
/home/talon/projects/autoskillit-runs/remediation-20260607-164912-642953/.autoskillit/temp/rectify/rectify_commit_guard_regression_heuristic_2026-06-07_170500.mdCloses #3887
🤖 Generated with Claude Code via AutoSkillit
Token Usage Summary
* Step used a non-Anthropic provider; caching behavior may differ.
Token Efficiency
Model Usage Breakdown