feat(metrics): count a plain re-assignment in python/embedded_python/ruby state_mutation (#2817) - #2964
Merged
Merged
Conversation
…ruby state_mutation The state_mutation rule (feeds risk_state_flux) counted only self.x=/@ivar=, :=, global/nonlocal, container mutators and (ruby) bang methods for these three languages -- never a plain `x = v`. That is narrower than the #2765 contract's corollary 1 (where a language has no declaration syntax, the assignment statement is the write), so `count = count + 1` scored 1 in lua/php/shell/go and 0 in python -- the cross-language inequality #2812 exists to remove. Add one house-style assignment arm (mirroring lua/js) to each rule, plus re.M (inert for the existing arms, which use no ^/$). The arm is anchored on the black/PEP8 convention that a statement assignment writes with a space before `=` (`x = 1`) while a keyword argument does not (`x=1`): (?:^|;)[ \t]*<lvalue>(?:\.attr|[idx])*[ \t]+=(?![=])(?!...,$) so `x = v`, `obj.attr = v` and `d[k] = v` count, while `foo(x=1)`, `def f(x=1)`, `x == 1` and annotated `x: int = 1` (declaration-with-initializer) do not. ruby uses a lowercase-initial lvalue (so `CONST = 1` stays freeze_hits) and drops `=~`/`=>`. Compound `+=` and unspaced `x=1` are deliberately out of scope. Tests: extend the cross-language state_mutation contract (CASES + exact-count COUNTS incl. multi-line-call cases), add an embedded_python entry, and flip ruby's `x = 1` from a negative to a positive (it enshrined the narrow behavior); refresh the three per-language strict rows. docs/state_mutation_rule_contract.md: move python/ruby/embedded_python from "deferred" to "agrees" and rewrite the narrowness note. Corpus reprice (raw findall @ language-crucible v1.2.0): python 1490->11647, embedded_python 191->894, ruby 64->140; kwargs/multi-line-call false-positive rate ~0.02%. Golden-master rebless owed (scoring-layer change). Closes #2817 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rUcYDAzYYCgrLdHyKBT9G
The #2817 plain-assignment arm raises the state_mutation raw count for python/embedded_python/ruby (corpus: python 1490->11647, embedded_python 191->894, ruby 64->140), which reprices risk_state_flux population-wide. Both golden masters regenerated per-leg in isolated venvs (full-precision: all deps; zero-dep: PyYAML only) against language-crucible @ v1.2.0. bless_scope.py (both legs): ~4133 diffs = 2656 corpus-wide topological (X/Y/Z) re-solve + ~1478 substantive, all attributable to the reprice: "Variable Reassignments"/"State Flux Exposure"/"Amplified Cascading Flux" directly, and normalized exposures (Error/Cognitive/Concurrency), Structural Magnitude and directory-group aggregates that are relative to a file's total magnitude. Every raw "Variable Reassignments" count change is on a .py/.rb file (incl. python files nested in mixed-language project dirs like cpp/NVDA); no language whose rule was not changed has its own raw count move, and NO files were newly parsed or excluded. The scoring layer absorbs the raw increase gracefully (e.g. braille.py reassignments 617->1801 but State Flux Exposure only 55.3->58.3). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rUcYDAzYYCgrLdHyKBT9G
Contributor
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
state_mutation(feedsrisk_state_flux) counted onlyself.x =/@ivar =,:=,global/nonlocal, container mutators and (ruby) bang methods for python/embedded_python/ruby — never a plainx = v. That is narrower than the #2765 contract's corollary 1 (a language with no declaration syntax counts the assignment statement as the write), socount = count + 1scored 1 in lua/php/shell/go and 0 in python — the cross-language inequality #2812 removes. The contract doc recorded these three as deferred.Fix: one house-style assignment arm (mirroring
lua/javascript) added to each rule, plusre.M(inert for the existing arms). Anchored on the black/PEP8 convention that a statement assignment writes with a space before=(x = 1) while a keyword argument does not (x=1):x = v,obj.attr = v,d[k] = v.foo(x=1),def f(x=1)(no space before=, not statement-start),x == 1, and annotatedx: int = 1(declaration-with-initializer).CONST = 1staysfreeze_hits) and drops=~/=>.x += 1and unspacedx=1.Crucible incidence table (language-crucible @ v1.2.0)
.rstdoc file)The space-before-
=anchor + the trailing-comma guard reduce kwargs/multi-line-call false positives to ~0.02%. Sampled matches are otherwise all genuine writes.Golden rebless (this PR)
Both masters regenerated per-leg in isolated venvs (full-precision / zero-dep).
bless_scope.pyon both legs: ~4133 diffs = 2656 corpus-wide topological (X/Y/Z) re-solve + ~1478 substantive, all attributable to the reprice —Variable Reassignments/State Flux Exposure/Amplified Cascading Fluxdirectly, plus normalized exposures / Structural Magnitude / directory-group aggregates that are relative to a file's total magnitude. Every raw count change is on a.py/.rbfile (incl. python files nested in mixed-language projects likecpp/NVDA); no unchanged-rule language moves its own raw count, and no files were newly parsed or excluded. The scoring layer absorbs the raw increase gracefully (e.g.braille.pyreassignments 617→1801 but State Flux Exposure only 55.3→58.3).Verification
tests/extraction/+tests/core_engine/: 8337 passed, 0 failed.tests/signal_contract_audit.py --ci: no new findings (contract staysstated; only counts move).tests/ruff_audit.py --ci(pinned ruff 0.16.0): no new lint findings; the 3 engine files are format-clean.Docs
docs/state_mutation_rule_contract.md: python/ruby/embedded_python rows moved deferred → agrees withbefore → aftercounts; the "what the contract cannot do with a regex" note rewritten to "landed in #2817".Label:
rosetta:rebless-owed— the keyword-rosetta corpus re-bless PR opens against enginemainafter merge.Closes #2817
🤖 Generated with Claude Code