feat(contracts): state_mutation gets a stated contract — a statement that writes to existing state (#2765, Phase 3) - #2818
Merged
Conversation
… that writes to existing state (#2765, roadmap Phase 3) One hit is a statement that writes a new value into state that already exists: a re-assignment (plain, compound or ++), an in-place container/structure update, or a write through a mutable cell. Four corollaries, each found live in the 46-language audit: a declaration is not a write (even `let mut`/`var`/`int x = 5`/ go `:=`; languages with no declaration syntax count every assignment); a type or modifier naming mutable state is not a write (IORef in a signature, AtomicInteger, volatile, mutable); a read/bind/cast is not a write (`this.` rvalues, haskell `<-`, perl bare `shift`, cpp `&`, std::move, payable()); one statement is one hit and a token another rule owns is not a second signal (dockerfile ENV -> globals; matlab clear, m4 popdef, apex .clear( -> cleanup; UPDATE...SET once). 30 rules rewritten on a shared statement-start + bare-lvalue anchor with a trailing-comma guard. Real-world corpus incidence: c 10644 -> 6300, cpp 11623 -> 4005, rust 2331 -> 636, typescript 9069 -> 5618, perl 5838 -> 3932, sqlite 35 -> 4, haskell 41 -> 1; dart 764 -> 2052 and abap 48 -> 402 widen because plain assignment had been invisible there. Corpus: 21 languages' state_mutation cells move, every one attributed in docs/state_mutation_rule_contract.md (label rosetta:rebless-owed; the keyword-rosetta re-bless branch carries the re-plants). Golden masters blessed from a clean language-crucible v1.2.0 worktree: 9,363 diffs per master = 4,323 topological + 5,040 in the state signal, its weighted view, and the formulas that read it (state_flux, cognitive_load, safety, file mass, the race-condition pair). One artifact newly parses: cobol RESPSTR.cpy lost ~500 phantom END-STRING hits and no longer trips the aperture's density guard. Also: tests/tools/rule_probe.py (rule incidence + samples + before/after audit rows, the harness every rule session had been rewriting), tests/tools/bless_scope.py (the uncapped golden diff bucketed by section/language/key, plus newly parsed/excluded artifacts), a single cross-language contract test module, and the rule-contract-audit skill rewritten as a command recipe. Deferred with an issue: python/embedded_python/ruby never count a plain re-assignment (#2817). Sheet row state_mutation: draft -> stated (3 of 68). Closes #2765 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Open
6 tasks
Contributor
Owner
Author
|
Cross-repo: the corpus re-bless is squid-protocol/keyword-rosetta#79 (branch |
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.
Phase 3 of #2812, first family.
docs/state_mutation_rule_contract.mdis the contract, the corollaries, the fallback family and the 46-language audit;gitgalaxy/standards/signal_contracts.pyrowstate_mutationgoesdraft -> stated(3 of 68).The contract
The issue's two candidate sentences were a real choice. The rejected one ("the introduction or use of mutable state") is what rust/kotlin/swift/scala/zig and js/ts implemented and it makes the signal a style measure; every consumer (
_calc_state_flux, cognitive load, safety, the cascading-flux pair, thecascading_state_mutationbottleneck) reads the count as behaviour, so the count is behaviour.Corollaries, each found live: (1) a declaration is not a write, even
let mut/var/int x = 5/go:=-- and where a language has no declaration syntax the assignment statement is the write; (2) a type or modifier naming mutable state is not a write (IORef Int,AtomicInteger x;,volatile,mutable); (3) a read, bind or cast is not a write (this.rvalues -- 376 hits ofthis.error(in one TS file -- haskell<-, perl bareshift, cpp&,std::move,payable()); (4) one statement is one hit, and a token another rule owns is not a second signal (dockerfileENV-> globals; matlabclear, m4popdef, apex.clear(-> cleanup;UPDATE t SETonce;s = append(s, x)once).What changed
let/varin front breaks the match) with a trailing-comma guard for enum members / named arguments,++/--touching an operand, and receiver-anchored container mutators. Per-language reasoning is in each rule's# #2765 contract:comment and the doc's audit table.x=1; abap's rule had no=at all).state_mutationcells move (rosetta_audit.py: 21 regressions, all attributed). Rule-side: haskell a.hs 2->0, dockerfile a 2->0, c a 2->0 / b 3->2, go b 5->2, objective-c 3->2, perl 3->2 & c 1->0, m4 c 2->0, apex c 1->0, matlab c 1->0. Plant-side (authored to the old rules, re-planted as real writes in the corpus PR): cpp, java, javascript, kotlin, rust, scala, swift, typescript, zig, solidity, sqlite, abap; livecode/scheme/tcl carried a third write in the decoy line. The re-blessed corpus verifies 46/46 against this branch.language-cruciblev1.2.0 worktree (a second bless from the dirty sibling checkout matched byte for byte).tests/tools/bless_scope.pyon the diff: 9,363 per master = 4,323 topological + 5,040 substantive, whose leaf keys are exactly the state signal, its weighted view,Amplified Cascading Flux, and the formulas that read it (State Flux / Cognitive Load / Error & Exception exposure, Structural Magnitude, the race-condition pair). One artifact newly parses:cobol/.../RESPSTR.cpylost ~500 phantomEND-STRINGhits and no longer trips the aperture's "Packed Payload Guard".tests/extraction/languages/test_state_mutation_contract_2765.py(positives/negatives per language, one-statement-one-hit counts, ReDoS detonation for every rewritten regex). Full suite 7,895 passed; ruff/mypy/dead-key audits clean;signal_contract_audit.py --ciexits 0 with the baseline shrunk by one.Tooling (the process ask)
Every rule session so far rebuilt the same two scripts; they are now standing tools:
tests/tools/rule_probe.py(a rule's incidence and matched lines on both corpora,--jsonsnapshots,--compareemits the audit-table rows) andtests/tools/bless_scope.py(the uncapped golden diff bucketed by section / language / leaf key, plus artifacts that moved between parsed and excluded). Therule-contract-auditskill is rewritten as a command recipe with the parallel legs and the worktree/env pitfalls this session hit.Deferred, with an issue
python, embedded_python and ruby never count a plain local re-assignment (
x = v): narrower than the contract by construction, not red on the corpus, and a population-wide reprice ofrisk_state_fluxfor the most-scanned language -- filed as #2817 rather than folded in here.Cross-repo
Engine merges first. keyword-rosetta branch
rebless/gitgalaxy-2765-state-mutation(PR to follow) carries the re-plants, 20 manifest cells, the notes, a new ledger entrystate-mutation-contract-2765and the retirements inbatch4-dual-keyword-overlaps; itsverify.ymlgoes green once main carries this PR.bias-history.ymlregenerates the chart on merge.Closes #2765
🤖 Generated with Claude Code