Skip to content

refactor: promote duck-typed capability probes to base-class interfaces - #5967

Merged
njzjz merged 22 commits into
deepmodeling:masterfrom
wanghan-iapcm:refactor-promote-capability-probes
Aug 12, 2026
Merged

refactor: promote duck-typed capability probes to base-class interfaces#5967
njzjz merged 22 commits into
deepmodeling:masterfrom
wanghan-iapcm:refactor-promote-capability-probes

Conversation

@wanghan-iapcm

@wanghan-iapcm wanghan-iapcm commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Promotes duck-typed capability probes (hasattr/getattr(obj, "x", default)) inventoried in #5897 to concrete-default methods/attributes declared once on the owning base class, so a typo'd or renamed name raises instead of silently degrading to the default. Eight change groups, one commit each (plus one fix-up commit):

  • Merge has_default_chg_spin into get_default_chg_spin (derive via is not None); drop the charge-spin hasattr probe family and declare concrete defaults on the owning bases.
  • Declare get_var_name / get_task_dim / get_intensive on make_base_model with concrete defaults; convert the jax2tf property probe and refresh a stale docstring.
  • Add a get_geo_compress() base accessor and drop consumer getattr/hasattr probes; pin both the override and default branches with a dedicated compression test.
  • Add a concrete reinit_exclude no-op default on make_base_fitting, killing the dp_atomic_model.py probe.
  • Add a get_pair_exclude_types() accessor on BaseAtomicModel and pin pair_excl as a direct-access contract (verified against every construction path, including deserialize and SpinModel.forward_common_lower).
  • Declare set_davg_zero / set_stddev_constant as class-default stat flags on the descriptor block bases (extended to make_base_descriptor's BD base after ratifying that merge_env_stat's real contract is Union[Descriptor, DescriptorBlock], not "blocks only").
  • Drop the dead-defensive has_message_passing / has_default_fparam probes now that both are already declared on the base — call directly.
  • Declare tebd_compress / type_embd_data compression slots in the tebd family __init__s (dpa1 / se_atten_v2 / se_t_tebd + blocks), including a follow-up fix that defuses a register_buffer trap for the DPA2 tebd compression slot.

Every promotion ships a dual-branch (default + override) universal-suite assertion; pair_excl ships a construction-path assertion instead.

Closes #5897

Known limitations

  • pd (Paddle) edits are verified by py_compile only — no local Paddle install to run its test suite.
  • CUDA fused-kernel consumers of get_geo_compress() and graph .pt2 export/AOTI paths are untested on this CPU-only box; GPU validation before merge is advisable.
  • No dedicated jax DeepEval charge-spin unit test (the jax infer/deep_eval.py charge-spin path is a one-line delegation, exercised only indirectly).
  • The native-spin pair-exclusion folding branch of SpinModel.forward_common_lower (pair_exclude_types set on a native spin model) is untested — no existing test sets it on a spin model.
  • DescrptDPA2.get_geo_compress()'s True branch is unpinned: no DPA2 compression test exists at all (pre-existing gap, not introduced here).
  • The atom_excl getattr probes (e.g. deepmd/kernels/cuda/dpa1/canonical.py:44) are the same duck-typing pattern but were never part of Promote remaining duck-typed attribute probes (add_chg_spin_ebd, geo_compress, reinit_exclude) to base-class interfaces #5897's inventory — candidate follow-up issue, not addressed here.
  • torch.compile-gated training paths are skipped on this box (torch 2.10/2.11 environment); a handful of .pt2 graph-freeze tests (test_dpa4_export.py, test_dpa4_zbl_parallel.py, test_graph_export_with_comm.py, test_zbl_bridging.py) fail with a torch inductor CPU codegen AssertionError (atomic_add store on a non-vectorized index) — confirmed pre-existing on a clean upstream/master worktree, unrelated to this branch's changes.
  • Hybrid descriptors' add_chg_spin_ebd now derives from get_dim_chg_spin() > 0 (rather than the previous getattr-probe), so a hybrid descriptor with a chg-spin-capable child now actually conditions on it, where it previously never did. This is a latent-bug fix surfaced by the promotion, not an intentional feature change — it has no dedicated end-to-end test.
  • The DeepEval facade's get_var_name() / get_intensive() now return None / False for live non-property models instead of raising NotImplementedError, matching the concrete-default contract on make_base_model. Callers that relied on the exception (if any exist outside this repo) would need to switch to checking the return value.
  • jax's and tf2's merge_env_stat multi-task path (multiple descriptors sharing stats across sub-models) has no dedicated unit test; only the single-task path is covered.
  • pd (Paddle)'s has_default_chg_spinget_default_chg_spin interface merge (completing the promotion started elsewhere in the branch) was verified by python -m py_compile only — no Paddle install on this box to run pd's test suite.

