Repository navigation
Conversation
…e head commit's trailer and the merge base (#589) Muse Wonder Full read #634 after it merged (it was out of quota until 2026-11-09); its four majors are real, and each is fixed here with a test, a mutant and a Boundaries row in decision 0166: - A call in the mutant lists was data whatever it called, so an entry that read the world, as os.getenv('X', 'old'), escaped the check. Now a call is data only of a helper tools/mutants.py defines, or of a text's replace; a builtin's or another module's is code, as the record says. - A comparison's fallback mutant took the first operator the line showed, one in a string among them, and a test that read the text killed a mutant of nothing. Now the operator is found between the comparison's two sides. - Reading the head commit's trailer alone, and diffing from the merge base, were held by nothing: each fixture had one commit on its base. Two tests now give a trailer in an earlier commit, and main moving on after the branch left it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ode in the mutant lists; the comparison's guards are held (#589) The Claude review and the security pass of eb184e4: - An entry that read the world through an attribute or a subscript, as os.environ['X'] or sys.platform, or by replace on a path, was still data. Now _bound reads what each name the module binds is: a name an import binds is code, wherever an entry reads it, and replace is data only on a text (a constant, a name given one, or what an allowed call gives). Two mutants: "a replace on anything is data in the mutant lists" and "what is read from a module in the mutant lists is data". - The comparison's two guards were held by nothing: a comparison it cannot swap, as ==, and one on another line of the statement. The candidates test now feeds both, with a mutant for each. The two Boundaries rows this change added say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…em, and a name bound twice is code (#589) Argon's and Muse's reads of eb184e4. Their findings on replace were fixed in fae6b69; three more were real: - Helpers were every def in the module, so a name an import bound before the list and a def rebound after it, as getenv, was a helper. Now _bind reads the module's top in order: a list sees only what was bound before it, a name bound twice is code, and A, B = x, y binds each name to its own value, as tools/mutants.py does. The real lists read exactly as before: 15260 lines of data either way. - The SWAP table's > and >= were held by nothing; the candidates test swaps both. - The trailer test always asked for the checkout's own HEAD; it now asks for the earlier commit after the fix round too. Six mutants, and the three Boundaries rows this change added name them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… them to a text, a value or a helper (#589) The Claude review of fe00bf1: an import behind an if, a try or a with, a star import, and a name bound to what os gave, as ENV = os.environ, were all data, because a name nothing was known to bind was taken for data. Now that is turned round: a name is data only where a statement before the list bound it to a text, to a value _literal takes, or to a helper it defines; an import binds its first name wherever it stands among the statements, and anything else any statement binds, or binds again, is code. The real lists read exactly as before. Five mutants, each killed by the cases the review gave, and by cases that bind the name as a text first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a decorator and a dunder unsettle a name (#589) The Claude review of c0065ce: a name kept its first kind when something other than an assignment changed it. Now _unsettle makes code each name a walrus binds anywhere, a global or nonlocal names, or a method is called on (but a text, which none changes, and a function's own name); a call of globals, locals, vars, exec, eval, setattr or delattr makes every name code. A decorated def is code, a dunder attribute is code, and replace is data on a helper's return only where the helper says it gives a str. The real lists read exactly as before. Ten mutants, each killed by the review's cases or by the case that keeps a helper's own name, an annotated text and a text's method as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e after globals() (#589) The Claude review of 2424df1: _text's own check that the call is data was held by no test, so os.environ['X'].replace(...).replace(...) could pass; and a helper's call stayed data after a call of globals or eval, which may rebind it. Both are now held, each with a case and a mutant. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… a helper that fills a list early are code (#589) Argon's read of 2424df1. Its findings on a helper's call after globals() were fixed in 5626728, and the one on a chained assignment misread data_lines, which binds a listed statement's other names after it reads the list. Four more were real, and each is held now: a store through a subscript or an attribute, and a del, change what a name is; an unpacking with a starred item is no pairing; and a method a helper calls on a name not bound yet makes it code once bound, unless the method is one a text has, so a helper that reads a text defined after it leaves the text a text. The mutant once called "a helper defined after the mutant lists is theirs" is named for what it does. The real lists read exactly as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d a case holds it (#589) The mutant "a call of any method in the mutant lists is data" survived the run of every untested.py mutant at dd25df3: no case called a method other than replace on a text. TEXT.format(1) now does, and is code, as the narrowing says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
Codex Review Summary: ❌ FailedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|



Part of #589. This is the follow-on to #634, the advisory check of a changed line of Python no test notices. #634 merged before Muse could read it: Muse was out of quota until 2026-11-09. Muse Wonder Full read it after the merge, at 60316bb, and found four majors. All four are real, and each is fixed here.
Decision 0166 gains Boundaries rows only; its words are not changed. No protected file is touched, and no record is added.
Muse's four findings on #634, fixed
os.getenv('X', 'old'), escaped the checktest_a_call_in_the_mutant_lists_is_data_only_of_the_modules_own_helpers, 27 mutantstest_a_mutant_is_made_of_an_added_line_and_never_of_a_quiet_one, 5 mutants (<,>,>=, the guards)test_a_trailer_is_read_from_the_head_commit_alone, 2 mutantstest_the_change_is_read_from_the_merge_base_and_not_from_main_as_it_moved_on, 1 mutantWhat is data in the mutant lists, now
The check skips a hunk only when it is data: an entry of
ISSUEorMUTANTSthat decides nothing. The fix rounds found many routes by which an entry that reads the world passed for data. The rule is now stated in terms of what is allowed, not what is forbidden:global;del;globals,locals,vars,exec,eval,setattrordelattrmakes every name code.replaceon a text;-> str;data_linesoftools/mutants.pyis the same under main'suntested.pyand this one.Residual, stated, not fixed: a contrived evasion is left out. One example is a nested scope whose own name masks the module's. The check is advisory, and the record already says the head's own tests can forge its counts. The hunk that reads the world sits outside the lists and is still checked.
A deliberate narrowing: a text method other than
replace, such as.strip()or.format(...), is now code where main took it for data. No entry of the real lists changes.Checks
make verifyon an export of the head: 1716 tests OK, at2b47efa.tools/untested.py, run bytools.mutantson an export of the head: 83 of 83 killed at2b47efa. 35 of them are new.Reads
Argon, Muse Wonder Full, the Claude review and the security pass read the first head,
eb184e4. The Claude review read each fix round again:fe00bf1,c0065ceand2424df1. Argon read2424df1. The last two rounds,5626728/dd25df3and2b47efa, close what those reads found, and add a case for a mutant that survived; no reader read them again.eb184e4eb184e4eb184e4eb184e4fe00bf1c0065ce2424df12424df1tools/untested.py:200_literal(func.value, helpers)on.replacecalls has no negative test and no mutanttools/untested.py:200_literaltreatsos.replace(...)and any module'sreplacefunction as literal datatools/untested.py:162tools/untested.py:200tools/untested.py:200tools/untested.py:484tools/untested.py:521tools/untested.py:191tools/untested.py:498tools/untested.py:499tools/untested.py:200tools/untested.py:192tools/untested.py:210tools/untested.py:193tools/untested.py:207tools/untested.py:193tools/untested.py:193tools/untested.py:231tools/untested.py:253tests/test_untested.py:354tools/mutants.py:15389tools/mutants.py:15406tools/untested.py:167tools/untested.py:201tools/untested.py:214tools/untested.py:247tools/untested.py:273tools/untested.py:286tools/untested.py:224tools/untested.py:247tools/untested.py:273tools/untested.py:406🤖 Generated with Claude Code