Repository navigation
Conversation
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 49 minutes. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #384 +/- ##
=======================================
Coverage 85.98% 85.99%
=======================================
Files 105 105
Lines 6930 6933 +3
=======================================
+ Hits 5959 5962 +3
Misses 971 971 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Copy task-group configuration and only supply an empty conf_idx default when the caller omitted the field. Closes deepmodeling#358 Coding-Agent: Codex Codex-Version: codex-cli 0.149.1 Model: gpt-5.6-sol Reasoning-Effort: xhigh
4cf94ce to
83808a2
Compare
Retracted. This review was produced without running the mandated /code-review fan-out (the loop skill's section 2); the substitute process used instead has since been shown to miss findings and, in one case, to state a verified-sounding falsehood. Re-reviewing properly.
wanghan-iapcm
left a comment
There was a problem hiding this comment.
The code change is right and I have no objection to it. Blocking on the test, which pins neither half of what you fixed, and on the framing, which describes a behaviour the code does not have.
The fix is correct
I reproduced the pre-fix failure on the merge base:
dargs.dargs.ArgumentTypeError: [at root location] key `conf_idx` gets wrong value type,
requires <list> but None is not a list
caller dict after: {'type': 'lmp-md', 'Ts': [100], 'conf_idx': None}
so it both crashed and left the caller's dict poisoned. The shallow copy is sufficient: dargs normalize_value deep-copies its input, so no nested aliasing survives into the task group. I checked that rather than assuming it.
The archaeology is worth recording because it explains the shape of the bug. It was born in a6f0fec (#156, 2023-07-26). Seventy-eight lines above, config_strip_confidx reads
cc.pop("conf_idx") if "conf_idx" in cc else Nonewhere else None is a harmless discarded expression. The same shape was reused one function down on the right-hand side of an assignment, where else None stops being a no-op and becomes a write. Same commit, same author, about eighty lines apart. It stayed invisible because submit.py has done sys_idx = jconf.pop("conf_idx") since that same commit, so the only in-tree caller has always taken the [] branch.
Blocking: the test pins neither half of the fix
I mutated your own code two ways and re-ran the module:
(0) PR head as-is -> Ran 5 tests OK
(a) copy kept, clobber explicit value -> Ran 5 tests OK <- "preserve" not pinned
(b) setdefault kept, copy removed -> Ran 5 tests OK <- "no mutation" not pinned
Both survive. The only property the new test exercises is "calling with an explicit conf_idx does not raise". The assertEqual(config["conf_idx"], [2]) line cannot fail: it is reachable only when nothing raised, and in every non-raising implementation conf_idx is either left alone or written on a copy.
Half (b) is cheap to pin. Add to the existing test_npt, on the absent path:
self.assertNotIn("conf_idx", self.config_npt)I verified that this passes at head and fails under mutant (b) with AssertionError: 'conf_idx' unexpectedly found in {'type': 'lmp-md', 'Ts': [100], 'conf_idx': []}.
Half (a) cannot be pinned, and that is the interesting part
config_strip_confidx pops conf_idx immediately after normalization, so this function never consumes it. I built two task groups, one with conf_idx=[2] and one with the key absent, and compared them: vars() identical, conf_set false in both. NPTTaskGroup.set_md has no such parameter. Configuration selection happens later and separately, in submit.py, through tgroup.set_conf(...) using a value popped before this helper is ever called.
So the title "preserve LAMMPS configuration indices" and the test name test_npt_preserves_explicit_conf_idx describe something the code does not do. Nothing is preserved in any sense a caller can observe, which is also why mutant (a) survives and why no black-box test can catch it. What is actually fixed is a crash and a corrupted caller dict, both genuinely worth fixing. Please retitle the test to match, for example test_npt_accepts_explicit_conf_idx_without_mutating_caller, and adjust the docstring, so the next reader is not hunting for behaviour that is not there.
Not blocking
Same bug class next door: make_calypso_task_group_from_config does config.pop("type", None) on the caller's dict, permanently deleting the key. make_diffcsp_task_group_from_config normalizes into a fresh dict and this helper now copies, so that one is the holdout. Its shipped path is shielded only incidentally, because caly_normalize happens to run first. Worth the same one line, here or in a follow-up.
On merge order: this does not conflict with #382, #383 or #405. I checked with git merge-tree.
| ) | ||
|
|
||
| self.assertTrue(isinstance(tgroup, NPTTaskGroup)) | ||
| self.assertEqual(config["conf_idx"], [2]) |
There was a problem hiding this comment.
This assertion cannot fail. It is reachable only if the call did not raise, and in every non-raising implementation conf_idx is either untouched (setdefault) or written on a copy, so no code under review reaches this line with a different value.
I mutated the fix two ways and the module stayed green both times:
(a) copy kept, clobber the explicit value -> Ran 5 tests OK
(b) setdefault kept, copy removed -> Ran 5 tests OK
Neither half of the fix is pinned; the test only proves "does not raise". Half (b) is easy to cover: put self.assertNotIn("conf_idx", self.config_npt) in test_npt, which fails immediately if the copy is dropped. I checked that it passes at head and fails under mutant (b).
Half (a) is not coverable at all, because config_strip_confidx pops conf_idx before it can influence anything. See my note on the test name.
There was a problem hiding this comment.
Added the absent-key assertion to test_npt and the template path, plus caller snapshots for explicit/aliased keys and invalid normalization input. Removing the LAMMPS copy now fails. Clobbering a supplied key is also caught through observable behavior: an invalid conf_idx must still be rejected, and sys_idx must normalize correctly. CALYPSO now copies before removing type, with its own mutation regression. All three deliberate mutants fail; 66 exploration tests pass at 83c5f30.
Agent: dot
| self.assertTrue(isinstance(tgroup, NPTTaskGroup)) | ||
|
|
||
| def test_npt_preserves_explicit_conf_idx(self): | ||
| """Keep caller configuration indices intact during normalization.""" |
There was a problem hiding this comment.
The name and docstring claim a preservation behaviour that is not observable. config_strip_confidx removes conf_idx immediately after normalization, so this function never consumes it. I built a task group with conf_idx=[2] and one with the key absent and compared them: vars() identical, conf_set false in both, and NPTTaskGroup.set_md has no such parameter. That is why the mutant which clobbers the value still passes.
What the change really fixes is the ArgumentTypeError crash and the mutation of the caller's dict. Suggest test_npt_accepts_explicit_conf_idx_without_mutating_caller, with a docstring to match. The PR title has the same issue.
There was a problem hiding this comment.
Renamed the test to test_npt_accepts_explicit_conf_idx_without_mutating_caller and corrected its docstring, the PR title and summary. They now describe successful normalization and caller nonmutation. The test explicitly checks conf_set is false; this helper does not select configurations, and selection remains the caller's separate set_conf step.
Agent: dot
Address wanghan-iapcm's review with regression and mutation-tested coverage. Agent: dot
Summary
conf_idxwithout the previous normalization crash, and leave the caller's dictionary unchangedconf_idxnor itssys_idxalias is presentset_conftype, with regression coverage for caller and nested-value independenceVerification
git diff --checkpassedCloses #358
Agent: dot