Summary by CodeRabbit

  • New Features
    • Added APIs for geometric compression status, property metadata, and excluded atom-type pairs.
    • Added safer atom-type exclusion reconfiguration where supported.
  • Improvements
    • Standardized charge/spin capability detection across model backends.
    • Improved serialization of compressed descriptors and optional model capabilities.
  • Bug Fixes
    • Corrected charge/spin default detection and pair-exclusion handling.
    • Improved compatibility when loading and exporting models with differing capabilities.
  • API Changes
    • Replaced the separate charge/spin default check with availability based on returned default values.

Han Wang added 12 commits August 11, 2026 20:18
…ling#5897)

merge_env_stat's base_obj/link_obj can be a bare Descriptor (se_e2_a,
se_r, se_t) as well as a DescriptorBlock, so the same concrete
defaults are also declared on make_base_descriptor's BD base -
otherwise direct attribute access crashes for descriptors that never
set set_stddev_constant themselves.
…ling#5897)

Declare type_embd_data/tebd_compress in the tebd-family descriptor
__init__s (DescrptDPA1, DescrptBlockSeAtten, DescrptSeTTebd) so their
presence is a class property rather than a runtime accident. Convert
the three self-probes (hasattr(self, "type_embd_data")) to the
equivalent self.type_embd_data is not None check.

Fix a regression this uncovers in pt_expt: DescrptDPA1/DescrptSeTTebd
compression paths call torch.nn.Module.register_buffer(self,
"type_embd_data", ...) directly, bypassing dpmodel_setattr's
existing None-slot-to-buffer promotion. Add
register_buffer_replacing_slot() in pt_expt/common.py mirroring that
existing idiom, and use it at both call sites.

Add a negative-assertion test pinning that a non-tebd descriptor
(DescrptSeA) never carries either attribute, since the jax restore
walker uses hasattr(obj, "tebd_compress") as a family-membership
test.
deepmd/pt_expt/descriptor/dpa2.py:_store_type_embd_data still called
torch.nn.Module.register_buffer(self, "type_embd_data", ...) directly,
the same raw pattern fixed for dpa1/se_t_tebd in the previous commit.
DescrptDPA2 (dpmodel) doesn't declare the type_embd_data slot yet, so
this was purely defensive, but it removes the landmine for whichever
future change declares it there. Swap to the existing
register_buffer_replacing_slot() helper in pt_expt/common.py.
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa90369e-668d-4b55-933a-a04404dee78b

📥 Commits

Reviewing files that changed from the base of the PR and between eef5ab1 and 7ac154b.

📒 Files selected for processing (6)
  • deepmd/jax/jax2tf/tfmodel.py
  • source/jax2tf_tests/test_serialization.py
  • source/tests/common/dpmodel/test_pair_exclude_contract.py
  • source/tests/common/dpmodel/test_zbl_bridging.py
  • source/tests/universal/common/cases/atomic_model/utils.py
  • source/tests/universal/common/cases/fitting/utils.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • source/tests/common/dpmodel/test_pair_exclude_contract.py
  • source/tests/universal/common/cases/atomic_model/utils.py
  • source/tests/common/dpmodel/test_zbl_bridging.py
  • source/tests/universal/common/cases/fitting/utils.py
  • source/jax2tf_tests/test_serialization.py

