fix(core-engine): matlab's return channel is not a state mutation (#2654) - #2703
Merged
Conversation
) MATLAB has no `return <value>` statement. A function result IS an assignment to a variable named in the `function [out] = f(...)` signature, so `out = env;` is the exact statement c/go/java write as `return env;`. state_mutation's rule counts every assignment, which made matlab the one language in the registry that pays for returning: on the keyword-rosetta corpus 15 of 19 raw hits were the return convention, and with #2546's per-function x3 flux weighting that is 25 of the cell's 25 -- against a corpus median of 2, the widest deviation in the whole bias table. Excluding every write to an output variable would be wrong the other way. runica.m uses `weights` as the accumulator for a whole ICA loop and assigns it repeatedly; that is genuine working state. The discriminator is not anything on the assignment's own line but whether the enclosing function ever READS the name back: a name whose every occurrence in the body is a bare left-hand side is purely the return channel, while a read, a self-reference (`out = out + i`) or a structured write (`out(i) = x`) makes it ordinary state and keeps all its hits. Implemented as a `matlab_return_channel` entry in #2674's registry-declared `_scope_filters`, so the registry stays data and an unknown filter name can only restore the pre-filter count, never zero the metric. Measured over Prism code streams, which is what coding_analysis actually sees: * keyword-rosetta: 19 hits -> 4, i.e. the cell moves 25 -> 4 (median 2, the same value haskell/m4/perl/dockerfile already sit at). All four files move and no other language does -- rosetta_audit reports 45/46 PASS with matlab the single regression, so this PR carries `rosetta:rebless-owed` and the corpus re-bless follows against engine main. * language-crucible eeglab: 1321 -> 1306 (1.1%). Every one of the 15 drops is a terminal binding (`com = ''`, `varargout = {...}`, `name = dirName;`, `h = uimenu(...)`, `this = class(TMP, 'eegobj')`); runica.m, the file that works its outputs hardest, is byte-identical at 440. Golden master re-blessed in both modes: 72 diffs each, 43 of them the benign corpus-wide topological re-solve and 29 substantive -- all inside matlab/eeglab apart from the two whole-corpus health averages those roll up into. Risk exposures fall slightly for real MATLAB (eeglab cognitive_load 62.99 -> 60.13), which is the intended direction. Suite 7533 green, audit_check clear (ruff/mypy/dead-key/ast), tree-sitter 30/30 and tri-comparison 3/3 OK. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
`rosetta:rebless-owed` is what turns an intentional corpus-visible change's regressions into warnings, but `rosetta-audit.yml` only listened for the default `pull_request` types, so the label could only ever be read by the run that OPENED the PR. `gh pr create --label` attaches labels after that payload is built, so #2703 -- the first PR to actually use the flow #2699 introduced -- read zero labels and went red on a regression its author had already declared, with no way to re-trigger short of an empty commit. Adds `labeled`/`unlabeled` to the trigger types and documents the gotcha in ROSETTA_AUDIT.md's decision list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Answers #2654, which was filed as a question: should MATLAB's mandatory
out = xreturn-convention assignments count asstate_mutation? The answer is no, and the discriminator is narrower than either option the issue sketched.Why it is a defect, not intended morphology
MATLAB has no
return <value>statement. A function result is an assignment to a name declared infunction [out] = f(...). The rosetta corpus makes this exact: c writesreturn env;, go writesreturn env, matlab writesout = env;— the same statement, and matlab is the only language in the registry charged for it.Re-derived against the current corpus (the issue's +450% was pre-Batch-A; the medians have moved since):
state_mutation19 raw hits, of which 15 are the return convention; #2546's per-function ×3 flux weighting turns those into the whole cell.
Why "exclude all writes to output variables" would be wrong
runica.musesweightsas the accumulator for an entire ICA loop and assigns it repeatedly. That is genuine working state. The discriminator is not on the assignment's line — it is whether the enclosing function ever reads the name back:out = env;, never mentioned again) → the return channel, droppedout = out + i,out(i) = x, passed as an argument → working state, every hit keptImplemented as a
matlab_return_channelentry in #2674's registry-declared_scope_filters, so the registry stays data and an unknown filter name can only restore the pre-filter count, never zero a metric.Measurements (Prism code streams, what
coding_analysisactually sees)keyword-rosetta — 19 → 4, so the cell moves 25 → 4, the value haskell/m4/perl/dockerfile already sit at:
main.ma.mb.mc.mrosetta_audit.py: 45/46 PASS, matlab the single regression — this is the intentional corpus-visible change therosetta:rebless-owedlabel is for. The corpus re-bless follows against engine main perdocs/self_scan/ROSETTA_AUDIT.md.language-crucible (eeglab) — 1321 → 1306 (1.1%). Every one of the 15 drops is a terminal binding:
com = '',varargout = { [] [] 0 {} [] },name = dirName;,h = uimenu(varargin{:});,this = class(TMP, 'eegobj'),command = sprintf(...).runica.m— the file that works its outputs hardest — is untouched at 440 → 440. Inparsepluginnamethe two outputs are judged independently: write-onlynamedrops, read-backverskeeps every hit.Golden master
Re-blessed in both modes. 72 diffs each: 43 are the benign corpus-wide topological re-solve, 29 substantive — all inside
matlab/eeglabapart from the two whole-corpus health averages they roll up into. Risk exposures fall slightly for real MATLAB (eeglabcognitive_load62.99 → 60.13,state_flux85.71 → 84.81), which is the intended direction: less phantom mutation means less phantom debt.Gauntlet
audit_check.pyall clear (ruff 70-finding baseline, mypy 2-error baseline, dead-key, ast-accuracy)tree_sitter_accuracy_audit --all --ci30/30 OKtri_comparison_chart --all --ci3/3 OKcrucible_check.pyPASS in both modes after the blesstest_matlab_strict.py, including the accumulator/indexed/multi-output cases, the unknown-filter-name fallback, and a linearity checkNote for Batch D
main.mloses itsstate_mutationentirely, and its notes call it "the cleanest demonstration in the corpus" of the ×3 per-function flux weighting. That demonstration should be re-planted with a genuine mutation inprobe_branchas part of the corpus re-bless — flagged there rather than fixed here.Closes #2654
🤖 Generated with Claude Code