📝 Walkthrough

Walkthrough

The PR replaces optional capability probes with explicit interfaces, removes has_default_chg_spin, standardizes pair-exclusion access, initializes descriptor compression state, and updates runtime integrations and tests across supported backends.

Changes

Capability contract standardization

Layer / File(s) Summary
Base capability interfaces
deepmd/dpmodel/atomic_model/*, deepmd/dpmodel/descriptor/*, deepmd/dpmodel/fitting/*, deepmd/dpmodel/model/*, deepmd/pd/model/*
Base classes now define charge-spin, property, geometric-compression, fitting-exclusion, pair-exclusion, compression-state, and statistics APIs.
Runtime capability routing
deepmd/dpmodel/model/*, deepmd/jax/*, deepmd/pd/*, deepmd/pt_expt/*, deepmd/tf2/*, deepmd/kernels/*
Execution paths now use direct capability methods and pair-exclusion access instead of optional attribute probes.
Inference and serialization metadata
deepmd/infer/*, deepmd/jax/*, deepmd/pd/*, deepmd/pt_expt/*, deepmd/tf2/*
Inference, synthetic inputs, graph construction, and artifact serialization use declared model capabilities with artifact-boundary compatibility checks.
Capability contract validation
source/tests/common/*, source/tests/universal/*, source/tests/infer/*, source/tests/pt_expt/*, source/jax2tf_tests/*
Tests cover capability defaults, compression state, pair exclusions, fitting exclusions, property metadata, and charge-spin default retrieval.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR covers most of #5897, but the summary shows no declaration of family-local tebd_compress or standardized trainable default. Add or verify the family-local tebd_compress declaration and standardize the trainable default, with corresponding tests.
Docstring Coverage ⚠️ Warning Docstring coverage is 64.03% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing duck-typed capability probes with base-class interfaces.
Out of Scope Changes check ✅ Passed The changes and tests stay within the linked issue scope for capability interfaces, direct access, serialization, and related contract coverage.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deepmd/dpmodel/fitting/make_base_fitting.py`:
- Around line 70-93: Update the reinit_exclude method signature to use None
instead of a mutable list default, while preserving the existing truthiness
check so no collection initialization is needed.

In `@source/tests/common/dpmodel/test_zbl_bridging.py`:
- Around line 399-401: Update the assertion comparing get_default_chg_spin() in
the bridged and plain models to compare the returned values directly, rather
than only comparing whether they are non-None, so the test validates the
forwarded default value.

In `@source/tests/universal/common/cases/atomic_model/utils.py`:
- Around line 105-108: Update the assertions around get_pair_exclude_types and
pair_excl to verify the configured excluded-pair values, not only whether both
representations are empty or nonempty. When self.module.pair_excl is present,
compare its mask configuration against pet; retain the existing empty-state
invariant for the None case.

In `@source/tests/universal/common/cases/fitting/utils.py`:
- Around line 111-116: Update the override branch in the fitting test around
reinit_exclude so the final reinit_exclude([]) call asserts that
self.module.exclude_types is empty, verifying the reset clears the prior [0]
exclusion.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0fe30b62-e608-491e-aebf-98408f25a5ad

📥 Commits

Reviewing files that changed from the base of the PR and between bc902da and cca4eb9.

📒 Files selected for processing (54)
  • deepmd/dpmodel/atomic_model/base_atomic_model.py
  • deepmd/dpmodel/atomic_model/dp_atomic_model.py
  • deepmd/dpmodel/atomic_model/linear_atomic_model.py
  • deepmd/dpmodel/descriptor/descriptor.py
  • deepmd/dpmodel/descriptor/dpa1.py
  • deepmd/dpmodel/descriptor/dpa2.py
  • deepmd/dpmodel/descriptor/dpa3.py
  • deepmd/dpmodel/descriptor/dpa4.py
  • deepmd/dpmodel/descriptor/hybrid.py
  • deepmd/dpmodel/descriptor/make_base_descriptor.py
  • deepmd/dpmodel/descriptor/se_atten_v2.py
  • deepmd/dpmodel/descriptor/se_t_tebd.py
  • deepmd/dpmodel/fitting/make_base_fitting.py
  • deepmd/dpmodel/model/base_model.py
  • deepmd/dpmodel/model/make_model.py
  • deepmd/dpmodel/model/spin_model.py
  • deepmd/dpmodel/utils/env_mat_stat.py
  • deepmd/infer/deep_eval.py
  • deepmd/jax/infer/deep_eval.py
  • deepmd/jax/jax2tf/serialization.py
  • deepmd/jax/jax_md/__init__.py
  • deepmd/jax/train/trainer.py
  • deepmd/jax/utils/serialization.py
  • deepmd/kernels/cuda/dpa1/canonical.py
  • deepmd/pd/infer/deep_eval.py
  • deepmd/pd/model/atomic_model/dp_atomic_model.py
  • deepmd/pd/model/descriptor/descriptor.py
  • deepmd/pd/model/descriptor/dpa2.py
  • deepmd/pt_expt/common.py
  • deepmd/pt_expt/descriptor/dpa1.py
  • deepmd/pt_expt/descriptor/dpa2.py
  • deepmd/pt_expt/descriptor/repflows.py
  • deepmd/pt_expt/descriptor/se_t_tebd.py
  • deepmd/pt_expt/infer/deep_eval.py
  • deepmd/pt_expt/model/make_model.py
  • deepmd/pt_expt/train/training.py
  • deepmd/pt_expt/utils/network.py
  • deepmd/pt_expt/utils/serialization.py
  • deepmd/tf2/model/dp_model.py
  • deepmd/tf2/train/trainer.py
  • deepmd/tf2/utils/serialization.py
  • source/tests/common/dpmodel/test_descriptor_block_defaults.py
  • source/tests/common/dpmodel/test_descriptor_dpa1.py
  • source/tests/common/dpmodel/test_make_base_fitting.py
  • source/tests/common/dpmodel/test_model_compression.py
  • source/tests/common/dpmodel/test_pair_exclude_contract.py
  • source/tests/common/dpmodel/test_zbl_bridging.py
  • source/tests/infer/gen_dpa4_spin_chgspin.py
  • source/tests/pt_expt/model/test_dpa4_native_spin.py
  • source/tests/universal/common/cases/atomic_model/utils.py
  • source/tests/universal/common/cases/descriptor/utils.py
  • source/tests/universal/common/cases/fitting/utils.py
  • source/tests/universal/common/cases/model/utils.py
  • source/tests/universal/dpmodel/descriptor/test_descriptor.py
💤 Files with no reviewable changes (3)
  • deepmd/dpmodel/descriptor/dpa3.py
  • deepmd/dpmodel/descriptor/dpa4.py
  • deepmd/pd/model/descriptor/dpa2.py

Comment thread deepmd/dpmodel/fitting/make_base_fitting.py
Comment thread source/tests/common/dpmodel/test_zbl_bridging.py Outdated
Comment thread source/tests/universal/common/cases/atomic_model/utils.py
Comment thread source/tests/universal/common/cases/fitting/utils.py
Han Wang and others added 8 commits August 12, 2026 09:19
get_pair_exclude_types() was declared only on dpmodel's concrete
BaseAtomicModel, not on the shared make_base_atomic_model() factory that
pt's atomic models also derive from (via make_base_atomic_model(torch.Tensor)).
The universal test_pair_exclude_contract case runs for pt too, so it hit
AttributeError there.

pt atomic models already set self.pair_exclude_types in __init__ via
reinit_pair_exclude (deepmd/pt/model/atomic_model/base_atomic_model.py),
so the accessor is safe to declare once, concretely, on the BAM base.
The shared universal descriptor/model cases asserted
'not hasattr(type(self.module), "has_default_chg_spin")', which fails
for the frozen pt backend: pt still declares the (now-redundant) method
on 8 descriptors + make_model, which is allowed since pt is frozen.

Move the negative assertion out of the shared case methods (which run
for every backend) into dpmodel-only test files, where the merge is
authoritative: TestHasDefaultChgSpinAbsentDP in
source/tests/universal/dpmodel/descriptor/test_descriptor.py and
source/tests/universal/dpmodel/model/test_model.py, asserting absence on
both the BD/base_model bases and the concrete dpmodel classes.
hasattr(model, "get_var_name") is always true now that make_base_model
declares the method with a concrete None default, so the tf2 SavedModel
export unconditionally exported a get_var_name/get_task_dim/get_intensive
tf.function trio for every model, including non-property models (where
get_var_name() returns None and get_task_dim() would raise).

Mirror the jax2tf pattern (deepmd/jax/jax2tf/serialization.py): gate on
'model.get_var_name() is not None' instead.
…erge

pd retained a divergent has_default_chg_spin chain (base_atomic_model,
dp_atomic_model, make_model, and the se_a/dpa1/dpa3/se_t_tebd descriptors)
after its DPA2 override was already dropped elsewhere, and after the rest
of the codebase merged has_default_chg_spin into get_default_chg_spin
(predicate: get_default_chg_spin() is not None).

Delete the has_default_chg_spin definitions and rewrite
DPAtomicModel.get_default_chg_spin to the dpmodel pattern (gate purely on
add_chg_spin_ebd, not an extra has_default_chg_spin probe on the
descriptor). Convert the one caller (pd/train/training.py) to the
'get_default_chg_spin() is not None' predicate, matching pt_expt's
get_additional_data_requirement.

Paddle is not installed locally; every edited file was verified with
'python -m py_compile' and a repo-wide grep confirms zero remaining
has_default_chg_spin references under deepmd/pd/.
…p_eval

- SpinModel.forward_common_lower's else branch (backbone_model without a
  nested .atomic_model) used getattr(self.backbone_model, "pair_excl", None).
  Per the __init__ annotation, backbone_model in that branch IS a
  DPAtomicModel, whose BaseAtomicModel.__init__ unconditionally sets
  self.pair_excl via reinit_pair_exclude -- so this is a guaranteed
  attribute, not one to defensively probe.
- pt_expt's model_type property called self._dpmodel.get_var_name() twice
  in the same elif condition; hoist to a single local variable alongside
  model_output_type, set to None in the metadata-only branch.
…e descriptor

Extends test_descriptor_block_defaults.py (Task 6's rationale: BD base in
make_base_descriptor was extended with set_davg_zero/set_stddev_constant
class defaults after ratifying that merge_env_stat's real contract is
Union[Descriptor, DescriptorBlock], not "blocks only"):

- test_base_descriptor_stat_flags_have_class_defaults: pins the BD base
  class defaults directly (mirrors the existing DescriptorBlock test).
- test_merge_env_stat_on_bare_descriptor_no_attribute_error: constructs a
  bare DescrptSeA (not a DescriptorBlock), runs compute_input_stats, and
  calls merge_env_stat on it -- proving no AttributeError when reading
  the stat-behavior flags on a Descriptor that never sets them itself.
…ility contracts

The frozen pt backend returns torch.Tensor from get_default_chg_spin while
dpmodel returns a list; the shared universal assertion must be
backend-agnostic. Asserting len(dcs) == get_dim_chg_spin() is also the
stronger contract.
@wanghan-iapcm
wanghan-iapcm requested a review from njzjz August 12, 2026 02:58
DummyModel (jax2tf serialization test) gains get_var_name -> None; the
_DescriptorWithStats stub gains the stat-flag class defaults that
merge_env_stat now reads directly.
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.68142% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.39%. Comparing base (bc902da) to head (7ac154b).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
deepmd/pt_expt/infer/deep_eval.py 41.66% 7 Missing ⚠️
deepmd/jax/jax2tf/serialization.py 33.33% 4 Missing ⚠️
deepmd/pd/infer/deep_eval.py 0.00% 3 Missing ⚠️
deepmd/pd/train/training.py 0.00% 3 Missing ⚠️
deepmd/tf2/train/trainer.py 0.00% 3 Missing ⚠️
deepmd/tf2/utils/serialization.py 40.00% 3 Missing ⚠️
deepmd/dpmodel/model/base_model.py 83.33% 2 Missing ⚠️
deepmd/jax/infer/deep_eval.py 33.33% 2 Missing ⚠️
deepmd/kernels/cuda/dpa1/canonical.py 0.00% 2 Missing ⚠️
deepmd/dpmodel/descriptor/se_t_tebd.py 50.00% 1 Missing ⚠️
... and 2 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5967      +/-   ##
==========================================
- Coverage   79.60%   79.39%   -0.22%     
==========================================
  Files        1085     1085              
  Lines      126405   126579     +174     
  Branches     4598     4598              
==========================================
- Hits       100631   100503     -128     
- Misses      24120    24423     +303     
+ Partials     1654     1653       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread deepmd/jax/infer/deep_eval.py

@njzjz-bot njzjz-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed independently from correctness, compatibility/testing, and maintainability perspectives. One actionable issue was found; the other two independent reviews found no additional issues.

Coding agent: Codex
Codex version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning effort: xhigh

Comment thread deepmd/jax/infer/deep_eval.py
- TFModelWrapper: normalize the exported empty default-chg-spin tensor
  to None at the artifact-decode boundary (its one owner), so the
  live-model invariant `get_default_chg_spin() is None == no default`
  holds for SavedModel artifacts too and the jax DeepEval predicate
  stays a plain `is not None`. Pure decode helper + two-branch test.
- test_zbl_bridging: compare the forwarded default chg-spin VALUES,
  not just their None-ness.
- universal atomic-model case: when pair_excl exists, its mask must
  hold exactly the symmetric closure of get_pair_exclude_types()
  (both backends symmetrize on reinit; compared as sets of tuples
  because pt stores a set and dpmodel a list). The closure form is
  pinned by test_pair_exclude_contract on a (0,1)-only config.
- universal fitting case: assert reinit_exclude([]) actually clears
  exclude_types on the override branch.

@njzjz-bot njzjz-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head 7ac154b with three independent passes covering correctness, multi-backend and serialization compatibility, and API and test contracts, followed by consolidated local verification and deduplication against existing review threads.

No new high-confidence actionable findings were found on the current diff, so there are no inline comments to attach.

Validation notes: targeted current-head tests for the new fitting, pair-exclusion, compression, and JAX SavedModel charge-spin decode contracts passed; Ruff passed on the changed backend trees. The remaining Paddle C++ CI failure is an external partial-download failure and is not attributable to this PR.

Coding agent: Codex
Codex version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning effort: xhigh

@njzjz-bot njzjz-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved after three independent review passes and consolidated verification of the current head 7ac154b. No new high-confidence actionable findings were identified.

Coding agent: Codex
Codex version: codex-cli 0.144.6
Model: gpt-5.6-sol
Reasoning effort: xhigh

@njzjz
njzjz enabled auto-merge August 12, 2026 16:56
@njzjz
njzjz added this pull request to the merge queue Aug 12, 2026
Merged via the queue into deepmodeling:master with commit adbd6bc Aug 12, 2026
62 of 63 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Promote remaining duck-typed attribute probes (add_chg_spin_ebd, geo_compress, reinit_exclude) to base-class interfaces

3 participants